@intentius/chant 0.90.0 → 0.93.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/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts +8 -0
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +20 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.d.ts +7 -4
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/plugins.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +42 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
- package/dist/components/verbs/vuln-scan.d.ts +72 -0
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/lexicon-module.d.ts +22 -0
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lifecycle/converge-ledger.d.ts +19 -0
- package/dist/lifecycle/converge-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +40 -5
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/lease.d.ts +72 -16
- package/dist/lifecycle/lease.d.ts.map +1 -1
- package/dist/lifecycle/member-ledger.d.ts +3 -2
- package/dist/lifecycle/member-ledger.d.ts.map +1 -1
- package/dist/lifecycle/plan-ledger.d.ts +114 -0
- package/dist/lifecycle/plan-ledger.d.ts.map +1 -0
- package/dist/lifecycle/run-ledger.d.ts +2 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/symptoms.d.ts +51 -0
- package/dist/lifecycle/symptoms.d.ts.map +1 -1
- package/dist/lifecycle/work-lease.d.ts +140 -0
- package/dist/lifecycle/work-lease.d.ts.map +1 -0
- package/dist/lint/rules/index.d.ts +4 -2
- package/dist/lint/rules/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +14 -3
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -1
- package/dist/lint/rules/op/sys010-key-over-plain-http.d.ts +29 -0
- package/dist/lint/rules/op/sys010-key-over-plain-http.d.ts.map +1 -0
- package/dist/lint/rules/sys001-no-literal-key.d.ts +3 -0
- package/dist/lint/rules/sys001-no-literal-key.d.ts.map +1 -0
- package/dist/op/__fixtures__/decide-stub-backend.d.ts +53 -0
- package/dist/op/__fixtures__/decide-stub-backend.d.ts.map +1 -0
- package/dist/op/activities/activity-contracts.d.ts +203 -2
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/apply.d.ts.map +1 -1
- package/dist/op/activities/change-coverage.d.ts +44 -0
- package/dist/op/activities/change-coverage.d.ts.map +1 -0
- package/dist/op/activities/converge.d.ts +24 -1
- package/dist/op/activities/converge.d.ts.map +1 -1
- package/dist/op/activities/decide.d.ts +107 -0
- package/dist/op/activities/decide.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +10 -0
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/shell.d.ts +32 -0
- package/dist/op/activities/shell.d.ts.map +1 -1
- package/dist/op/activities/source-release.d.ts +86 -0
- package/dist/op/activities/source-release.d.ts.map +1 -0
- package/dist/op/activities/source-rollback.d.ts +100 -0
- package/dist/op/activities/source-rollback.d.ts.map +1 -0
- package/dist/op/activities/work-evidence.d.ts +42 -0
- package/dist/op/activities/work-evidence.d.ts.map +1 -0
- package/dist/op/activity-contract.d.ts +1 -0
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/activity-profiles.d.ts +16 -0
- package/dist/op/activity-profiles.d.ts.map +1 -1
- package/dist/op/builders.d.ts +84 -2
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/converge-op.d.ts +31 -4
- package/dist/op/composites/converge-op.d.ts.map +1 -1
- package/dist/op/decide-backend.d.ts +116 -0
- package/dist/op/decide-backend.d.ts.map +1 -0
- package/dist/op/decide-config.d.ts +120 -0
- package/dist/op/decide-config.d.ts.map +1 -0
- package/dist/op/decide-read-inputs.d.ts +40 -0
- package/dist/op/decide-read-inputs.d.ts.map +1 -0
- package/dist/op/discover.d.ts +25 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/gate-wait.d.ts +43 -0
- package/dist/op/gate-wait.d.ts.map +1 -0
- package/dist/op/gate.d.ts +5 -2
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/index.d.ts +18 -5
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/lifecycle-receipt-store.d.ts +34 -0
- package/dist/op/lifecycle-receipt-store.d.ts.map +1 -0
- package/dist/op/local-executor.d.ts +48 -4
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-output.d.ts +2 -0
- package/dist/op/local-output.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +12 -1
- 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 +126 -1
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +46 -5
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/op/source-archive.d.ts +63 -0
- package/dist/op/source-archive.d.ts.map +1 -0
- package/dist/op/step-output-ref.d.ts +2 -2
- package/dist/op/step-output-ref.d.ts.map +1 -1
- package/dist/op/steward-points.d.ts +136 -0
- package/dist/op/steward-points.d.ts.map +1 -0
- package/dist/op/steward-turn.d.ts +53 -0
- package/dist/op/steward-turn.d.ts.map +1 -0
- package/dist/op/steward.d.ts +161 -0
- package/dist/op/steward.d.ts.map +1 -0
- package/dist/op/types.d.ts +58 -0
- package/dist/op/types.d.ts.map +1 -1
- package/dist/op/work-lease-decl.d.ts +18 -0
- package/dist/op/work-lease-decl.d.ts.map +1 -0
- package/dist/op/work-lease-run.d.ts +173 -0
- package/dist/op/work-lease-run.d.ts.map +1 -0
- package/dist/workspace/__fixtures__/decide-workspace.d.ts +100 -0
- package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -0
- package/dist/workspace/answers-ledger.d.ts +76 -0
- package/dist/workspace/answers-ledger.d.ts.map +1 -0
- package/dist/workspace/box-isolation.d.ts +99 -0
- package/dist/workspace/box-isolation.d.ts.map +1 -0
- package/dist/workspace/changes-cli.d.ts +16 -0
- package/dist/workspace/changes-cli.d.ts.map +1 -0
- package/dist/workspace/changes.d.ts +200 -0
- package/dist/workspace/changes.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.d.ts +59 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.d.ts +51 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.d.ts +26 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.d.ts +59 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.d.ts +22 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts +71 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -0
- package/dist/workspace/chant-migrations.d.ts +99 -0
- package/dist/workspace/chant-migrations.d.ts.map +1 -0
- package/dist/workspace/checks/box-isolation.d.ts +18 -0
- package/dist/workspace/checks/box-isolation.d.ts.map +1 -0
- package/dist/workspace/checks/boxes.d.ts +104 -0
- package/dist/workspace/checks/boxes.d.ts.map +1 -0
- package/dist/workspace/checks/diagrams.d.ts +31 -0
- package/dist/workspace/checks/diagrams.d.ts.map +1 -0
- package/dist/workspace/checks/records.d.ts +8 -0
- package/dist/workspace/checks/records.d.ts.map +1 -1
- package/dist/workspace/checks.d.ts +13 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/compose-graph.d.ts +2 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/decide.d.ts +229 -0
- package/dist/workspace/decide.d.ts.map +1 -0
- package/dist/workspace/decision-points.schema.json +137 -0
- package/dist/workspace/declaration.d.ts +103 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +285 -0
- package/dist/workspace/declared-kinds.d.ts +32 -0
- package/dist/workspace/declared-kinds.d.ts.map +1 -1
- package/dist/workspace/generated-files.d.ts +7 -0
- package/dist/workspace/generated-files.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/lineage-check.d.ts +3 -0
- package/dist/workspace/lineage-check.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade.d.ts +6 -1
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/ls.d.ts +39 -1
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/point-answer.schema.json +95 -0
- package/dist/workspace/points-cli.d.ts +113 -0
- package/dist/workspace/points-cli.d.ts.map +1 -0
- package/dist/workspace/points.d.ts +320 -0
- package/dist/workspace/points.d.ts.map +1 -0
- package/dist/workspace/reason-codes.d.ts +38 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/record-assets.d.ts.map +1 -1
- package/dist/workspace/records-cli.d.ts +23 -1
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-close.d.ts +1 -1
- package/dist/workspace/records-close.d.ts.map +1 -1
- package/dist/workspace/records-write.d.ts +11 -5
- package/dist/workspace/records-write.d.ts.map +1 -1
- package/dist/workspace/records.d.ts +42 -6
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/status-gates.d.ts +7 -2
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status-stewards.d.ts +179 -0
- package/dist/workspace/status-stewards.d.ts.map +1 -0
- package/dist/workspace/status.d.ts +68 -1
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/work-cli.d.ts +189 -0
- package/dist/workspace/work-cli.d.ts.map +1 -0
- package/dist/workspace/work-evidence.d.ts +74 -0
- package/dist/workspace/work-evidence.d.ts.map +1 -0
- package/dist/workspace/work.d.ts +43 -1
- package/dist/workspace/work.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/audit.test.ts +9 -1
- package/src/cli/commands/build.ts +3 -2
- package/src/cli/commands/lint.ts +7 -1
- package/src/cli/handlers/components.test.ts +93 -0
- package/src/cli/handlers/components.ts +44 -3
- package/src/cli/handlers/graph.test.ts +20 -0
- package/src/cli/handlers/graph.ts +16 -2
- package/src/cli/handlers/operator.ts +141 -4
- package/src/cli/handlers/run.test.ts +173 -2
- package/src/cli/handlers/run.ts +174 -3
- package/src/cli/main.test.ts +50 -0
- package/src/cli/main.ts +97 -2
- package/src/cli/mcp/workspace-tools.test.ts +48 -19
- package/src/cli/mcp/workspace-tools.ts +110 -8
- package/src/cli/plugins.ts +11 -3
- package/src/cli/registry.ts +42 -1
- package/src/codegen/pinned-upgrade.ts +2 -1
- package/src/codegen/release-wiring.test.ts +49 -2
- package/src/components/capability-plugin-loader.ts +3 -3
- package/src/components/cli-support.ts +2 -2
- package/src/components/verbs/vuln-scan.test.ts +124 -1
- package/src/components/verbs/vuln-scan.ts +142 -1
- package/src/config.ts +11 -0
- package/src/lexicon-module.ts +56 -1
- package/src/lexicon-package.test.ts +96 -0
- package/src/lifecycle/converge-ledger.ts +20 -0
- package/src/lifecycle/git.ts +65 -15
- package/src/lifecycle/lease.test.ts +22 -0
- package/src/lifecycle/lease.ts +133 -29
- package/src/lifecycle/member-ledger.ts +3 -2
- package/src/lifecycle/plan-ledger.test.ts +148 -0
- package/src/lifecycle/plan-ledger.ts +158 -0
- package/src/lifecycle/run-ledger.ts +6 -0
- package/src/lifecycle/symptoms.ts +95 -0
- package/src/lifecycle/work-lease.test.ts +236 -0
- package/src/lifecycle/work-lease.ts +426 -0
- package/src/lint/rules/index.ts +6 -2
- package/src/lint/rules/op/index.ts +17 -4
- package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +23 -1
- package/src/lint/rules/op/ops014-converge-rule-refusals.ts +10 -6
- package/src/lint/rules/op/sys010-key-over-plain-http.test.ts +52 -0
- package/src/lint/rules/op/sys010-key-over-plain-http.ts +100 -0
- package/src/lint/rules/sys001-no-literal-key.test.ts +31 -0
- package/src/lint/rules/sys001-no-literal-key.ts +67 -0
- package/src/op/__fixtures__/decide-stub-backend.ts +143 -0
- package/src/op/activities/activity-contracts.ts +190 -1
- package/src/op/activities/apply.ts +7 -6
- package/src/op/activities/change-coverage.ts +60 -0
- package/src/op/activities/converge.test.ts +55 -1
- package/src/op/activities/converge.ts +208 -29
- package/src/op/activities/decide.live.test.ts +78 -0
- package/src/op/activities/decide.test.ts +300 -0
- package/src/op/activities/decide.ts +267 -0
- package/src/op/activities/index.ts +21 -0
- package/src/op/activities/shell.test.ts +91 -1
- package/src/op/activities/shell.ts +91 -2
- package/src/op/activities/source-release.test.ts +118 -0
- package/src/op/activities/source-release.ts +168 -0
- package/src/op/activities/source-rollback.test.ts +131 -0
- package/src/op/activities/source-rollback.ts +239 -0
- package/src/op/activities/work-evidence.ts +62 -0
- package/src/op/activity-contract-registry.test.ts +2 -0
- package/src/op/activity-contract-registry.ts +2 -2
- package/src/op/activity-contract.test.ts +12 -0
- package/src/op/activity-contract.ts +6 -1
- package/src/op/activity-profiles.ts +29 -0
- package/src/op/activity-registry.test.ts +1 -1
- package/src/op/activity-registry.ts +2 -2
- package/src/op/builders.ts +124 -5
- package/src/op/command-gate.test.ts +192 -0
- package/src/op/composites/converge-op.test.ts +27 -1
- package/src/op/composites/converge-op.ts +69 -15
- package/src/op/decide-backend.test.ts +44 -0
- package/src/op/decide-backend.ts +212 -0
- package/src/op/decide-config.test.ts +52 -0
- package/src/op/decide-config.ts +80 -0
- package/src/op/decide-read-inputs.ts +117 -0
- package/src/op/discover.ts +71 -0
- package/src/op/gate-approval.ts +2 -2
- package/src/op/gate-wait.ts +57 -0
- package/src/op/gate.ts +8 -3
- package/src/op/generate-pipeline.ts +2 -2
- package/src/op/index.ts +34 -6
- package/src/op/lifecycle-receipt-store.test.ts +60 -0
- package/src/op/lifecycle-receipt-store.ts +61 -0
- package/src/op/local-executor.ts +367 -33
- package/src/op/local-output.test.ts +33 -0
- package/src/op/local-output.ts +33 -2
- package/src/op/op-ir.test.ts +10 -0
- package/src/op/op-ir.ts +18 -0
- package/src/op/op-verb-class.ts +1 -0
- package/src/op/operator.ts +360 -10
- package/src/op/runtime.ts +37 -8
- package/src/op/runtimes/local.ts +6 -1
- package/src/op/source-archive.ts +161 -0
- package/src/op/step-output-ref.ts +6 -2
- package/src/op/steward-points.test.ts +313 -0
- package/src/op/steward-points.ts +194 -0
- package/src/op/steward-turn.ts +79 -0
- package/src/op/steward.test.ts +296 -0
- package/src/op/steward.ts +277 -0
- package/src/op/types.ts +60 -0
- package/src/op/work-lease-decl.ts +80 -0
- package/src/op/work-lease-run.test.ts +345 -0
- package/src/op/work-lease-run.ts +395 -0
- package/src/workspace/__fixtures__/decide-workspace.ts +129 -0
- package/src/workspace/__fixtures__/studio-template-84c8b21.json +67 -0
- package/src/workspace/answers-ledger.ts +118 -0
- package/src/workspace/box-isolation.test.ts +261 -0
- package/src/workspace/box-isolation.ts +205 -0
- package/src/workspace/changes-cli.ts +56 -0
- package/src/workspace/changes.schema.json +472 -0
- package/src/workspace/changes.test.ts +315 -0
- package/src/workspace/changes.ts +512 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit-fly-site.ts +234 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit-live-names.ts +164 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit-rollback.ts +223 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.ts +195 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit-ship-policy.ts +108 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit.ts +882 -0
- package/src/workspace/chant-migrations.e2e.test.ts +1089 -0
- package/src/workspace/chant-migrations.ts +164 -0
- package/src/workspace/check-contract.test.ts +5 -1
- package/src/workspace/check.schema.json +25 -7
- package/src/workspace/checks/box-isolation.ts +68 -0
- package/src/workspace/checks/boxes.test.ts +276 -0
- package/src/workspace/checks/boxes.ts +442 -0
- package/src/workspace/checks/diagrams.test.ts +134 -0
- package/src/workspace/checks/diagrams.ts +108 -0
- package/src/workspace/checks/records.ts +72 -0
- package/src/workspace/checks.test.ts +7 -0
- package/src/workspace/checks.ts +27 -3
- package/src/workspace/compose-graph.ts +2 -0
- package/src/workspace/conformance/__fixture__/decisions/decision.kind.mjs +10 -0
- package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +26 -0
- package/src/workspace/conformance/index.ts +5 -0
- package/src/workspace/decide.test.ts +224 -0
- package/src/workspace/decide.ts +709 -0
- package/src/workspace/decision-points.schema.json +137 -0
- package/src/workspace/declaration.schema.json +285 -0
- package/src/workspace/declaration.test.ts +58 -0
- package/src/workspace/declaration.ts +241 -0
- package/src/workspace/declared-kinds.test.ts +5 -5
- package/src/workspace/declared-kinds.ts +71 -3
- package/src/workspace/generated-files.ts +14 -0
- package/src/workspace/graph-cli.ts +1 -1
- package/src/workspace/graph.schema.json +9 -1
- package/src/workspace/intent.schema.json +12 -3
- package/src/workspace/intent.ts +3 -10
- package/src/workspace/lineage-check.ts +16 -1
- package/src/workspace/lineage-upgrade-cli.ts +1 -1
- package/src/workspace/lineage-upgrade.test.ts +70 -0
- package/src/workspace/lineage-upgrade.ts +81 -10
- package/src/workspace/ls-contract.test.ts +57 -0
- package/src/workspace/ls.schema.json +46 -1
- package/src/workspace/ls.ts +62 -3
- package/src/workspace/point-answer.schema.json +95 -0
- package/src/workspace/points-cli.ts +284 -0
- package/src/workspace/points-write.schema.json +499 -0
- package/src/workspace/points.schema.json +743 -0
- package/src/workspace/points.test.ts +264 -0
- package/src/workspace/points.ts +564 -0
- package/src/workspace/read-contract.test.ts +18 -1
- package/src/workspace/reason-codes.test.ts +24 -1
- package/src/workspace/reason-codes.ts +49 -0
- package/src/workspace/record-assets.test.ts +3 -2
- package/src/workspace/record-assets.ts +4 -1
- package/src/workspace/records-amend.schema.json +2 -0
- package/src/workspace/records-cli.ts +28 -5
- package/src/workspace/records-close.schema.json +2 -0
- package/src/workspace/records-contract.test.ts +3 -2
- package/src/workspace/records-new.schema.json +2 -0
- package/src/workspace/records-review.schema.json +2 -0
- package/src/workspace/records-sessions-write.e2e.test.ts +77 -0
- package/src/workspace/records-sessions-write.test.ts +2 -34
- package/src/workspace/records-write.e2e.test.ts +108 -0
- package/src/workspace/records-write.test.ts +32 -41
- package/src/workspace/records-write.ts +33 -15
- package/src/workspace/records.schema.json +53 -2
- package/src/workspace/records.test.ts +48 -3
- package/src/workspace/records.ts +142 -6
- package/src/workspace/status-contract.test.ts +189 -6
- package/src/workspace/status-gates.ts +9 -4
- package/src/workspace/status-stewards.ts +329 -0
- package/src/workspace/status.schema.json +335 -5
- package/src/workspace/status.ts +142 -6
- package/src/workspace/work-acceptance.test.ts +274 -0
- package/src/workspace/work-cli.e2e.test.ts +180 -0
- package/src/workspace/work-cli.ts +429 -0
- package/src/workspace/work-evidence.schema.json +212 -0
- package/src/workspace/work-evidence.ts +169 -0
- package/src/workspace/work-history.schema.json +349 -0
- package/src/workspace/work-history.test.ts +156 -0
- package/src/workspace/work-lease.schema.json +233 -0
- package/src/workspace/work-readiness-chud.test.ts +145 -0
- package/src/workspace/work.test.ts +3 -2
- package/src/workspace/work.ts +100 -1
- /package/src/cli/{discovery-skip.test.ts → discovery-skip.e2e.test.ts} +0 -0
- /package/src/workspace/conformance/{conformance.test.ts → conformance.e2e.test.ts} +0 -0
- /package/src/workspace/{which-chant.test.ts → which-chant.e2e.test.ts} +0 -0
|
@@ -124,6 +124,76 @@ describe("chant workspace upgrade", () => {
|
|
|
124
124
|
expect(git(proj, ["worktree", "list"]).split("\n")).toHaveLength(1);
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
+
test("builds and lints the chant member chant.workspace.json declares, not the scope root (#2804)", async () => {
|
|
128
|
+
release("v2.0.0", {
|
|
129
|
+
"chant.workspace.json": JSON.stringify({ name: "proj", schema: 1, members: [{ name: "delivery", dir: "delivery", kind: "chant" }] }, null, 2) + "\n",
|
|
130
|
+
"delivery/chant.config.ts": "export default {};\n",
|
|
131
|
+
});
|
|
132
|
+
const calls: Array<{ command: string; cwd: string }> = [];
|
|
133
|
+
const recording: ChantRunner = async (command, cwd) => {
|
|
134
|
+
calls.push({ command, cwd });
|
|
135
|
+
return { exitCode: 0, output: "" };
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const staged = await stageUpgrade({ root: proj, to: "v2.0.0", runChant: recording });
|
|
139
|
+
try {
|
|
140
|
+
// Never at the scope root: it has no chant.config once the project is a workspace.
|
|
141
|
+
expect(calls.every((c) => c.cwd === join(staged.worktreeProject, "delivery"))).toBe(true);
|
|
142
|
+
expect(calls.map((c) => c.command).sort()).toEqual(["build", "lint"]);
|
|
143
|
+
expect(staged.checks).toEqual(
|
|
144
|
+
expect.arrayContaining([
|
|
145
|
+
{ name: "build", status: "passed", member: "delivery" },
|
|
146
|
+
{ name: "lint", status: "passed", member: "delivery" },
|
|
147
|
+
]),
|
|
148
|
+
);
|
|
149
|
+
} finally {
|
|
150
|
+
staged.dispose();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
test("a member's own node_modules is linked into the staging worktree for its checks, and stays out of the patch (#2847)", async () => {
|
|
155
|
+
release("v2.0.0", {
|
|
156
|
+
"chant.workspace.json": JSON.stringify({ name: "proj", schema: 1, members: [{ name: "delivery", dir: "delivery", kind: "chant" }] }, null, 2) + "\n",
|
|
157
|
+
"delivery/chant.config.ts": "export default {};\n",
|
|
158
|
+
});
|
|
159
|
+
// The member installs its packages itself; git never sees them.
|
|
160
|
+
put(proj, "delivery/node_modules/member-only/package.json", JSON.stringify({ name: "member-only", version: "1.0.0" }) + "\n");
|
|
161
|
+
writeFileSync(join(proj, ".git", "info", "exclude"), "node_modules\n");
|
|
162
|
+
const seen: string[] = [];
|
|
163
|
+
const recording: ChantRunner = async (command, cwd) => {
|
|
164
|
+
if (existsSync(join(cwd, "node_modules", "member-only", "package.json"))) seen.push(command);
|
|
165
|
+
return { exitCode: 0, output: "" };
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const staged = await stageUpgrade({ root: proj, to: "v2.0.0", runChant: recording });
|
|
169
|
+
try {
|
|
170
|
+
expect(seen.sort()).toEqual(["build", "lint"]);
|
|
171
|
+
expect(staged.changedPaths.some((p) => p.includes("node_modules"))).toBe(false);
|
|
172
|
+
expect(staged.patch).not.toContain("node_modules");
|
|
173
|
+
} finally {
|
|
174
|
+
staged.dispose();
|
|
175
|
+
}
|
|
176
|
+
// Disposing the worktree removes the link, never the member's own packages.
|
|
177
|
+
expect(existsSync(join(proj, "delivery", "node_modules", "member-only", "package.json"))).toBe(true);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("a member's failing build fails the upgrade's checks before the gate (#2804)", async () => {
|
|
181
|
+
release("v2.0.0", {
|
|
182
|
+
"chant.workspace.json": JSON.stringify({ name: "proj", schema: 1, members: [{ name: "delivery", dir: "delivery", kind: "chant" }] }, null, 2) + "\n",
|
|
183
|
+
"delivery/chant.config.ts": "export default {};\n",
|
|
184
|
+
});
|
|
185
|
+
const failingBuild: ChantRunner = async (command) => (command === "build" ? { exitCode: 1, output: "boom\n" } : { exitCode: 0, output: "" });
|
|
186
|
+
|
|
187
|
+
const result = await upgradeCommand({ root: proj, to: "v2.0.0", runChant: failingBuild });
|
|
188
|
+
expect(result.outcome).toBe("checks-failed");
|
|
189
|
+
expect(result.exitCode).toBe(1);
|
|
190
|
+
expect(result.staged!.checks).toEqual(
|
|
191
|
+
expect.arrayContaining([{ name: "build", status: "failed", detail: "boom", member: "delivery" }]),
|
|
192
|
+
);
|
|
193
|
+
// The tree is unchanged: an unbuildable migration never reaches the gate.
|
|
194
|
+
expect(git(proj, ["status", "--porcelain"])).toBe("");
|
|
195
|
+
});
|
|
196
|
+
|
|
127
197
|
test("gates on the patch digest, then applies exactly the approved patch", async () => {
|
|
128
198
|
release("v2.0.0", { "README.md": "starter v2\n" });
|
|
129
199
|
const port = ledger();
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
36
|
import { execFileSync, spawn } from "node:child_process";
|
|
37
|
-
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
37
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
38
38
|
import { tmpdir } from "node:os";
|
|
39
|
-
import { basename, join, relative, resolve, sep } from "node:path";
|
|
39
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
40
40
|
import { computePlanDigest } from "../lifecycle/plan-digest";
|
|
41
41
|
import type { ResolvedGateApproval } from "../op/gate-approval";
|
|
42
42
|
import { checkLineage, findingKey, type CheckFinding } from "./lineage-check";
|
|
@@ -56,10 +56,13 @@ import {
|
|
|
56
56
|
type ManualStep,
|
|
57
57
|
} from "./lineage-lock";
|
|
58
58
|
import { mergeFile } from "./lineage-merge";
|
|
59
|
+
import { reportPlan, runChantMigrations, type ChantMigrationReport } from "./chant-migrations";
|
|
60
|
+
import { readDeclaration, readerVersion, WorkspaceReadError } from "./declaration";
|
|
59
61
|
import { assertCodeAllowed, planMigrations, runMigration, splitMigrations, type LoadedMigration } from "./lineage-migrations";
|
|
60
62
|
import { applyUpstream, type UpdateResult } from "./lineage-update";
|
|
61
63
|
import { carryParameters, readManifest, substituteParameters } from "./template-manifest";
|
|
62
64
|
import { repinSubstituted, type RepinnedRecord } from "./template-pins";
|
|
65
|
+
import { workingTree } from "./tree";
|
|
63
66
|
|
|
64
67
|
/** The kind the patch digest is taken under, so it never collides with another kind of plan. */
|
|
65
68
|
export const UPGRADE_PLAN_KIND = "workspace-upgrade";
|
|
@@ -74,10 +77,12 @@ export class UpgradeError extends LockError {
|
|
|
74
77
|
// ── Checks ───────────────────────────────────────────────────────────────────
|
|
75
78
|
|
|
76
79
|
export interface UpgradeCheck {
|
|
77
|
-
name: "build" | "lint" | "workspace check";
|
|
80
|
+
name: "build" | "lint" | "workspace check" | "migration";
|
|
78
81
|
status: "passed" | "failed" | "skipped";
|
|
79
82
|
/** Why a check was skipped, or the tail of a failed command's output. */
|
|
80
83
|
detail?: string;
|
|
84
|
+
/** The chant member `build` or `lint` ran in ("." for the scope root), when it is not the only one. */
|
|
85
|
+
member?: string;
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
/** Runs `chant build` or `chant lint` in a directory. */
|
|
@@ -141,6 +146,8 @@ export interface StagedUpgrade {
|
|
|
141
146
|
to: string | null;
|
|
142
147
|
commit?: { from?: string; to: string };
|
|
143
148
|
migrations: string[];
|
|
149
|
+
/** The migrations chant ships (./chant-migrations.ts) that found something to move, applied or not. */
|
|
150
|
+
chantMigrations: ChantMigrationReport[];
|
|
144
151
|
written: string[];
|
|
145
152
|
merged: string[];
|
|
146
153
|
removed: string[];
|
|
@@ -460,6 +467,25 @@ function tail(text: string, lines = 30): string {
|
|
|
460
467
|
return text.trimEnd().split("\n").slice(-lines).join("\n");
|
|
461
468
|
}
|
|
462
469
|
|
|
470
|
+
/**
|
|
471
|
+
* The `chant` members `chant.workspace.json` declares in `dir` (#2804): a
|
|
472
|
+
* template built as a workspace, such as the studio kit's, keeps its chant
|
|
473
|
+
* project in a member (`delivery`), not at the scope's root, and the root
|
|
474
|
+
* itself never has a `chant.config`. Empty when `dir` declares no workspace,
|
|
475
|
+
* or the declaration cannot be read: the caller then falls back to `dir`
|
|
476
|
+
* itself.
|
|
477
|
+
*/
|
|
478
|
+
function chantMemberDirs(dir: string): string[] {
|
|
479
|
+
try {
|
|
480
|
+
return readDeclaration(workingTree(dir))
|
|
481
|
+
.members.filter((m) => m.kind === "chant")
|
|
482
|
+
.map((m) => m.dir);
|
|
483
|
+
} catch (err) {
|
|
484
|
+
if (err instanceof WorkspaceReadError) return [];
|
|
485
|
+
throw err;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
463
489
|
/**
|
|
464
490
|
* Stage an upgrade: steps 1 to 5 and the digest of step 6. Nothing in the
|
|
465
491
|
* project's tree changes. The caller decides the gate, then applies the patch
|
|
@@ -568,6 +594,12 @@ export async function stageUpgrade(options: UpgradeOptions): Promise<StagedUpgra
|
|
|
568
594
|
rmSync(scratch, { recursive: true, force: true });
|
|
569
595
|
}
|
|
570
596
|
|
|
597
|
+
// chant's own migrations (#2737): planned from what the scope holds, and
|
|
598
|
+
// applied only when the plan has no conflict. A conflict fails the checks.
|
|
599
|
+
// Each is planned from the tree the ones before it left.
|
|
600
|
+
const chantRuns = lineage.kind === "template" ? runChantMigrations({ dir: scopeDir, lineage: staged, chantVersion: readerVersion() }) : [];
|
|
601
|
+
const chantMigrations: ChantMigrationReport[] = chantRuns.map((r) => reportPlan(r.plan, r.applied));
|
|
602
|
+
|
|
571
603
|
// 4. Merge per file.
|
|
572
604
|
const result = applyUpstream(scopeDir, staged, upstream.files, { base, merge: mergeFile });
|
|
573
605
|
for (const path of result.written) if (upstream.executable.has(path)) chmodSync(join(scopeDir, path), 0o755);
|
|
@@ -607,12 +639,40 @@ export async function stageUpgrade(options: UpgradeOptions): Promise<StagedUpgra
|
|
|
607
639
|
|
|
608
640
|
// 5. Checks.
|
|
609
641
|
const checks: UpgradeCheck[] = [];
|
|
642
|
+
for (const m of chantMigrations.filter((m) => !m.applied)) {
|
|
643
|
+
checks.push({
|
|
644
|
+
name: "migration",
|
|
645
|
+
status: "failed",
|
|
646
|
+
detail: `${m.id} was not applied: ${m.conflicts.map((c) => `${c.path}: ${c.reason}`).join("\n")}`,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
610
649
|
if (changed) {
|
|
611
|
-
|
|
650
|
+
// Every `chant` member chant.workspace.json declares, so a template
|
|
651
|
+
// whose chant project sits in a member (the studio kit's `delivery/`)
|
|
652
|
+
// is built and linted there, not skipped for having no chant.config at
|
|
653
|
+
// the scope's root (#2804). A scope with no workspace declaration falls
|
|
654
|
+
// back to the root, as before.
|
|
655
|
+
const members = chantMemberDirs(worktreeProject);
|
|
656
|
+
const targets = members.length > 0 ? members : isChantProject(worktreeProject) ? ["."] : [];
|
|
657
|
+
if (targets.length > 0) {
|
|
612
658
|
const run = options.runChant ?? spawnChant;
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
659
|
+
const namedMember = targets.length > 1 || targets[0] !== ".";
|
|
660
|
+
// A member that installs its packages in its own directory resolves them from its node_modules, which is not
|
|
661
|
+
// an ancestor of the staging worktree: link it in from the project (#2847). The patch and its digest are
|
|
662
|
+
// computed above, so the links never reach them, and dispose() removes them with the worktree.
|
|
663
|
+
for (const member of targets) {
|
|
664
|
+
if (member === ".") continue;
|
|
665
|
+
const from = join(root, member, "node_modules");
|
|
666
|
+
const to = join(worktreeProject, member, "node_modules");
|
|
667
|
+
if (existsSync(from) && !existsSync(to) && existsSync(dirname(to))) symlinkSync(from, to, "dir");
|
|
668
|
+
}
|
|
669
|
+
for (const member of targets) {
|
|
670
|
+
const dir = member === "." ? worktreeProject : join(worktreeProject, member);
|
|
671
|
+
const at = namedMember ? { member } : {};
|
|
672
|
+
for (const command of ["build", "lint"] as const) {
|
|
673
|
+
const r = await run(command, dir);
|
|
674
|
+
checks.push(r.exitCode === 0 ? { name: command, status: "passed", ...at } : { name: command, status: "failed", detail: tail(r.output), ...at });
|
|
675
|
+
}
|
|
616
676
|
}
|
|
617
677
|
} else {
|
|
618
678
|
for (const name of ["build", "lint"] as const) checks.push({ name, status: "skipped", detail: "not a chant project (no chant.config)" });
|
|
@@ -627,7 +687,8 @@ export async function stageUpgrade(options: UpgradeOptions): Promise<StagedUpgra
|
|
|
627
687
|
from: fromDir ? sourcePin(lineage.source) : lineage.ref ?? null,
|
|
628
688
|
to: fromDir ? sourcePin(staged.source) : staged.ref ?? null,
|
|
629
689
|
...(upstream.commit ? { commit: { ...(lineage.address?.commit ? { from: lineage.address.commit } : {}), to: upstream.commit } } : {}),
|
|
630
|
-
migrations: plan.chain.map((m) => m.migration.id),
|
|
690
|
+
migrations: [...plan.chain.map((m) => m.migration.id), ...chantMigrations.filter((m) => m.applied).map((m) => m.id)],
|
|
691
|
+
chantMigrations,
|
|
631
692
|
written: result.written,
|
|
632
693
|
merged: result.merged,
|
|
633
694
|
removed: result.removed,
|
|
@@ -721,7 +782,14 @@ export function describeStaged(staged: StagedUpgrade): string[] {
|
|
|
721
782
|
const lines: string[] = [];
|
|
722
783
|
const at = (p: string) => (staged.scope === "." ? p : `${staged.scope}/${p}`);
|
|
723
784
|
lines.push(`${staged.scope} ${staged.template} ${staged.from ?? "(no ref)"} -> ${staged.to ?? "(no ref)"}`);
|
|
724
|
-
|
|
785
|
+
const chantIds = new Set(staged.chantMigrations.map((m) => m.id));
|
|
786
|
+
for (const id of staged.migrations) if (!chantIds.has(id)) lines.push(` migration: ${id}`);
|
|
787
|
+
for (const m of staged.chantMigrations) {
|
|
788
|
+
lines.push(` chant migration: ${m.id} (${m.applied ? "applied" : "not applied: it has conflicts"}), to ${m.description}`);
|
|
789
|
+
for (const c of m.changes) lines.push(` ${c.action === "delete" ? "delete" : "write"}: ${at(c.path)} (${c.why}${c.edited ? "; it was edited since the template, and the edit stays in git history" : ""})`);
|
|
790
|
+
for (const n of m.notMoved) lines.push(` not moved: ${n.what} -> ${n.where}`);
|
|
791
|
+
for (const c of m.conflicts) lines.push(` conflict: ${at(c.path)}: ${c.reason}`);
|
|
792
|
+
}
|
|
725
793
|
for (const p of staged.written) lines.push(` updated: ${at(p)}`);
|
|
726
794
|
for (const p of staged.merged) lines.push(` merged: ${at(p)}`);
|
|
727
795
|
for (const p of staged.removed) lines.push(` removed: ${at(p)}`);
|
|
@@ -735,7 +803,10 @@ export function describeStaged(staged: StagedUpgrade): string[] {
|
|
|
735
803
|
` governance: ${staged.governance.paths.join(", ")}; needs ${q.count} human approval(s)${q.roles ? ` with a role in ${q.roles.join(", ")}` : ""}, from the rules at ${staged.governance.rules.slice(0, 12)}`,
|
|
736
804
|
);
|
|
737
805
|
}
|
|
738
|
-
for (const c of staged.checks)
|
|
806
|
+
for (const c of staged.checks) {
|
|
807
|
+
const label = c.member !== undefined ? `${c.name} (${c.member})` : c.name;
|
|
808
|
+
lines.push(` ${label}: ${c.status}${c.status === "skipped" && c.detail ? ` (${c.detail})` : ""}`);
|
|
809
|
+
}
|
|
739
810
|
lines.push(` patch: ${staged.changedPaths.length} file(s)${staged.lock.tracked ? "" : ` and the untracked ${LOCK_FILE}`}, ${staged.digest}`);
|
|
740
811
|
return lines;
|
|
741
812
|
}
|
|
@@ -135,6 +135,63 @@ describe("chant workspace ls on built workspaces", () => {
|
|
|
135
135
|
expect(doc.summary).toEqual({ members: 5, unreadable: 3, groups: 1, matches: 0 });
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
+
test("lists declared diagrams flattened across the workspace and its members (#2764)", () => {
|
|
139
|
+
const root = repo({
|
|
140
|
+
"chant.workspace.json": JSON.stringify({
|
|
141
|
+
name: "acme",
|
|
142
|
+
schema: 1,
|
|
143
|
+
members: [
|
|
144
|
+
{
|
|
145
|
+
name: "docs",
|
|
146
|
+
dir: "docs",
|
|
147
|
+
kind: "other",
|
|
148
|
+
because: "the docs site",
|
|
149
|
+
diagrams: [
|
|
150
|
+
{
|
|
151
|
+
name: "architecture",
|
|
152
|
+
title: "Studio architecture",
|
|
153
|
+
source: "docs/diagrams/architecture.d2",
|
|
154
|
+
render: "docs/diagrams/architecture.svg",
|
|
155
|
+
renderer: { tool: "d2", version: "0.9.0", args: ["--layout=elk", "--theme=0", "--pad=40", "--omit-version"] },
|
|
156
|
+
sourceHash: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
diagrams: [
|
|
162
|
+
{
|
|
163
|
+
name: "boundary",
|
|
164
|
+
title: "chant and hud",
|
|
165
|
+
source: null,
|
|
166
|
+
render: "docs/diagrams/boundary.svg",
|
|
167
|
+
renderer: { tool: "graphviz", version: "9.0.0", args: [] },
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
}),
|
|
171
|
+
"docs/README.md": "",
|
|
172
|
+
});
|
|
173
|
+
const doc = result(listWorkspace({ cwd: root }));
|
|
174
|
+
expectValid(doc);
|
|
175
|
+
expect(doc.diagrams).toEqual([
|
|
176
|
+
{
|
|
177
|
+
name: "boundary",
|
|
178
|
+
title: "chant and hud",
|
|
179
|
+
source: null,
|
|
180
|
+
render: "docs/diagrams/boundary.svg",
|
|
181
|
+
renderer: { tool: "graphviz", version: "9.0.0", args: [] },
|
|
182
|
+
member: null,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: "architecture",
|
|
186
|
+
title: "Studio architecture",
|
|
187
|
+
source: "docs/diagrams/architecture.d2",
|
|
188
|
+
render: "docs/diagrams/architecture.svg",
|
|
189
|
+
renderer: { tool: "d2", version: "0.9.0", args: ["--layout=elk", "--theme=0", "--pad=40", "--omit-version"] },
|
|
190
|
+
member: "docs",
|
|
191
|
+
},
|
|
192
|
+
]);
|
|
193
|
+
});
|
|
194
|
+
|
|
138
195
|
test("a nested workspace member is readable by its own declaration, and ls inside it lists the inner one", () => {
|
|
139
196
|
const root = repo({
|
|
140
197
|
"chant.workspace.json": declaration([{ name: "kit", dir: "vendor/kit", kind: "workspace" }]),
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"result": {
|
|
9
9
|
"description": "The declaration was read. Exit code 0, even when some members can't be read.",
|
|
10
10
|
"type": "object",
|
|
11
|
-
"required": ["$schema", "contract", "chant", "at", "workspace", "members", "groups", "summary"],
|
|
11
|
+
"required": ["$schema", "contract", "chant", "at", "workspace", "members", "groups", "diagrams", "summary"],
|
|
12
12
|
"properties": {
|
|
13
13
|
"$schema": { "const": "https://intentius.io/chant/schemas/workspace/ls/v1/ls.schema.json" },
|
|
14
14
|
"contract": { "const": 1 },
|
|
@@ -61,6 +61,11 @@
|
|
|
61
61
|
"type": "array",
|
|
62
62
|
"items": { "$ref": "#/$defs/group" }
|
|
63
63
|
},
|
|
64
|
+
"diagrams": {
|
|
65
|
+
"description": "Added in contract 1 by #2764. Every declared diagram artifact, flattened across the workspace and its members: the workspace's own first, then each member's, in file order.",
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": { "$ref": "#/$defs/diagram" }
|
|
68
|
+
},
|
|
64
69
|
"summary": {
|
|
65
70
|
"type": "object",
|
|
66
71
|
"required": ["members", "unreadable", "groups", "matches"],
|
|
@@ -138,9 +143,49 @@
|
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
145
|
]
|
|
146
|
+
},
|
|
147
|
+
"acceptance": {
|
|
148
|
+
"description": "Added in contract 1 by #2772. For a work kind whose work block names acceptance criteria: each current work item that lists some, in path order, with how many of its criteria passing evidence meets, read in the tree read. Null for any other kind, and when the kind or its records can't be read.",
|
|
149
|
+
"oneOf": [
|
|
150
|
+
{ "type": "null" },
|
|
151
|
+
{
|
|
152
|
+
"type": "array",
|
|
153
|
+
"items": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"required": ["item", "state", "met", "total"],
|
|
156
|
+
"properties": {
|
|
157
|
+
"item": { "type": "string", "description": "The work item's id." },
|
|
158
|
+
"state": { "type": ["string", "null"], "description": "The item's state." },
|
|
159
|
+
"met": { "type": "integer", "minimum": 0, "description": "Criteria met by evidence naming them, with result pass and the criterion's verification; a manual verdict counts only from someone other than the implementer." },
|
|
160
|
+
"total": { "type": "integer", "minimum": 0, "description": "Criteria the item lists." }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
]
|
|
141
165
|
}
|
|
142
166
|
}
|
|
143
167
|
},
|
|
168
|
+
"diagram": {
|
|
169
|
+
"description": "A diagram artifact the declaration names (#2764), pinned to the renderer its render was made with. chant runs no renderer; everything here comes straight from the declaration.",
|
|
170
|
+
"type": "object",
|
|
171
|
+
"required": ["name", "title", "source", "render", "renderer", "member"],
|
|
172
|
+
"properties": {
|
|
173
|
+
"name": { "type": "string" },
|
|
174
|
+
"title": { "type": "string" },
|
|
175
|
+
"source": { "type": ["string", "null"], "description": "From the workspace root, with / separators. Null for an SVG with no source." },
|
|
176
|
+
"render": { "type": "string", "description": "From the workspace root, with / separators." },
|
|
177
|
+
"renderer": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"required": ["tool", "version", "args"],
|
|
180
|
+
"properties": {
|
|
181
|
+
"tool": { "enum": ["d2", "mermaid", "graphviz"] },
|
|
182
|
+
"version": { "type": "string", "description": "The exact release the render was made with, such as 0.9.0." },
|
|
183
|
+
"args": { "type": "array", "items": { "type": "string" }, "description": "Passed before the input and output paths, in order." }
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"member": { "type": ["string", "null"], "description": "The member that declares it, or null for the workspace's own." }
|
|
187
|
+
}
|
|
188
|
+
},
|
|
144
189
|
"group": {
|
|
145
190
|
"type": "object",
|
|
146
191
|
"required": ["name", "kind", "glob", "matches", "skipped", "reason"],
|
package/src/workspace/ls.ts
CHANGED
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* and each member's, with each kind file's own name when it loads (#2680).
|
|
14
14
|
* Loading one imports it, so {@link listWorkspace} lists them unloaded and
|
|
15
15
|
* {@link listWorkspaceWithKinds}, which the command runs, loads them.
|
|
16
|
+
*
|
|
17
|
+
* The declared diagram artifacts are listed too, flattened across the
|
|
18
|
+
* workspace and its members into one `diagrams` array (#2764). Unlike record
|
|
19
|
+
* kinds, nothing about a diagram is loaded: everything printed comes
|
|
20
|
+
* straight from the declaration, and chant runs no renderer to list it.
|
|
16
21
|
*/
|
|
17
22
|
|
|
18
23
|
import { existsSync } from "node:fs";
|
|
@@ -20,11 +25,13 @@ import { resolve } from "node:path";
|
|
|
20
25
|
import { formatError } from "../cli/format";
|
|
21
26
|
import type { CommandContext } from "../cli/registry";
|
|
22
27
|
import {
|
|
28
|
+
declaredDiagrams,
|
|
23
29
|
readDeclaration,
|
|
24
30
|
readerVersion,
|
|
25
31
|
resolveGroups,
|
|
26
32
|
WorkspaceReadError,
|
|
27
33
|
type Declaration,
|
|
34
|
+
type DiagramDeclaration,
|
|
28
35
|
type ErrorLocation,
|
|
29
36
|
type Member,
|
|
30
37
|
type WorkspaceErrorCode,
|
|
@@ -74,6 +81,20 @@ export interface LsRecordKind {
|
|
|
74
81
|
kind: string | null;
|
|
75
82
|
/** Why the kind file can't be loaded, or null. */
|
|
76
83
|
reason: { code: DeclaredKindReasonCode; message: string } | null;
|
|
84
|
+
/**
|
|
85
|
+
* For a work kind with acceptance criteria (#2772): each current work item
|
|
86
|
+
* that lists criteria, with how many passing evidence meets. Null for any
|
|
87
|
+
* other kind, and when the kind or its records can't be read.
|
|
88
|
+
*/
|
|
89
|
+
acceptance: LsAcceptance[] | null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** A work item's acceptance criteria, counted (#2772). */
|
|
93
|
+
export interface LsAcceptance {
|
|
94
|
+
item: string;
|
|
95
|
+
state: string | null;
|
|
96
|
+
met: number;
|
|
97
|
+
total: number;
|
|
77
98
|
}
|
|
78
99
|
|
|
79
100
|
export interface LsMember {
|
|
@@ -89,6 +110,25 @@ export interface LsMember {
|
|
|
89
110
|
records: LsRecordKind[];
|
|
90
111
|
}
|
|
91
112
|
|
|
113
|
+
/**
|
|
114
|
+
* A diagram artifact the declaration names (#2764), flattened across the
|
|
115
|
+
* workspace and its members: hud reads one list, the way it already reads
|
|
116
|
+
* `records --json`'s flat `assets[]`. `sourceHash`, the declaration's own
|
|
117
|
+
* bookkeeping for `chant workspace check`'s drift finding, is not printed
|
|
118
|
+
* here; a reader that draws diagrams has no use for it.
|
|
119
|
+
*/
|
|
120
|
+
export interface LsDiagram {
|
|
121
|
+
name: string;
|
|
122
|
+
title: string;
|
|
123
|
+
/** From the workspace root, with / separators. Null for an SVG with no source. */
|
|
124
|
+
source: string | null;
|
|
125
|
+
/** From the workspace root, with / separators. */
|
|
126
|
+
render: string;
|
|
127
|
+
renderer: DiagramDeclaration["renderer"];
|
|
128
|
+
/** The member that declares it, or null for the workspace's own. */
|
|
129
|
+
member: string | null;
|
|
130
|
+
}
|
|
131
|
+
|
|
92
132
|
export interface LsGroup {
|
|
93
133
|
name: string;
|
|
94
134
|
kind: "examples";
|
|
@@ -117,6 +157,8 @@ export type LsDocument =
|
|
|
117
157
|
};
|
|
118
158
|
members: LsMember[];
|
|
119
159
|
groups: LsGroup[];
|
|
160
|
+
/** Every declared diagram, the workspace's own first, then each member's, in file order (#2764). */
|
|
161
|
+
diagrams: LsDiagram[];
|
|
120
162
|
summary: { members: number; unreadable: number; groups: number; matches: number };
|
|
121
163
|
}
|
|
122
164
|
| {
|
|
@@ -162,11 +204,12 @@ export async function listWorkspaceWithKinds(query: LsQuery): Promise<LsDocument
|
|
|
162
204
|
const { doc, declaration, tree, rootOnDisk } = readListing(query);
|
|
163
205
|
if (!declaration || "error" in doc) return doc;
|
|
164
206
|
const { loadDeclaredKinds } = await import("./declared-kinds");
|
|
165
|
-
const loaded = await loadDeclaredKinds(declaration, tree!, rootOnDisk
|
|
207
|
+
const loaded = await loadDeclaredKinds(declaration, tree!, rootOnDisk!, { acceptance: true, ...(doc.at !== null ? { at: doc.at } : {}) });
|
|
166
208
|
const byPath = new Map(loaded.map((k) => [k.declared.path, k]));
|
|
167
209
|
const fill = (r: LsRecordKind): LsRecordKind => {
|
|
168
210
|
const k = byPath.get(r.path)!;
|
|
169
|
-
|
|
211
|
+
const acceptance = k.acceptance ? k.acceptance.map((a) => ({ item: a.item, state: a.state, met: a.met, total: a.total })) : null;
|
|
212
|
+
return { ...r, name: r.name ?? k.kind, kind: k.kind, reason: k.reason, acceptance };
|
|
170
213
|
};
|
|
171
214
|
return {
|
|
172
215
|
...doc,
|
|
@@ -175,7 +218,7 @@ export async function listWorkspaceWithKinds(query: LsQuery): Promise<LsDocument
|
|
|
175
218
|
};
|
|
176
219
|
}
|
|
177
220
|
|
|
178
|
-
const unloaded = (records: Declaration["records"]): LsRecordKind[] => records.map((r) => ({ name: r.name, path: r.path, kind: null, reason: null }));
|
|
221
|
+
const unloaded = (records: Declaration["records"]): LsRecordKind[] => records.map((r) => ({ name: r.name, path: r.path, kind: null, reason: null, acceptance: null }));
|
|
179
222
|
|
|
180
223
|
function readListing(query: LsQuery): { doc: LsDocument; declaration?: Declaration; tree?: WorkspaceTree; rootOnDisk?: string } {
|
|
181
224
|
const chant = readerVersion();
|
|
@@ -213,6 +256,14 @@ function readListing(query: LsQuery): { doc: LsDocument; declaration?: Declarati
|
|
|
213
256
|
? { code: "no-matches", message: `no directory ${g.group.globs.join(" or ")} matches${tree.label} holds a chant project` }
|
|
214
257
|
: null,
|
|
215
258
|
}));
|
|
259
|
+
const diagrams: LsDiagram[] = declaredDiagrams(declaration).map((d) => ({
|
|
260
|
+
name: d.name,
|
|
261
|
+
title: d.title,
|
|
262
|
+
source: d.source,
|
|
263
|
+
render: d.render,
|
|
264
|
+
renderer: d.renderer,
|
|
265
|
+
member: d.member,
|
|
266
|
+
}));
|
|
216
267
|
const doc: LsDocument = {
|
|
217
268
|
...head,
|
|
218
269
|
at,
|
|
@@ -227,6 +278,7 @@ function readListing(query: LsQuery): { doc: LsDocument; declaration?: Declarati
|
|
|
227
278
|
},
|
|
228
279
|
members,
|
|
229
280
|
groups: lsGroups,
|
|
281
|
+
diagrams,
|
|
230
282
|
summary: {
|
|
231
283
|
members: members.length,
|
|
232
284
|
unreadable: members.filter((m) => !m.readable).length,
|
|
@@ -296,8 +348,15 @@ function formatLs(doc: Extract<LsDocument, { members: unknown }>): string {
|
|
|
296
348
|
kinds.forEach(({ r }, i) => {
|
|
297
349
|
lines.push(rendered[i + 1]);
|
|
298
350
|
if (r.reason) lines.push(` ${r.reason.code}: ${r.reason.message}`);
|
|
351
|
+
for (const a of r.acceptance ?? []) lines.push(` ${a.item} ${a.state ?? "-"}: ${a.met}/${a.total} criteria met`);
|
|
299
352
|
});
|
|
300
353
|
}
|
|
354
|
+
if (doc.diagrams.length > 0) {
|
|
355
|
+
lines.push("");
|
|
356
|
+
const rows = [["DIAGRAM", "MEMBER", "SOURCE", "RENDER", "RENDERER"]];
|
|
357
|
+
for (const d of doc.diagrams) rows.push([d.name, d.member ?? "(workspace)", d.source ?? "-", d.render, `${d.renderer.tool} ${d.renderer.version}`]);
|
|
358
|
+
lines.push(...table(rows));
|
|
359
|
+
}
|
|
301
360
|
if (doc.groups.length > 0) {
|
|
302
361
|
lines.push("");
|
|
303
362
|
const rows = [["GROUP", "KIND", "GLOB", "PROJECTS"]];
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "urn:intentius:chant:point-answer:1",
|
|
4
|
+
"title": "Decision point answer front matter",
|
|
5
|
+
"description": "The front matter of one answer to a decision point (ws-058, #2739), as `chant workspace points ask` and `points answer` write it into the records directory of a record kind with an `answers` block. One record per point, declaration and inputs: its id is the point's name and the first 12 hex digits of the inputs hash, so the same question is answered once. A table's answer is `answered`; a model's answer at or above its threshold is `proposed` until a person confirms it; a question no decider before the quorum answered is `escalated`, open for people. A workspace copies this file next to its answer kind, as reference-workspace/answers/ does. Values stay within what YAML and JSON share. Fields other than these must start with x-.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"patternProperties": { "^x-": {} },
|
|
9
|
+
"required": ["id", "title", "point", "point_version", "question_type", "candidates", "inputs", "inputs_hash", "state", "decider", "asked_on"],
|
|
10
|
+
"properties": {
|
|
11
|
+
"id": { "type": "string", "pattern": "^[a-z][a-z0-9-]*-[0-9a-f]{12}$", "description": "The point's name, a hyphen, and the first 12 hex digits of inputs_hash." },
|
|
12
|
+
"title": { "type": "string", "minLength": 1 },
|
|
13
|
+
"point": { "type": "string", "pattern": "^[a-z][a-z0-9-]*$", "description": "The point in the points file this answers." },
|
|
14
|
+
"point_version": { "$ref": "#/definitions/sha256", "description": "sha256 of the point's declaration when it was asked. Editing the question or any decider changes it." },
|
|
15
|
+
"question_type": { "enum": ["noul", "choice", "score"] },
|
|
16
|
+
"candidates": { "type": "array", "minItems": 2, "items": { "type": ["string", "boolean"] }, "description": "The answers the question allowed: true and false, a choice's options, or a score's levels." },
|
|
17
|
+
"inputs": { "type": "object", "description": "The state the deciders saw, input name to value." },
|
|
18
|
+
"inputs_hash": { "$ref": "#/definitions/sha256", "description": "sha256 of the point, its version and its inputs. The same hash is answered once." },
|
|
19
|
+
"constrains": { "type": "array", "items": { "type": "string", "minLength": 1 }, "description": "What the question is about, such as a work item's id." },
|
|
20
|
+
"state": { "enum": ["escalated", "proposed", "answered"] },
|
|
21
|
+
"answer": { "type": ["string", "boolean"] },
|
|
22
|
+
"decider": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"required": ["kind"],
|
|
25
|
+
"properties": {
|
|
26
|
+
"kind": { "enum": ["table", "model", "quorum"] },
|
|
27
|
+
"row": { "type": "integer", "minimum": 0, "description": "table: the row that matched." },
|
|
28
|
+
"backend": { "type": "string", "minLength": 1 },
|
|
29
|
+
"model": { "type": "string", "minLength": 1, "description": "model: the model id that answered, as the backend reported it." },
|
|
30
|
+
"count": { "type": "integer", "minimum": 1 },
|
|
31
|
+
"roles": { "type": "array", "items": { "type": "string" } },
|
|
32
|
+
"by": { "type": "array", "items": { "type": "string" }, "description": "quorum: who answered." }
|
|
33
|
+
},
|
|
34
|
+
"additionalProperties": false
|
|
35
|
+
},
|
|
36
|
+
"probabilities": { "$ref": "#/definitions/probabilities" },
|
|
37
|
+
"confidence": { "$ref": "#/definitions/unit" },
|
|
38
|
+
"threshold": { "$ref": "#/definitions/unit" },
|
|
39
|
+
"escalations": {
|
|
40
|
+
"type": "array",
|
|
41
|
+
"description": "The deciders asked before the one that answered, or before the quorum, and why each did not answer.",
|
|
42
|
+
"items": { "$ref": "#/definitions/escalation" }
|
|
43
|
+
},
|
|
44
|
+
"answered_by": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "The people who answered or confirmed it." },
|
|
45
|
+
"asked_on": { "$ref": "#/definitions/date" },
|
|
46
|
+
"answered_on": { "$ref": "#/definitions/date" },
|
|
47
|
+
"source": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"description": "Where the answer came from (#2708): via, client and model, the model id that answered when a model decider did."
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"allOf": [
|
|
53
|
+
{
|
|
54
|
+
"if": { "properties": { "state": { "const": "proposed" } }, "required": ["state"] },
|
|
55
|
+
"then": { "required": ["answer"], "properties": { "decider": { "properties": { "kind": { "const": "model" } } } } }
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"if": { "properties": { "state": { "const": "answered" } }, "required": ["state"] },
|
|
59
|
+
"then": { "required": ["answer", "answered_on"] }
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"if": { "properties": { "state": { "const": "escalated" } }, "required": ["state"] },
|
|
63
|
+
"then": { "not": { "required": ["answer"] }, "properties": { "decider": { "properties": { "kind": { "const": "quorum" } } } } }
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"if": { "properties": { "decider": { "properties": { "kind": { "const": "model" } }, "required": ["kind"] } }, "required": ["decider"] },
|
|
67
|
+
"then": { "required": ["probabilities", "confidence", "threshold"], "properties": { "decider": { "required": ["backend", "model"] } } }
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"if": { "properties": { "state": { "const": "answered" }, "decider": { "properties": { "kind": { "const": "quorum" } }, "required": ["kind"] } }, "required": ["state", "decider"] },
|
|
71
|
+
"then": { "required": ["answered_by"], "properties": { "decider": { "required": ["by"] } } }
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"definitions": {
|
|
75
|
+
"sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
|
|
76
|
+
"unit": { "type": "number", "minimum": 0, "maximum": 1 },
|
|
77
|
+
"date": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
|
|
78
|
+
"probabilities": { "type": "object", "additionalProperties": { "$ref": "#/definitions/unit" } },
|
|
79
|
+
"escalation": {
|
|
80
|
+
"type": "object",
|
|
81
|
+
"required": ["kind", "reason"],
|
|
82
|
+
"properties": {
|
|
83
|
+
"kind": { "enum": ["table", "model"] },
|
|
84
|
+
"reason": { "type": "string", "minLength": 1 },
|
|
85
|
+
"backend": { "type": "string" },
|
|
86
|
+
"model": { "type": "string" },
|
|
87
|
+
"answer": { "type": ["string", "boolean", "null"] },
|
|
88
|
+
"probabilities": { "$ref": "#/definitions/probabilities" },
|
|
89
|
+
"confidence": { "$ref": "#/definitions/unit" },
|
|
90
|
+
"threshold": { "$ref": "#/definitions/unit" }
|
|
91
|
+
},
|
|
92
|
+
"additionalProperties": false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|