@intentius/chant 0.102.0 → 0.104.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/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/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/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/fan-out.d.ts +33 -0
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +7 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/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/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.d.ts +3 -2
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +63 -1
- package/dist/cli/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.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/verbs/shell.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/gated-waves.d.ts +147 -0
- package/dist/gated-waves.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +48 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +7 -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/lint/post-synth.d.ts +18 -0
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.d.ts +126 -0
- package/dist/op/activities/activity-contracts.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 +4 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activity-contract.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/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/factory.d.ts +83 -0
- package/dist/op/factory.d.ts.map +1 -0
- package/dist/op/index.d.ts +4 -1
- package/dist/op/index.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/types.d.ts +8 -0
- package/dist/op/types.d.ts.map +1 -1
- 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/telemetry-attribution.d.ts +31 -0
- package/dist/telemetry-attribution.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/vendor/js-yaml-load.d.ts +56 -0
- package/dist/vendor/js-yaml-load.d.ts.map +1 -0
- 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 +27 -3
- package/dist/workspace/box-factory.d.ts.map +1 -1
- 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/checks.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 +2 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/vitest.d.ts +9 -2
- package/dist/workspace/conformance/vitest.d.ts.map +1 -1
- package/dist/workspace/conformance/writer.d.ts +108 -14
- package/dist/workspace/conformance/writer.d.ts.map +1 -1
- 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 +65 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +153 -4
- 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/init.d.ts +21 -0
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/intent-cli.d.ts +1 -1
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-record.d.ts +28 -1
- package/dist/workspace/intent-record.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts +102 -5
- 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 +48 -0
- 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-upgrade.d.ts +31 -2
- package/dist/workspace/lineage-upgrade.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/reason-codes.d.ts +33 -4
- package/dist/workspace/reason-codes.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-cli.d.ts +7 -0
- 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-write.d.ts +66 -6
- package/dist/workspace/records-write.d.ts.map +1 -1
- package/dist/workspace/records.d.ts +28 -9
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/runs-cli.d.ts +138 -6
- package/dist/workspace/runs-cli.d.ts.map +1 -1
- package/dist/workspace/runs.d.ts +132 -11
- package/dist/workspace/runs.d.ts.map +1 -1
- package/dist/workspace/session-kinds.d.ts +1 -1
- package/dist/workspace/session-kinds.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 +2 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +54 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/symbols.d.ts +16 -5
- package/dist/workspace/symbols.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 +6 -1
- package/dist/workspace/trust/seal.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.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/workspace-kinds.schema.json +122 -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 +6 -2
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/yaml.d.ts +1 -1
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +6 -1
- 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/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/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/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/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/operator.test.ts +21 -0
- package/src/cli/handlers/operator.ts +34 -3
- package/src/cli/handlers/pr.ts +373 -0
- package/src/cli/handlers/run.ts +1 -0
- package/src/cli/main.test.ts +20 -0
- package/src/cli/main.ts +185 -23
- 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 +1 -1
- package/src/cli/mcp/workspace-tools.ts +34 -6
- package/src/cli/registry.ts +63 -1
- 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/discovery/sandbox/bundle.ts +1 -1
- 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/index.ts +1 -0
- package/src/lexicon.ts +51 -0
- package/src/lifecycle/gate-ledger.ts +7 -0
- package/src/lifecycle/git.ts +102 -16
- 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/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 +6 -0
- 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/decide-backend.ts +5 -1
- package/src/op/decide-read-inputs.ts +33 -5
- package/src/op/factory.e2e.test.ts +232 -0
- package/src/op/factory.ts +118 -0
- package/src/op/index.ts +9 -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/types.ts +8 -0
- package/src/op/work-lease-run.ts +3 -0
- 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/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/vendor/js-yaml-load.test.ts +115 -0
- package/src/vendor/js-yaml-load.ts +1939 -0
- package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
- package/src/workspace/app-kind.test.ts +196 -0
- package/src/workspace/box-cli.ts +113 -0
- package/src/workspace/box-factory.test.ts +4 -1
- package/src/workspace/box-factory.ts +37 -4
- 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/chant-migrations.e2e.test.ts +17 -5
- package/src/workspace/checks/boxes.test.ts +3 -0
- package/src/workspace/checks.ts +10 -3
- package/src/workspace/component-environments.test.ts +105 -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 +7 -2
- package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +42 -2
- 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 +96 -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 +14 -8
- package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +187 -6
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +25 -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 +2 -1
- package/src/workspace/conformance/index.mjs +22 -1
- package/src/workspace/conformance/index.ts +5 -1
- package/src/workspace/conformance/vitest.ts +33 -1
- package/src/workspace/conformance/writer-conformance.e2e.test.ts +49 -3
- package/src/workspace/conformance/writer.test.ts +32 -2
- package/src/workspace/conformance/writer.ts +339 -28
- package/src/workspace/decide.test.ts +208 -4
- package/src/workspace/decide.ts +427 -73
- package/src/workspace/decision-points.schema.json +11 -4
- package/src/workspace/declaration.schema.json +153 -4
- package/src/workspace/declaration.ts +141 -0
- 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 +2 -2
- package/src/workspace/graph.schema.json +67 -0
- package/src/workspace/identity.test.ts +23 -0
- package/src/workspace/init.ts +82 -2
- package/src/workspace/intent-cli.ts +26 -9
- package/src/workspace/intent-patch-id.test.ts +162 -0
- package/src/workspace/intent-record.schema.json +130 -3
- package/src/workspace/intent-record.ts +74 -28
- 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 +5 -5
- package/src/workspace/intent.schema.json +234 -4
- package/src/workspace/intent.ts +260 -66
- 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 +157 -2
- 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 +162 -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/profiles.test.ts +159 -0
- package/src/workspace/read-contract.test.ts +2 -2
- package/src/workspace/reason-codes.test.ts +13 -1
- package/src/workspace/reason-codes.ts +38 -4
- package/src/workspace/record-sessions.ts +9 -8
- package/src/workspace/records-amend.schema.json +78 -0
- package/src/workspace/records-cli.ts +20 -6
- package/src/workspace/records-close.schema.json +78 -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 +7 -0
- package/src/workspace/records-review.schema.json +78 -0
- package/src/workspace/records-sessions-write.test.ts +69 -0
- package/src/workspace/records-sessions.test.ts +22 -0
- package/src/workspace/records-write.ts +192 -25
- package/src/workspace/records.schema.json +16 -0
- package/src/workspace/records.ts +50 -9
- 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 +343 -14
- package/src/workspace/runs-statement.test.ts +239 -0
- package/src/workspace/runs-write.schema.json +416 -5
- package/src/workspace/runs.schema.json +451 -4
- package/src/workspace/runs.test.ts +39 -0
- package/src/workspace/runs.ts +296 -35
- package/src/workspace/session-kinds.ts +3 -3
- package/src/workspace/squash.ts +198 -0
- package/src/workspace/status-contract.test.ts +5 -2
- package/src/workspace/status-gates.ts +3 -1
- package/src/workspace/status.schema.json +126 -3
- package/src/workspace/status.ts +90 -1
- package/src/workspace/symbols.ts +20 -9
- package/src/workspace/trust/run-commits.ts +115 -0
- package/src/workspace/trust/run-statement.ts +226 -0
- package/src/workspace/trust/seal.ts +8 -2
- 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.ts +3 -0
- package/src/workspace/work-evidence.schema.json +3 -0
- package/src/workspace/work-size.test.ts +77 -0
- package/src/workspace/work-size.ts +93 -0
- package/src/workspace/workspace-kinds.schema.json +122 -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 +16 -1
- package/src/workspace/write-scope.ts +33 -11
- package/src/yaml.ts +31 -21
package/src/cli/main.ts
CHANGED
|
@@ -347,6 +347,30 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
347
347
|
result.fromAffected = args[++i];
|
|
348
348
|
} else if (arg === "--gate") {
|
|
349
349
|
result.gate = args[++i];
|
|
350
|
+
} else if (arg === "--wave-gate") {
|
|
351
|
+
result.waveGate = args[++i];
|
|
352
|
+
if (!result.waveGate || result.waveGate.startsWith("-")) throw new Error("--wave-gate needs a gate name: --wave-gate <name>");
|
|
353
|
+
} else if (arg === "--wave") {
|
|
354
|
+
const raw = args[++i];
|
|
355
|
+
const wave = Number(raw);
|
|
356
|
+
if (!Number.isInteger(wave) || wave < 1) throw new Error(`--wave needs a wave number from 1: got "${raw ?? ""}"`);
|
|
357
|
+
result.wave = wave;
|
|
358
|
+
} else if (arg === "--canary") {
|
|
359
|
+
const raw = args[++i];
|
|
360
|
+
if (!raw || raw.startsWith("-")) throw new Error("--canary needs a component name: --canary <name>[,<name>...]");
|
|
361
|
+
(result.canary ??= []).push(...raw.split(",").map((n) => n.trim()).filter(Boolean));
|
|
362
|
+
} else if (arg === "--pr") {
|
|
363
|
+
const raw = args[++i];
|
|
364
|
+
const pr = Number(raw);
|
|
365
|
+
if (!Number.isInteger(pr) || pr < 1) throw new Error(`--pr needs a pull or merge request number: got "${raw ?? ""}"`);
|
|
366
|
+
result.pr = pr;
|
|
367
|
+
} else if (arg === "--forge") {
|
|
368
|
+
result.forge = args[++i];
|
|
369
|
+
if (!result.forge || result.forge.startsWith("-")) throw new Error("--forge needs a forge: --forge github|gitlab|forgejo");
|
|
370
|
+
} else if (arg === "--require-review") {
|
|
371
|
+
result.requireReview = true;
|
|
372
|
+
} else if (arg === "--pr-loop") {
|
|
373
|
+
result.prLoop = true;
|
|
350
374
|
} else if (arg === "--resume") {
|
|
351
375
|
result.resume = args[++i];
|
|
352
376
|
} else if (arg === "--local") {
|
|
@@ -389,6 +413,9 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
389
413
|
if (value !== undefined && !value.startsWith("-")) result.intent = args[++i];
|
|
390
414
|
else if (args.includes("--record")) result.intent = "";
|
|
391
415
|
else throw new Error("--intent needs a region: --intent <path[:start-end]|path#symbol>, or --intent --record <id>");
|
|
416
|
+
} else if (arg === "--follow-squash") {
|
|
417
|
+
// `chant workspace graph --intent ... --follow-squash` and `chant workspace runs --follow-squash` (#3035)
|
|
418
|
+
result.followSquash = true;
|
|
392
419
|
} else if (arg === "--record") {
|
|
393
420
|
// `chant workspace graph --intent --record <id>`
|
|
394
421
|
result.record = args[++i];
|
|
@@ -423,6 +450,29 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
423
450
|
// `chant workspace records amend <id> --set <file|->` (#2670)
|
|
424
451
|
result.set = args[++i];
|
|
425
452
|
if (!result.set || (result.set.startsWith("-") && result.set !== "-")) throw new Error("--set needs a JSON file, or - for standard input: --set <file|->");
|
|
453
|
+
} else if (arg === "--cover") {
|
|
454
|
+
// `chant workspace box listing set <member> --cover <image>` (#3308)
|
|
455
|
+
result.cover = args[++i];
|
|
456
|
+
if (!result.cover || result.cover.startsWith("-")) throw new Error("--cover needs a PNG, JPEG or WebP file: --cover <image>");
|
|
457
|
+
} else if (arg === "--cover-path") {
|
|
458
|
+
// `chant workspace box listing set <member> --cover <image> --cover-path <path>` (#3308)
|
|
459
|
+
result.coverPath = args[++i];
|
|
460
|
+
if (!result.coverPath || result.coverPath.startsWith("-")) throw new Error("--cover-path needs a path from the workspace root: --cover-path <path>");
|
|
461
|
+
} else if (arg === "--records") {
|
|
462
|
+
// `chant workspace box publish <member> --records` (#3165): the records kept uncommitted, not a work item.
|
|
463
|
+
result.records = true;
|
|
464
|
+
} else if (arg === "--expect") {
|
|
465
|
+
// `chant workspace records amend|review|close <id> --expect <digest>` (#3173): the record's digest the caller last read.
|
|
466
|
+
result.expect = args[++i];
|
|
467
|
+
if (!result.expect || result.expect.startsWith("-")) throw new Error("--expect needs the record's digest, as records --json prints it: --expect <digest>");
|
|
468
|
+
} else if (arg === "--label") {
|
|
469
|
+
// `chant workspace wip save --label <text>` (#3172)
|
|
470
|
+
result.label = args[++i];
|
|
471
|
+
if (!result.label || result.label.startsWith("-")) throw new Error("--label needs the snapshot's name, such as a turn id: --label <text>");
|
|
472
|
+
} else if (arg === "--branch") {
|
|
473
|
+
// `chant workspace wip --branch <branch>` (#3172)
|
|
474
|
+
result.branch = args[++i];
|
|
475
|
+
if (!result.branch || result.branch.startsWith("-")) throw new Error("--branch needs a branch name: --branch <branch>");
|
|
426
476
|
} else if (arg === "--verdict") {
|
|
427
477
|
// `chant workspace records review <id> --verdict agree|dissent|abstain` (#2670)
|
|
428
478
|
result.verdict = args[++i];
|
|
@@ -437,9 +487,13 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
437
487
|
// `chant workspace points --open` (#2739): only the questions still open.
|
|
438
488
|
result.open = true;
|
|
439
489
|
} else if (arg === "--inputs") {
|
|
440
|
-
// `chant workspace points ask <point> --inputs <file
|
|
490
|
+
// `chant workspace points ask <point> --inputs <file|-|json>` (#2739; JSON itself, #3403)
|
|
441
491
|
result.inputs = args[++i];
|
|
442
|
-
if (!result.inputs || (result.inputs.startsWith("-") && result.inputs !== "-")) throw new Error("--inputs needs a JSON file,
|
|
492
|
+
if (!result.inputs || (result.inputs.startsWith("-") && result.inputs !== "-")) throw new Error("--inputs needs a JSON file, - for standard input, or the JSON itself: --inputs <file|-|json>");
|
|
493
|
+
} else if (arg === "--candidates") {
|
|
494
|
+
// `chant workspace points ask <point> --candidates <file|-|json>` (#3403): an ad-hoc point's question and candidates.
|
|
495
|
+
result.candidates = args[++i];
|
|
496
|
+
if (!result.candidates || (result.candidates.startsWith("-") && result.candidates !== "-")) throw new Error("--candidates needs a JSON file, - for standard input, or the JSON itself: --candidates <file|-|json>");
|
|
443
497
|
} else if (arg === "--response") {
|
|
444
498
|
// `chant workspace points ask <point> --response <file>` (#2739): a POST /v1/systemone response the caller got.
|
|
445
499
|
result.response = args[++i];
|
|
@@ -508,6 +562,11 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
508
562
|
result.actor = args[++i];
|
|
509
563
|
} else if (arg === "--approver") {
|
|
510
564
|
result.approver = args[++i];
|
|
565
|
+
} else if (arg === "--relayed-by") {
|
|
566
|
+
// `chant approve <op> <gate> --relayed-by <principal>` and `workspace points answer <id> --relayed-by <principal>` (#3402):
|
|
567
|
+
// who carried the approval or answer to chant for the person it names.
|
|
568
|
+
result.relayedBy = args[++i];
|
|
569
|
+
if (!result.relayedBy || result.relayedBy.startsWith("-")) throw new Error("--relayed-by needs the principal that relayed it: --relayed-by <principal>");
|
|
511
570
|
} else if (arg === "--on") {
|
|
512
571
|
// `chant run ... --on <lexicon>` (#2121) — which runtime hosts the run.
|
|
513
572
|
result.on = args[++i];
|
|
@@ -577,6 +636,11 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
577
636
|
const value = args[++i];
|
|
578
637
|
if (!value || value.startsWith("-")) throw new Error(`${arg} needs a value: ${arg} <${arg.slice(2)}>`);
|
|
579
638
|
result[arg.slice(2) as "holder" | "ttl" | "token" | "outcome"] = value;
|
|
639
|
+
} else if (arg === "--signer") {
|
|
640
|
+
// `chant workspace runs statement <id> --signer <principal>` (#3192): the runner principal that will sign.
|
|
641
|
+
const value = args[++i];
|
|
642
|
+
if (!value || value.startsWith("-")) throw new Error("--signer needs a principal: --signer <principal>");
|
|
643
|
+
result.signer = value;
|
|
580
644
|
} else if (arg === "--unit" || arg === "--decision") {
|
|
581
645
|
// `chant workspace runs --unit <id> | --decision <id>` (#3033): the runs on one work item, or for one decision.
|
|
582
646
|
const value = args[++i];
|
|
@@ -659,6 +723,7 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
659
723
|
// flags" isn't something this loop can name in isolation.
|
|
660
724
|
throw new Error(`Unknown flag: ${arg}\nRun "chant --help" to see supported flags.`);
|
|
661
725
|
} else if (!arg.startsWith("-")) {
|
|
726
|
+
if (result.command) (result.positionals ??= []).push(arg);
|
|
662
727
|
if (!result.command) {
|
|
663
728
|
result.command = arg;
|
|
664
729
|
} else if (result.path === ".") {
|
|
@@ -777,6 +842,14 @@ Commands:
|
|
|
777
842
|
(--json) its target, stage (planned/emitted/bridged/
|
|
778
843
|
applied) and path. Read-only.
|
|
779
844
|
|
|
845
|
+
Change sets:
|
|
846
|
+
change-set summary <file> The grouped plan summary of a change-set
|
|
847
|
+
[--format text|json|markdown] document: members taking
|
|
848
|
+
[--limit <chars>] the same change grouped, every destroy,
|
|
849
|
+
replacement, failure and hole named.
|
|
850
|
+
markdown fits an MR/PR note of --limit
|
|
851
|
+
characters (default 65536). Read-only.
|
|
852
|
+
|
|
780
853
|
Ops:
|
|
781
854
|
run <name> Run an Op on the resolved runtime (--on; local by default)
|
|
782
855
|
[--work <id>] [--holder <name>]: the work item an Op
|
|
@@ -838,7 +911,9 @@ Ops:
|
|
|
838
911
|
--sign [<key file>] seals the approval with an ssh
|
|
839
912
|
key; a gate the workspace's identity.gates names
|
|
840
913
|
counts only an approval sealed by a key the signers
|
|
841
|
-
file at base lists for --actor
|
|
914
|
+
file at base lists for --actor. --relayed-by
|
|
915
|
+
<principal> records who carried the approval to chant
|
|
916
|
+
for --actor (a follower, a bot); --sign covers it
|
|
842
917
|
|
|
843
918
|
graph Show Op dependency graph (--stacks for cross-stack order,
|
|
844
919
|
--format ir|mermaid|dot|layout for the lint-gated graph IR,
|
|
@@ -909,7 +984,7 @@ Workspace (level 1, #2524):
|
|
|
909
984
|
the fields hold none. --sign seals the record's author
|
|
910
985
|
(decided_by for decisions) with an ssh key. Prints
|
|
911
986
|
{path, id} as JSON and never commits
|
|
912
|
-
workspace records amend <id> [--kind <kind file>] --set <file|-> [--sign [<key file>]] [--dry-run]
|
|
987
|
+
workspace records amend <id> [--kind <kind file>] --set <file|-> [--expect <digest>] [--sign [<key file>]] [--dry-run]
|
|
913
988
|
Set top-level fields of one record. A closed record
|
|
914
989
|
never changes, and an approved one changes only its
|
|
915
990
|
state (upward), pins and reviews; anything else is
|
|
@@ -918,21 +993,30 @@ Workspace (level 1, #2524):
|
|
|
918
993
|
decisions) is refused with ratify-quorum-not-met
|
|
919
994
|
until its quorum is met. --sign seals the author
|
|
920
995
|
again; without it an amendment removes the author
|
|
921
|
-
seal and says so.
|
|
922
|
-
|
|
996
|
+
seal and says so. --expect refuses the write with
|
|
997
|
+
record-conflict when the record's digest has moved
|
|
998
|
+
on. Prints {path, id, changed, digest}
|
|
999
|
+
workspace records review <id> [--kind <kind file>] --verdict agree|dissent|abstain --by <principal> [--note <text>] [--session <id>] [--expect <digest>] [--sign [<key file>]] [--dry-run]
|
|
923
1000
|
Append a review to one record, dated and bound to
|
|
924
1001
|
the digest of the record text. A dissent needs
|
|
925
1002
|
--note. --sign seals it with an ssh key (git's
|
|
926
1003
|
user.signingkey without a file); under a signers
|
|
927
1004
|
file at base only a sealed verdict counts. With
|
|
928
1005
|
--session, the session must be open, and the verdict
|
|
929
|
-
is appended to its verdicts too.
|
|
930
|
-
|
|
931
|
-
|
|
1006
|
+
is appended to its verdicts too. --expect refuses a
|
|
1007
|
+
verdict on a record that moved on. Prints
|
|
1008
|
+
{path, id, review, digest}
|
|
1009
|
+
workspace records close <session id> [--kind <session kind file>] [--expect <digest>] [--dry-run]
|
|
932
1010
|
Close an open review session: its state, close time,
|
|
933
1011
|
closing commit and seal, in one write. Without
|
|
934
1012
|
--kind, the one session kind the declaration names.
|
|
935
1013
|
Prints {path, id, changed, seal, closedRev}
|
|
1014
|
+
Every working-tree write holds the working tree's
|
|
1015
|
+
write lock (CHANT_WRITE_LOCK_WAIT_MS, default 15s)
|
|
1016
|
+
workspace lock [acquire --holder <name> [--ttl <duration>] | release --token <token>] [--json]
|
|
1017
|
+
Who holds the working tree's write lock; take it for
|
|
1018
|
+
a batch of writes across chant calls, each run with
|
|
1019
|
+
CHANT_WRITE_LOCK=<token>, and give it back
|
|
936
1020
|
workspace work claim|renew|release <id> --holder <name> [--kind <kind file>] [--ttl <seconds|duration>] [--token <token>] [--outcome <outcome>] [--note <text>] [--json]
|
|
937
1021
|
Take, heartbeat or give back the lease on a work item:
|
|
938
1022
|
refs/chant/lease/work/<id>, a compare-and-set ref with a
|
|
@@ -950,12 +1034,14 @@ Workspace (level 1, #2524):
|
|
|
950
1034
|
a url or a path pinned by hash) is appended to the
|
|
951
1035
|
item's pins through records amend. Prints the
|
|
952
1036
|
work-evidence document and never commits
|
|
953
|
-
workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--json]
|
|
1037
|
+
workspace runs [--unit <id>] [--decision <id>] [--by <principal>] [--since <rev>] [--follow-squash] [--json]
|
|
954
1038
|
The agent runs in the run ledger on chant/lifecycle, each
|
|
955
1039
|
with its model, tokens, cost and the commits it made,
|
|
956
1040
|
and totals per work item, decision and principal; a run
|
|
957
1041
|
that reports no cost is listed as unpriced, never zero.
|
|
958
|
-
Read-only, never fetches
|
|
1042
|
+
Read-only, never fetches; --follow-squash joins each
|
|
1043
|
+
squash merge to its pull request's runs, fetching a
|
|
1044
|
+
missing refs/pull/<n>/head from origin
|
|
959
1045
|
workspace runs start --from <file|->
|
|
960
1046
|
Record that an agent run started: who it worked for,
|
|
961
1047
|
its harness, model, work item and lease. Prints the run
|
|
@@ -966,18 +1052,65 @@ Workspace (level 1, #2524):
|
|
|
966
1052
|
and the commits it made
|
|
967
1053
|
workspace runs record --from <file|->
|
|
968
1054
|
Record a finished run, its start and end in one write
|
|
1055
|
+
workspace runs sign <run id> (--key <runner.pem> | --envelope <file|->) [--base <rev>]
|
|
1056
|
+
Store a DSSE statement over an ended run (its record's
|
|
1057
|
+
hash, work item, harness, model and commits), signed
|
|
1058
|
+
with a runner or steward key .chant/trust.json lists
|
|
1059
|
+
at base, or signed elsewhere and checked here
|
|
1060
|
+
workspace runs statement <run id> --signer <principal>
|
|
1061
|
+
Print the statement for a signer whose key is
|
|
1062
|
+
elsewhere, such as a lobby, with the payload to sign
|
|
1063
|
+
workspace runs verify [<run id>] [--require signed] [--base <rev>] [--json]
|
|
1064
|
+
Judge each run's stored statements against the runner
|
|
1065
|
+
keys at base. Reports only, unless --require signed
|
|
1066
|
+
workspace box listing set <member> [--from <file|->] [--cover <image> [--cover-path <path>]] [--by <principal>] [--dry-run]
|
|
1067
|
+
Change a box's listing (published, title, line, cover)
|
|
1068
|
+
in the declaration, in place, keeping its formatting
|
|
1069
|
+
and comments; --cover copies a PNG, JPEG or WebP into
|
|
1070
|
+
the repository. Judged by the write scope at base.
|
|
1071
|
+
Prints the box-listing-write document; never commits
|
|
1072
|
+
workspace box publish <member> (<item> | --records) [--by <principal>] [--head <owner/name>] [--dry-run]
|
|
1073
|
+
Publish a built work item, or the records kept
|
|
1074
|
+
uncommitted, through the publisher the box block names:
|
|
1075
|
+
run with a JSON request on stdin, its answer checked
|
|
1076
|
+
and its commit held to the apply record (ws-088).
|
|
1077
|
+
Prints the box-publish document; chant itself never
|
|
1078
|
+
commits, pushes or calls a forge
|
|
1079
|
+
workspace wip [--branch <branch>] [--json]
|
|
1080
|
+
List the work-in-progress snapshots under
|
|
1081
|
+
refs/chant/wip/<branch>, newest first, and how far each
|
|
1082
|
+
ref the box's replicate policy names is from its remote.
|
|
1083
|
+
Reads locally; never fetches (#3172)
|
|
1084
|
+
workspace wip save [--label <text>] [--by <principal>]
|
|
1085
|
+
Snapshot the whole working tree, uncommitted records
|
|
1086
|
+
included, onto refs/chant/wip/<branch> without touching
|
|
1087
|
+
the index or the branch; pushes when the policy says so
|
|
1088
|
+
workspace wip restore [<snapshot>] [--by <principal>]
|
|
1089
|
+
Put the working tree back as the snapshot (the branch's
|
|
1090
|
+
latest by default) holds it, after a snapshot of how it
|
|
1091
|
+
is now; HEAD never moves
|
|
1092
|
+
workspace wip push Push the refs the box's replicate policy names to its
|
|
1093
|
+
remote, never forced, for the host's schedule
|
|
1094
|
+
workspace wip fetch On a replacement box, bring back what was replicated:
|
|
1095
|
+
create or fast-forward the local refs, then wip restore
|
|
969
1096
|
workspace points [--open] [--kind <kind file>] [--at <rev>] [--json]
|
|
970
1097
|
List the decision points the declared answer kinds'
|
|
971
1098
|
points files declare, and the questions asked of them;
|
|
972
1099
|
--open keeps the escalated and proposed ones (ws-058)
|
|
973
|
-
workspace points ask <point> --inputs <file
|
|
1100
|
+
workspace points ask <point> --inputs <file|-|json> [--candidates <file|-|json>] [--response <file>] [--subject <id>] [--kind <kind file>] [--dry-run]
|
|
974
1101
|
Ask a point's table, model and quorum deciders and
|
|
975
1102
|
record the answer: proposed from a model, escalated to
|
|
976
1103
|
people below its threshold. --response is a POST
|
|
977
|
-
/v1/systemone response the caller got; chant calls no model
|
|
978
|
-
|
|
1104
|
+
/v1/systemone response the caller got; chant calls no model.
|
|
1105
|
+
--candidates gives an ad-hoc point's question and
|
|
1106
|
+
candidates, { question, criteria }
|
|
1107
|
+
workspace points answer <id> --answer <value> --by <name>... [--note <text>] [--relayed-by <principal>] [--kind <kind file>] [--dry-run]
|
|
979
1108
|
Record people's answer to an open question, or confirm
|
|
980
|
-
a model's proposal, once the point's quorum is met
|
|
1109
|
+
a model's proposal, once the point's quorum is met,
|
|
1110
|
+
with their note and who relayed it
|
|
1111
|
+
workspace points retract <id> --by <name>... [--note <text>] [--kind <kind file>] [--dry-run]
|
|
1112
|
+
Take an answer back: the question is open for people
|
|
1113
|
+
again, and the answer stays in its retractions
|
|
981
1114
|
workspace pin <path> [--json]
|
|
982
1115
|
Print the integrity value that pins the plugin at
|
|
983
1116
|
<path>, to put in a path pin of chant.workspace.json.
|
|
@@ -987,13 +1120,14 @@ Workspace (level 1, #2524):
|
|
|
987
1120
|
member it is bound to, the record kinds and verbs its
|
|
988
1121
|
write scope allows, and the spec records --current
|
|
989
1122
|
prints. Without a name, the session CHANT_AGENT names
|
|
990
|
-
workspace verify [--base <rev>] [--head <rev>] [--require attested]
|
|
1123
|
+
workspace verify [--base <rev>] [--head <rev>] [--require attested | attested-runs]
|
|
991
1124
|
Check the commits in base..head against the signers
|
|
992
1125
|
and roles read from base. A change to the signers file
|
|
993
1126
|
or .chant/trust.json needs a signature by a signer
|
|
994
1127
|
trusted at base, and a new signer set needs a
|
|
995
|
-
threshold of the old one.
|
|
996
|
-
|
|
1128
|
+
threshold of the old one. A commit an agent run made
|
|
1129
|
+
is attested by the run's signed statement; with
|
|
1130
|
+
attested-runs, only those commits must be
|
|
997
1131
|
workspace signers [--json] [rotate [--threshold <n>] | sign --key <file>]
|
|
998
1132
|
Show the signer history at base, or propose the next
|
|
999
1133
|
signer set and sign it with a current signer's key
|
|
@@ -1101,12 +1235,14 @@ Workspace (level 1, #2524):
|
|
|
1101
1235
|
Each composite instance the members declare, with the
|
|
1102
1236
|
components whose contract can deploy it; an instance
|
|
1103
1237
|
with none lists an empty set
|
|
1104
|
-
workspace graph --intent <path[:start-end]|path#symbol> [--at <rev>] [--kind <kind file>...] [--json]
|
|
1238
|
+
workspace graph --intent <path[:start-end]|path#symbol> [--at <rev>] [--kind <kind file>...] [--follow-squash] [--json]
|
|
1105
1239
|
The intent graph over one region: the commits that
|
|
1106
1240
|
touched it, the decisions whose constrains cover it,
|
|
1107
1241
|
the artifacts they pin, and findings with closed codes.
|
|
1108
|
-
Without --kind, every record kind the declaration names
|
|
1109
|
-
|
|
1242
|
+
Without --kind, every record kind the declaration names.
|
|
1243
|
+
--follow-squash follows a squash merge to its pull
|
|
1244
|
+
request's commits, fetching a missing ref from origin
|
|
1245
|
+
workspace graph --intent --record <id> [--at <rev>] [--kind <kind file>...] [--follow-squash] [--json]
|
|
1110
1246
|
One decision's intent walk over every path: and member:
|
|
1111
1247
|
entry it constrains: the commits in its window, each
|
|
1112
1248
|
own, worked, within-other or unexplained, with counts
|
|
@@ -1156,8 +1292,23 @@ Component release ledger + status:
|
|
|
1156
1292
|
(--base <ref> [--head <ref>] [--include-dependents],
|
|
1157
1293
|
or --from-affected <file>; --dry-run prints the
|
|
1158
1294
|
derivation and dispatches nothing; --gate <name>
|
|
1159
|
-
puts one approval over the whole set;
|
|
1160
|
-
<
|
|
1295
|
+
puts one approval over the whole set;
|
|
1296
|
+
--wave-gate <name> puts one on each wave, planned
|
|
1297
|
+
when the wave is reached, with --canary <name>
|
|
1298
|
+
for wave 1 and --wave <n> for one wave per CI
|
|
1299
|
+
job; --resume <file> finishes an attempt that
|
|
1300
|
+
stopped)
|
|
1301
|
+
components pr-plan Plan the components a pull request reaches and
|
|
1302
|
+
the ones that depend on them, and write the
|
|
1303
|
+
report and note (--base <ref> --pr <n>
|
|
1304
|
+
[--forge github|gitlab|forgejo] posts them);
|
|
1305
|
+
applies nothing
|
|
1306
|
+
components pr-apply On merge: plan the same members again and apply
|
|
1307
|
+
them only if an approval stands for that digest
|
|
1308
|
+
(chant approve pr-<n> pr-apply --plan <digest>);
|
|
1309
|
+
a moved plan refuses with exit 3
|
|
1310
|
+
(--require-review: the approver must have
|
|
1311
|
+
approved the pull request on the forge)
|
|
1161
1312
|
components release <env> Append one immutable release record
|
|
1162
1313
|
(--component <name> --digest <sha256:...>
|
|
1163
1314
|
[--git-sha <sha>] [--run-id <id>] [--actor <name>]);
|
|
@@ -1564,6 +1715,8 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1564
1715
|
// Status read over a tree of carve manifests (#2038): the contract a
|
|
1565
1716
|
// renderer replaces its own walk-and-guess discovery with. Read-only.
|
|
1566
1717
|
{ name: "carve status", handler: runCarveStatus },
|
|
1718
|
+
// #3188 — the grouped plan summary of a change-set document. Reads one file; imported on first use.
|
|
1719
|
+
{ name: "change-set summary", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/change-set")).runChangeSetSummary(ctx) },
|
|
1567
1720
|
{ name: "init", handler: runInit, runsNoConfig: true },
|
|
1568
1721
|
{ name: "init lexicon", handler: runInitLexicon },
|
|
1569
1722
|
{ name: "update", handler: runUpdate },
|
|
@@ -1630,6 +1783,12 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1630
1783
|
{ name: "workspace graph", handler: async (ctx) => (await import("../workspace/member-commands")).runWorkspaceMembers(ctx, "graph") },
|
|
1631
1784
|
// Each unit decides for itself whether its config is loaded (runCommandInProcess).
|
|
1632
1785
|
{ name: "workspace member-run", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/member-run")).runWorkspaceMemberRun(ctx, runCommandInProcess) },
|
|
1786
|
+
// #3308 — a box's listing, written through chant so a tool never edits the declaration itself (ws-074).
|
|
1787
|
+
{ name: "workspace box", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/box-cli")).runWorkspaceBox(ctx) },
|
|
1788
|
+
// #3173 — the working tree's write lock, held across chant calls for a batch of writes (ws-089).
|
|
1789
|
+
{ name: "workspace lock", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/write-lock-cli")).runWorkspaceLock(ctx) },
|
|
1790
|
+
// #3172 — work in progress under refs/chant/wip/<branch>, replicated under the box's policy (ws-085).
|
|
1791
|
+
{ name: "workspace wip", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/wip-cli")).runWorkspaceWip(ctx) },
|
|
1633
1792
|
{ name: "workspace pin", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/pin-cli")).runWorkspacePin(ctx) },
|
|
1634
1793
|
// #2548 — an agent session's member, write scope and spec, for a session that resumes.
|
|
1635
1794
|
{ name: "workspace agent", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/agent-cli")).runWorkspaceAgent(ctx) },
|
|
@@ -1655,6 +1814,9 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1655
1814
|
|
|
1656
1815
|
// Component release ledger + status surface (#568, epic #551)
|
|
1657
1816
|
{ name: "components fan-out", requiresPlugins: true, handler: runComponentsFanOut },
|
|
1817
|
+
// #3183 — the pull-request loop the generated CI runs. Imported on first use.
|
|
1818
|
+
{ name: "components pr-plan", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr")).runComponentsPrPlan(ctx) },
|
|
1819
|
+
{ name: "components pr-apply", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr")).runComponentsPrApply(ctx) },
|
|
1658
1820
|
{ name: "components status", requiresPlugins: true, handler: runComponentsStatus },
|
|
1659
1821
|
{ name: "components release", handler: runComponentsReleaseRecord },
|
|
1660
1822
|
{ name: "components export", handler: runComponentsExport },
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { withTestDir } from "@intentius/chant-test-utils";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { writeFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { appendPendingGate, readGateLedger } from "../../lifecycle/gate-ledger";
|
|
7
|
+
import { resetGateOrigin } from "../../lifecycle/gate-origin";
|
|
8
|
+
|
|
9
|
+
const started = vi.fn();
|
|
10
|
+
const resolveGate = vi.fn();
|
|
11
|
+
|
|
12
|
+
vi.mock("../../op/discover", () => ({
|
|
13
|
+
discoverOps: async () => ({
|
|
14
|
+
errors: [],
|
|
15
|
+
ops: new Map([
|
|
16
|
+
["tf-apply", { config: { name: "tf-apply", overview: "apply", phases: [], neverOverMcp: true } }],
|
|
17
|
+
["plain-op", { config: { name: "plain-op", overview: "plain", phases: [] } }],
|
|
18
|
+
]),
|
|
19
|
+
}),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
vi.mock("../../op/runtimes/local", () => ({
|
|
23
|
+
createLocalOpRuntime: () => ({
|
|
24
|
+
name: "local",
|
|
25
|
+
start: async (config: { name: string }) => {
|
|
26
|
+
started(config.name);
|
|
27
|
+
return { result: async () => ({ op: config.name, runId: "r1", state: "succeeded", startedAt: "t" }) };
|
|
28
|
+
},
|
|
29
|
+
status: async () => undefined,
|
|
30
|
+
list: async () => new Map(),
|
|
31
|
+
resolveGate,
|
|
32
|
+
}),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
import { createOpApproveTool, createOpRunTool, createOpStatusTool, createOpReportTool } from "./op-tools";
|
|
36
|
+
|
|
37
|
+
function git(args: string[], cwd: string): void {
|
|
38
|
+
spawnSync("git", args, { cwd, encoding: "utf-8" });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe("neverOverMcp (chant#3447)", () => {
|
|
42
|
+
const cwd = process.cwd();
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
started.mockClear();
|
|
45
|
+
resolveGate.mockClear();
|
|
46
|
+
});
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
process.chdir(cwd);
|
|
49
|
+
resetGateOrigin();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("op-approve refuses a CI-reached gate of a declared Op and the ledger is unchanged", async () => {
|
|
53
|
+
await withTestDir(async (dir) => {
|
|
54
|
+
git(["init", "-q", "-b", "main"], dir);
|
|
55
|
+
git(["config", "user.email", "t@chant.dev"], dir);
|
|
56
|
+
git(["config", "user.name", "T"], dir);
|
|
57
|
+
writeFileSync(join(dir, "README.md"), "x\n");
|
|
58
|
+
git(["add", "."], dir);
|
|
59
|
+
git(["commit", "-q", "-m", "init"], dir);
|
|
60
|
+
|
|
61
|
+
// A gate reached on forge CI, not over MCP: the same-origin rule would let it through.
|
|
62
|
+
await appendPendingGate(
|
|
63
|
+
{
|
|
64
|
+
op: "tf-apply",
|
|
65
|
+
gate: "wave-2",
|
|
66
|
+
timestamp: "2026-01-01T00:00:00.000Z",
|
|
67
|
+
origin: "cli",
|
|
68
|
+
expiresAt: "2999-01-01T00:00:00.000Z",
|
|
69
|
+
planDigest: `sha256:${"a".repeat(64)}`,
|
|
70
|
+
},
|
|
71
|
+
{ cwd: dir },
|
|
72
|
+
);
|
|
73
|
+
const before = await readGateLedger("tf-apply", { cwd: dir });
|
|
74
|
+
expect(before.pending).toHaveLength(1);
|
|
75
|
+
|
|
76
|
+
process.chdir(dir);
|
|
77
|
+
await expect(createOpApproveTool().handler({ name: "tf-apply", gate: "wave-2" })).rejects.toThrow(
|
|
78
|
+
/neverOverMcp.*whichever channel/s,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
expect(await readGateLedger("tf-apply", { cwd: dir })).toEqual(before);
|
|
82
|
+
expect(resolveGate).not.toHaveBeenCalled();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("op-run refuses a declared Op and starts nothing", async () => {
|
|
87
|
+
await expect(createOpRunTool().handler({ name: "tf-apply" })).rejects.toThrow(/neverOverMcp.*chant run tf-apply/s);
|
|
88
|
+
expect(started).not.toHaveBeenCalled();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("an Op that does not declare it still runs", async () => {
|
|
92
|
+
const result = (await createOpRunTool().handler({ name: "plain-op" })) as { state: string };
|
|
93
|
+
expect(result.state).toBe("succeeded");
|
|
94
|
+
expect(started).toHaveBeenCalledWith("plain-op");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("op-status and op-report still answer for a declared Op", async () => {
|
|
98
|
+
await expect(createOpStatusTool().handler({ name: "tf-apply" })).resolves.toMatchObject({ op: "tf-apply" });
|
|
99
|
+
await expect(createOpReportTool().handler({ name: "tf-apply" })).resolves.toContain("# tf-apply");
|
|
100
|
+
});
|
|
101
|
+
});
|
package/src/cli/mcp/op-tools.ts
CHANGED
|
@@ -53,6 +53,21 @@ async function runtimeFor(name: unknown): Promise<OpRuntimeProvider> {
|
|
|
53
53
|
return plugin.opRuntime;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* The refusal for an Op that declares `neverOverMcp`, or `undefined` when MCP
|
|
58
|
+
* may act on it. It names the rule and the way through, which is a person at a
|
|
59
|
+
* shell. An Op that is not discovered is left to the caller's own not-found
|
|
60
|
+
* handling.
|
|
61
|
+
*/
|
|
62
|
+
async function neverOverMcpRefusal(name: string, action: "run" | "approve"): Promise<string | undefined> {
|
|
63
|
+
const { ops } = await discoverOps();
|
|
64
|
+
if (!ops.get(name)?.config.neverOverMcp) return undefined;
|
|
65
|
+
return action === "run"
|
|
66
|
+
? `Op "${name}" declares neverOverMcp, so it is not run over MCP. Run it at a shell with \`chant run ${name}\`; op-status and op-report still answer here.`
|
|
67
|
+
: `Op "${name}" declares neverOverMcp, so its gates are not resolved over MCP, whichever channel reached them. ` +
|
|
68
|
+
`Approvals belong to people: approve at a shell with \`chant approve ${name} <gate>\`.`;
|
|
69
|
+
}
|
|
70
|
+
|
|
56
71
|
const RUNTIME_PARAM = {
|
|
57
72
|
type: "string",
|
|
58
73
|
description: 'Runtime to address: a lexicon name with an opRuntime, or "local" (the default)',
|
|
@@ -103,7 +118,8 @@ export function createOpRunTool(): ToolRegistration {
|
|
|
103
118
|
definition: {
|
|
104
119
|
name: "op-run",
|
|
105
120
|
description:
|
|
106
|
-
"Run an Op on a runtime and return its result. Defaults to the built-in local runtime, which executes the Op in this process."
|
|
121
|
+
"Run an Op on a runtime and return its result. Defaults to the built-in local runtime, which executes the Op in this process. " +
|
|
122
|
+
"Refuses an Op that declares neverOverMcp.",
|
|
107
123
|
inputSchema: {
|
|
108
124
|
type: "object",
|
|
109
125
|
properties: {
|
|
@@ -117,6 +133,8 @@ export function createOpRunTool(): ToolRegistration {
|
|
|
117
133
|
const name = params.name as string;
|
|
118
134
|
|
|
119
135
|
const { ops } = await discoverOps();
|
|
136
|
+
const refusal = await neverOverMcpRefusal(name, "run");
|
|
137
|
+
if (refusal) throw new Error(refusal);
|
|
120
138
|
if (!ops.has(name)) {
|
|
121
139
|
const available = [...ops.keys()];
|
|
122
140
|
return `Op "${name}" not found. Available: ${available.join(", ") || "none"}`;
|
|
@@ -185,7 +203,8 @@ export function createOpApproveTool(): ToolRegistration {
|
|
|
185
203
|
"Record a gate's resolution on the gate ledger and wake the runtime hosting the gated run. " +
|
|
186
204
|
"Refuses a gate this same channel reached: a run started with op-run must be approved from " +
|
|
187
205
|
"somewhere else, normally `chant approve <op> <gate>` at a shell. The approver is recorded as " +
|
|
188
|
-
"unattested, because this channel cannot verify a name."
|
|
206
|
+
"unattested, because this channel cannot verify a name. Also refuses every gate of an Op that " +
|
|
207
|
+
"declares neverOverMcp, whatever channel reached the gate.",
|
|
189
208
|
inputSchema: {
|
|
190
209
|
type: "object",
|
|
191
210
|
properties: {
|
|
@@ -206,6 +225,9 @@ export function createOpApproveTool(): ToolRegistration {
|
|
|
206
225
|
const gate = params.gate as string;
|
|
207
226
|
if (!name || !gate) throw new Error("op-approve needs both an Op name and a gate name");
|
|
208
227
|
|
|
228
|
+
const refusal = await neverOverMcpRefusal(name, "approve");
|
|
229
|
+
if (refusal) throw new Error(refusal);
|
|
230
|
+
|
|
209
231
|
const runtime = await runtimeFor(params.runtime);
|
|
210
232
|
const outcome = await recordGateApproval(name, gate, {
|
|
211
233
|
note: params.note as string | undefined,
|
|
@@ -85,7 +85,7 @@ describe("which servers have the workspace tools", () => {
|
|
|
85
85
|
const { tools } = (await rpc(server(cwd), "tools/list")) as { tools: { name: string }[] };
|
|
86
86
|
expect(tools.map((t) => t.name)).toEqual(expect.arrayContaining(names));
|
|
87
87
|
}
|
|
88
|
-
expect(names).toEqual(["workspace-ls", "workspace-status", "workspace-graph", "workspace-changes", "workspace-records", "workspace-points", "workspace-agent", "workspace-work-history", "workspace-runs", "records-new", "records-amend", "records-review", "records-close", "points-answer"]);
|
|
88
|
+
expect(names).toEqual(["workspace-ls", "workspace-status", "workspace-graph", "workspace-changes", "workspace-records", "workspace-points", "workspace-agent", "workspace-work-history", "workspace-runs", "records-new", "records-amend", "records-review", "records-close", "points-answer", "points-retract"]);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
test("a server outside any workspace, or given none, does not", async () => {
|