@intentius/chant 0.91.0 → 0.94.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/graph.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +6 -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-plugins.d.ts +6 -6
- package/dist/cli/mcp/workspace-tools.d.ts +2 -1
- 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 +12 -2
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/pinned-upgrade.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/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/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 +201 -0
- 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/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 +11 -4
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +29 -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 +2 -0
- package/dist/op/op-ir.d.ts.map +1 -1
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/operator.d.ts +97 -1
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +37 -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/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 +22 -1
- package/dist/op/steward.d.ts.map +1 -1
- package/dist/op/types.d.ts +7 -0
- package/dist/op/types.d.ts.map +1 -1
- package/dist/op/work-lease-run.d.ts +1 -1
- package/dist/op/work-lease-run.d.ts.map +1 -1
- 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-intent.d.ts +85 -0
- package/dist/workspace/box-intent.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 +104 -0
- package/dist/workspace/chant-migrations.d.ts.map +1 -0
- package/dist/workspace/checks/boxes.d.ts +47 -1
- package/dist/workspace/checks/boxes.d.ts.map +1 -1
- 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 +7 -0
- package/dist/workspace/checks/records.d.ts.map +1 -1
- package/dist/workspace/checks.d.ts +7 -0
- 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 +49 -4
- package/dist/workspace/decide.d.ts.map +1 -1
- package/dist/workspace/decision-points.schema.json +3 -3
- package/dist/workspace/declaration.d.ts +58 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +119 -1
- package/dist/workspace/declared-kinds.d.ts +20 -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-joins.d.ts +5 -5
- 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 +2 -0
- package/dist/workspace/points-cli.d.ts.map +1 -1
- package/dist/workspace/points.d.ts +4 -6
- package/dist/workspace/points.d.ts.map +1 -1
- package/dist/workspace/reason-codes.d.ts +16 -2
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/records-cli.d.ts +11 -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 +34 -4
- 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 +65 -1
- package/dist/workspace/status-stewards.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +24 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/work-cli.d.ts +113 -2
- package/dist/workspace/work-cli.d.ts.map +1 -1
- 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/graph.test.ts +20 -0
- package/src/cli/handlers/graph.ts +16 -2
- package/src/cli/handlers/operator.ts +34 -2
- package/src/cli/handlers/run.test.ts +154 -2
- package/src/cli/handlers/run.ts +121 -2
- package/src/cli/main.test.ts +10 -0
- package/src/cli/main.ts +23 -3
- package/src/cli/mcp/workspace-plugins.ts +6 -6
- package/src/cli/mcp/workspace-tools.test.ts +35 -19
- package/src/cli/mcp/workspace-tools.ts +62 -4
- package/src/cli/plugins.ts +11 -3
- package/src/cli/registry.ts +12 -2
- package/src/cli/serve-mcp-workspace.test.ts +6 -6
- 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/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/run-ledger.ts +6 -0
- package/src/lifecycle/symptoms.ts +95 -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 +308 -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 +119 -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/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 +18 -3
- package/src/op/local-executor.ts +151 -15
- package/src/op/local-output.test.ts +33 -0
- package/src/op/local-output.ts +20 -2
- package/src/op/op-ir.test.ts +10 -0
- package/src/op/op-ir.ts +4 -0
- package/src/op/op-verb-class.ts +1 -0
- package/src/op/operator.ts +290 -11
- package/src/op/runtime.ts +31 -8
- package/src/op/runtimes/local.ts +3 -1
- package/src/op/source-archive.ts +161 -0
- package/src/op/steward-points.test.ts +364 -0
- package/src/op/steward-points.ts +194 -0
- package/src/op/steward-turn.ts +79 -0
- package/src/op/steward.test.ts +87 -3
- package/src/op/steward.ts +25 -1
- package/src/op/types.ts +7 -0
- package/src/op/work-lease-run.test.ts +20 -1
- package/src/op/work-lease-run.ts +2 -2
- 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-intent.test.ts +205 -0
- package/src/workspace/box-intent.ts +159 -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 +169 -0
- package/src/workspace/check-contract.test.ts +4 -2
- package/src/workspace/check.schema.json +19 -5
- package/src/workspace/checks/boxes.test.ts +82 -2
- package/src/workspace/checks/boxes.ts +202 -1
- package/src/workspace/checks/diagrams.test.ts +134 -0
- package/src/workspace/checks/diagrams.ts +108 -0
- package/src/workspace/checks/records.ts +47 -0
- package/src/workspace/checks.ts +20 -2
- 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 +1 -1
- package/src/workspace/decide.ts +156 -23
- package/src/workspace/decision-points.schema.json +3 -3
- package/src/workspace/declaration.schema.json +119 -1
- package/src/workspace/declaration.test.ts +58 -0
- package/src/workspace/declaration.ts +112 -0
- package/src/workspace/declared-kinds.test.ts +31 -5
- package/src/workspace/declared-kinds.ts +46 -1
- 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-joins.test.ts +5 -5
- package/src/workspace/intent-joins.ts +5 -5
- package/src/workspace/intent.schema.json +8 -2
- 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/points-cli.ts +17 -3
- package/src/workspace/points-write.schema.json +11 -1
- package/src/workspace/points.schema.json +51 -0
- package/src/workspace/points.test.ts +16 -15
- package/src/workspace/points.ts +5 -17
- package/src/workspace/read-contract.test.ts +9 -1
- package/src/workspace/reason-codes.test.ts +18 -8
- package/src/workspace/reason-codes.ts +21 -2
- package/src/workspace/records-amend.schema.json +2 -0
- package/src/workspace/records-cli.ts +27 -4
- package/src/workspace/records-close.schema.json +2 -0
- package/src/workspace/records-formats.test.ts +15 -15
- 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-since.test.ts +8 -7
- 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 +36 -2
- package/src/workspace/records.test.ts +49 -4
- package/src/workspace/records.ts +109 -3
- package/src/workspace/status-contract.test.ts +14 -8
- package/src/workspace/status-gates.ts +9 -4
- package/src/workspace/status-stewards.ts +155 -5
- package/src/workspace/status.schema.json +129 -8
- package/src/workspace/status.ts +46 -1
- package/src/workspace/work-acceptance.test.ts +274 -0
- package/src/workspace/{work-cli.test.ts → work-cli.e2e.test.ts} +1 -1
- package/src/workspace/work-cli.ts +193 -10
- 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-readiness-chud.test.ts → work-readiness.test.ts} +30 -32
- package/src/workspace/work.test.ts +20 -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
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
import { z } from "zod";
|
|
27
27
|
import { activityContract } from "../activity-contract";
|
|
28
|
+
import { backendSchema } from "../decide-config";
|
|
28
29
|
|
|
29
30
|
export const lifecycleSnapshotContract = activityContract(
|
|
30
31
|
"lifecycleSnapshot",
|
|
@@ -54,8 +55,14 @@ export const shellCmdContract = activityContract(
|
|
|
54
55
|
env: z.record(z.string(), z.string()).optional(),
|
|
55
56
|
cwd: z.string().optional(),
|
|
56
57
|
okExit: z.array(z.number()).optional(),
|
|
58
|
+
gatedExit: z.number().optional(),
|
|
59
|
+
gate: z.strictObject({ op: z.string(), gate: z.string() }).optional(),
|
|
60
|
+
json: z.boolean().optional(),
|
|
57
61
|
}),
|
|
58
|
-
|
|
62
|
+
// `json` is stdout parsed, when the step sets `json` (#2787): whatever the
|
|
63
|
+
// command printed, so its shape is the author's and only the whole value is
|
|
64
|
+
// a reference target (`sh.out.json`).
|
|
65
|
+
z.object({ stdout: z.string(), stderr: z.string(), exitCode: z.number(), json: z.unknown().optional() }),
|
|
59
66
|
);
|
|
60
67
|
|
|
61
68
|
export const httpCheckContract = activityContract(
|
|
@@ -166,3 +173,185 @@ export const proposeWorkspaceUpgradeContract = activityContract(
|
|
|
166
173
|
summary: z.string(),
|
|
167
174
|
}),
|
|
168
175
|
);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The forward coverage check over an Op's own diff (#2773). `args` mirrors
|
|
179
|
+
* `ChangeCoverageArgs`. `returns` names what a step reads: whether the check
|
|
180
|
+
* passed, the range and work item checked, and each finding with the
|
|
181
|
+
* `triage` a work item seeded from it takes as its `source`.
|
|
182
|
+
*/
|
|
183
|
+
export const changeCoverageContract = activityContract(
|
|
184
|
+
"changeCoverage",
|
|
185
|
+
z.strictObject({
|
|
186
|
+
cwd: z.string().optional(),
|
|
187
|
+
range: z.string().optional(),
|
|
188
|
+
work: z.string().optional(),
|
|
189
|
+
severity: z.enum(["off", "warn", "fail"]).optional(),
|
|
190
|
+
}),
|
|
191
|
+
z.object({
|
|
192
|
+
ok: z.boolean(),
|
|
193
|
+
range: z.object({ spec: z.string(), base: z.string(), head: z.string() }),
|
|
194
|
+
work: z.string().nullable(),
|
|
195
|
+
severity: z.enum(["off", "warn", "fail"]),
|
|
196
|
+
findings: z.array(
|
|
197
|
+
z.object({
|
|
198
|
+
code: z.enum(["change-uncovered", "change-out-of-scope"]),
|
|
199
|
+
path: z.string(),
|
|
200
|
+
message: z.string(),
|
|
201
|
+
severity: z.enum(["warn", "fail"]),
|
|
202
|
+
records: z.array(z.string()),
|
|
203
|
+
triage: z.object({ finding: z.enum(["change-uncovered", "change-out-of-scope"]), region: z.string() }),
|
|
204
|
+
}),
|
|
205
|
+
),
|
|
206
|
+
summary: z.object({
|
|
207
|
+
paths: z.number(),
|
|
208
|
+
covered: z.number(),
|
|
209
|
+
uncovered: z.number(),
|
|
210
|
+
outOfScope: z.number(),
|
|
211
|
+
ignored: z.number(),
|
|
212
|
+
records: z.number(),
|
|
213
|
+
}),
|
|
214
|
+
}),
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Evidence for an acceptance criterion, under the run's work lease (#2772).
|
|
219
|
+
* `lease` is the run's lease, a reference the builder fills in, so it is not
|
|
220
|
+
* checked here. `returns` names what a step reads: the item, the record's
|
|
221
|
+
* path, the entry appended and the criteria counted with it.
|
|
222
|
+
*/
|
|
223
|
+
export const workEvidenceContract = activityContract(
|
|
224
|
+
"workEvidence",
|
|
225
|
+
z.strictObject({
|
|
226
|
+
lease: z.unknown(),
|
|
227
|
+
criterion: z.string(),
|
|
228
|
+
result: z.enum(["pass", "fail"]),
|
|
229
|
+
title: z.string(),
|
|
230
|
+
url: z.string().optional(),
|
|
231
|
+
path: z.string().optional(),
|
|
232
|
+
kind: z.string().optional(),
|
|
233
|
+
cwd: z.string().optional(),
|
|
234
|
+
}),
|
|
235
|
+
z.object({
|
|
236
|
+
item: z.string(),
|
|
237
|
+
path: z.string(),
|
|
238
|
+
evidence: z.record(z.string(), z.unknown()),
|
|
239
|
+
acceptance: z.object({ met: z.number(), total: z.number(), criteria: z.array(z.object({ id: z.string(), verification: z.string(), met: z.boolean() })) }),
|
|
240
|
+
}),
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The source-release activities (#2782, ./source-release.ts). A release Op
|
|
245
|
+
* reads `archive.out.digest` into its plan, `plan.out.digest` into its gate
|
|
246
|
+
* and its ship step, and `plan.out.file` into its record step.
|
|
247
|
+
*/
|
|
248
|
+
export const sourceArchiveContract = activityContract(
|
|
249
|
+
"sourceArchive",
|
|
250
|
+
z.strictObject({ path: z.string(), ref: z.string().optional(), out: z.string().optional(), cwd: z.string().optional() }),
|
|
251
|
+
z.object({ digest: z.string(), archive: z.string(), commit: z.string(), dir: z.string(), files: z.number(), bytes: z.number() }),
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
export const releasePlanContract = activityContract(
|
|
255
|
+
"releasePlan",
|
|
256
|
+
z.strictObject({
|
|
257
|
+
component: z.string(),
|
|
258
|
+
env: z.string(),
|
|
259
|
+
gitSha: z.string(),
|
|
260
|
+
content: z.record(z.string(), z.unknown()),
|
|
261
|
+
dir: z.string().optional(),
|
|
262
|
+
cwd: z.string().optional(),
|
|
263
|
+
}),
|
|
264
|
+
z.object({ digest: z.string(), file: z.string(), gitSha: z.string() }),
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
export const releaseRecordContract = activityContract(
|
|
268
|
+
"releaseRecord",
|
|
269
|
+
z.strictObject({
|
|
270
|
+
plan: z.string(),
|
|
271
|
+
digest: z.string().optional(),
|
|
272
|
+
approval: z.strictObject({ op: z.string(), gate: z.string() }).optional(),
|
|
273
|
+
actor: z.string().optional(),
|
|
274
|
+
runId: z.string().optional(),
|
|
275
|
+
cwd: z.string().optional(),
|
|
276
|
+
}),
|
|
277
|
+
z.object({ recorded: z.boolean(), digest: z.string(), env: z.string(), component: z.string(), approver: z.string().nullable() }),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* `decide` (#2740, core's since #2828). OPS012 checks a step's args against
|
|
282
|
+
* it and OPS013 a later step's reference into its result, so a misspelled
|
|
283
|
+
* `point` or a key written as a literal string fails `chant build` rather
|
|
284
|
+
* than a run.
|
|
285
|
+
*/
|
|
286
|
+
const decideEscalation = z.object({ kind: z.enum(["table", "model"]), reason: z.string() }).loose();
|
|
287
|
+
|
|
288
|
+
export const decideContract = activityContract(
|
|
289
|
+
"decide",
|
|
290
|
+
z.strictObject({
|
|
291
|
+
point: z.string().min(1),
|
|
292
|
+
inputs: z.record(z.string(), z.unknown()).optional(),
|
|
293
|
+
read: z.record(z.string(), z.string()).optional(),
|
|
294
|
+
subject: z.string().optional(),
|
|
295
|
+
kind: z.string().optional(),
|
|
296
|
+
cwd: z.string().optional(),
|
|
297
|
+
backends: z.record(z.string(), backendSchema).optional(),
|
|
298
|
+
dryRun: z.boolean().optional(),
|
|
299
|
+
}),
|
|
300
|
+
z.strictObject({
|
|
301
|
+
id: z.string(),
|
|
302
|
+
path: z.string(),
|
|
303
|
+
state: z.enum(["escalated", "proposed", "answered"]),
|
|
304
|
+
open: z.boolean(),
|
|
305
|
+
answer: z.union([z.string(), z.boolean(), z.null()]),
|
|
306
|
+
decider: z.string(),
|
|
307
|
+
model: z.string().nullable(),
|
|
308
|
+
backend: z.string().nullable(),
|
|
309
|
+
confidence: z.number().nullable(),
|
|
310
|
+
threshold: z.number().nullable(),
|
|
311
|
+
answeredBy: z.array(z.string()),
|
|
312
|
+
escalations: z.array(decideEscalation),
|
|
313
|
+
missing: z.array(z.string()),
|
|
314
|
+
}),
|
|
315
|
+
{ entities: ["point"] },
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* The rollback activities for a source release (#2800, ./source-rollback.ts).
|
|
320
|
+
* A rollback Op reads `plan.out.digest` into its gate, `plan.out.to` and the
|
|
321
|
+
* archive fields into the step that restores the Machine, and
|
|
322
|
+
* `plan.out.file` into its record step.
|
|
323
|
+
*/
|
|
324
|
+
export const releaseRollbackPlanContract = activityContract(
|
|
325
|
+
"releaseRollbackPlan",
|
|
326
|
+
z.strictObject({
|
|
327
|
+
component: z.string(),
|
|
328
|
+
env: z.string(),
|
|
329
|
+
to: z.string().optional(),
|
|
330
|
+
path: z.string().optional(),
|
|
331
|
+
dir: z.string().optional(),
|
|
332
|
+
cwd: z.string().optional(),
|
|
333
|
+
}),
|
|
334
|
+
z.object({
|
|
335
|
+
digest: z.string(),
|
|
336
|
+
file: z.string(),
|
|
337
|
+
to: z.string(),
|
|
338
|
+
from: z.string(),
|
|
339
|
+
gitSha: z.string(),
|
|
340
|
+
archive: z.string(),
|
|
341
|
+
archiveDigest: z.string(),
|
|
342
|
+
dir: z.string(),
|
|
343
|
+
}),
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
export const releaseRollbackRecordContract = activityContract(
|
|
347
|
+
"releaseRollbackRecord",
|
|
348
|
+
z.strictObject({
|
|
349
|
+
plan: z.string(),
|
|
350
|
+
digest: z.string().optional(),
|
|
351
|
+
approval: z.strictObject({ op: z.string(), gate: z.string() }).optional(),
|
|
352
|
+
actor: z.string().optional(),
|
|
353
|
+
runId: z.string().optional(),
|
|
354
|
+
cwd: z.string().optional(),
|
|
355
|
+
}),
|
|
356
|
+
z.object({ recorded: z.boolean(), digest: z.string(), env: z.string(), component: z.string(), approver: z.string().nullable() }),
|
|
357
|
+
);
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
import { exec } from "node:child_process";
|
|
36
36
|
import { promisify } from "node:util";
|
|
37
37
|
import { normalizeApply, type ApplyResult } from "../../apply";
|
|
38
|
+
import { importLexiconPackage } from "../../lexicon-module";
|
|
38
39
|
|
|
39
40
|
const execAsync = promisify(exec);
|
|
40
41
|
|
|
@@ -241,7 +242,7 @@ async function loadK8sApplier(): Promise<K8sApplier> {
|
|
|
241
242
|
const spec = "@intentius/chant-lexicon-k8s/op/activities";
|
|
242
243
|
let mod: { applyManifest?: K8sApplier };
|
|
243
244
|
try {
|
|
244
|
-
mod = (await
|
|
245
|
+
mod = (await importLexiconPackage(spec)) as { applyManifest?: K8sApplier };
|
|
245
246
|
} catch (err) {
|
|
246
247
|
throw new Error(
|
|
247
248
|
`apply target "kubectl" needs @intentius/chant-lexicon-k8s, which could not be loaded ` +
|
|
@@ -269,7 +270,7 @@ async function loadAzureApplier(): Promise<AzureApplier> {
|
|
|
269
270
|
};
|
|
270
271
|
let mod: AzureModule;
|
|
271
272
|
try {
|
|
272
|
-
mod = (await
|
|
273
|
+
mod = (await importLexiconPackage(spec)) as AzureModule;
|
|
273
274
|
} catch (err) {
|
|
274
275
|
throw new Error(
|
|
275
276
|
`apply target "arm" needs @intentius/chant-lexicon-azure, which could not be loaded ` +
|
|
@@ -304,7 +305,7 @@ async function loadGcpApplier(): Promise<GcpApplier> {
|
|
|
304
305
|
};
|
|
305
306
|
let mod: GcpModule;
|
|
306
307
|
try {
|
|
307
|
-
mod = (await
|
|
308
|
+
mod = (await importLexiconPackage(spec)) as GcpModule;
|
|
308
309
|
} catch (err) {
|
|
309
310
|
throw new Error(
|
|
310
311
|
`apply target "gcp" needs @intentius/chant-lexicon-gcp, which could not be loaded ` +
|
|
@@ -339,7 +340,7 @@ async function loadFlyApplier(): Promise<FlyApplier> {
|
|
|
339
340
|
};
|
|
340
341
|
let mod: FlyModule;
|
|
341
342
|
try {
|
|
342
|
-
mod = (await
|
|
343
|
+
mod = (await importLexiconPackage(spec)) as FlyModule;
|
|
343
344
|
} catch (err) {
|
|
344
345
|
throw new Error(
|
|
345
346
|
`apply target "fly" needs @intentius/chant-lexicon-fly, which could not be loaded ` +
|
|
@@ -370,7 +371,7 @@ async function loadAwsApplier(): Promise<AwsApplier> {
|
|
|
370
371
|
const spec = "@intentius/chant-lexicon-aws/op/activities";
|
|
371
372
|
let mod: { awsApply?: AwsApplier };
|
|
372
373
|
try {
|
|
373
|
-
mod = (await
|
|
374
|
+
mod = (await importLexiconPackage(spec)) as { awsApply?: AwsApplier };
|
|
374
375
|
} catch (err) {
|
|
375
376
|
throw new Error(
|
|
376
377
|
`apply target "cloudformation" needs @intentius/chant-lexicon-aws, which could not be loaded ` +
|
|
@@ -395,7 +396,7 @@ async function loadAwsRollback(): Promise<AwsRollback> {
|
|
|
395
396
|
const spec = "@intentius/chant-lexicon-aws/op/activities";
|
|
396
397
|
let mod: { rollbackStack?: AwsRollback };
|
|
397
398
|
try {
|
|
398
|
-
mod = (await
|
|
399
|
+
mod = (await importLexiconPackage(spec)) as { rollbackStack?: AwsRollback };
|
|
399
400
|
} catch (err) {
|
|
400
401
|
throw new Error(
|
|
401
402
|
`rollback for target "cloudformation" needs @intentius/chant-lexicon-aws, which could not be ` +
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* changeCoverage — the forward coverage check (#2773) as an Op activity, for
|
|
3
|
+
* an Op that changes the checkout (#2748) to run on its own diff.
|
|
4
|
+
*
|
|
5
|
+
* Such an Op's leased steps work in a worktree of their own on
|
|
6
|
+
* `chant/work/[<member>/]<item>`. Given that worktree as `cwd`
|
|
7
|
+
* (`workLeaseOutput("worktree")`) and no `range`, the activity checks the
|
|
8
|
+
* commits the branch holds beyond the main worktree's HEAD, with the branch's
|
|
9
|
+
* item as the work item in hand, exactly as `chant workspace check --changes
|
|
10
|
+
* <base>..HEAD --work <item>` would. A `range` or `work` given replaces what
|
|
11
|
+
* the branch says.
|
|
12
|
+
*
|
|
13
|
+
* The step fails when the check's severity is `fail` and it has a finding,
|
|
14
|
+
* or when the check can't run; otherwise it returns the document's findings
|
|
15
|
+
* and summary for later steps. The workspace code loads on first call, so
|
|
16
|
+
* importing core's activities loads nothing under `workspace/` (#2525 rule 5).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { ChangeFinding, ChangesDocument } from "../../workspace/changes";
|
|
20
|
+
|
|
21
|
+
export interface ChangeCoverageArgs {
|
|
22
|
+
/** The checkout to check: the Op's worktree. Default: the working directory. */
|
|
23
|
+
cwd?: string;
|
|
24
|
+
/** `<base>..<head>`, `<base>...<head>` or `<base>`. Default: the work branch's own commits. */
|
|
25
|
+
range?: string;
|
|
26
|
+
/** The work item in hand. Default: the work branch's item. */
|
|
27
|
+
work?: string;
|
|
28
|
+
/** In place of the declaration's `changes.severity`. */
|
|
29
|
+
severity?: "off" | "warn" | "fail";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ChangeCoverageResult {
|
|
33
|
+
ok: boolean;
|
|
34
|
+
range: { spec: string; base: string; head: string };
|
|
35
|
+
work: string | null;
|
|
36
|
+
severity: "off" | "warn" | "fail";
|
|
37
|
+
findings: Pick<ChangeFinding, "code" | "path" | "message" | "severity" | "records" | "triage">[];
|
|
38
|
+
summary: Exclude<ChangesDocument, { error: unknown }>["summary"];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function changeCoverage(args: ChangeCoverageArgs = {}): Promise<ChangeCoverageResult> {
|
|
42
|
+
const { checkChanges, workBranchChanges } = await import("../../workspace/changes");
|
|
43
|
+
const cwd = args.cwd ?? process.cwd();
|
|
44
|
+
const branch = args.range === undefined ? workBranchChanges(cwd) : undefined;
|
|
45
|
+
const range = args.range ?? branch?.range;
|
|
46
|
+
if (range === undefined) throw new Error(`changeCoverage: ${cwd} is not on a chant/work/ branch, so give the range to check`);
|
|
47
|
+
const work = args.work ?? branch?.work;
|
|
48
|
+
const { doc } = await checkChanges({ cwd, range, ...(work !== undefined ? { work } : {}), ...(args.severity ? { severity: args.severity } : {}) });
|
|
49
|
+
if ("error" in doc) throw new Error(`changeCoverage: ${doc.error.code}: ${doc.error.message}`);
|
|
50
|
+
const result: ChangeCoverageResult = {
|
|
51
|
+
ok: doc.ok,
|
|
52
|
+
range: doc.range,
|
|
53
|
+
work: doc.work?.record ?? null,
|
|
54
|
+
severity: doc.severity,
|
|
55
|
+
findings: doc.findings.map(({ code, path, message, severity, records, triage }) => ({ code, path, message, severity, records, triage })),
|
|
56
|
+
summary: doc.summary,
|
|
57
|
+
};
|
|
58
|
+
if (!doc.ok) throw new Error(`changeCoverage: ${doc.findings.length} change ${doc.findings.length === 1 ? "finding" : "findings"} at severity fail: ${doc.findings.map((f) => `${f.code} ${f.path}`).join(", ")}`);
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
2
|
import { eq, gt, run, report, when } from "../converge-rule";
|
|
3
|
-
import type
|
|
3
|
+
import { parseResourceObservation, type ConvergeSymptom, type ObservedResource, type ResourceSymptom } from "../../lifecycle/symptoms";
|
|
4
4
|
import type { ConvergeTickRecord, ConvergeRuleOutcome } from "../../lifecycle/converge-ledger";
|
|
5
5
|
import {
|
|
6
6
|
planConvergeTick,
|
|
7
|
+
planResourceTick,
|
|
8
|
+
consecutiveResourceFires,
|
|
7
9
|
verbClassAllowedToDispatch,
|
|
8
10
|
enforceVerbClassAtDispatch,
|
|
9
11
|
sanitizeOneLine,
|
|
@@ -354,3 +356,55 @@ describe("classifyDispatchFailure", () => {
|
|
|
354
356
|
expect(classifyDispatchFailure("")).toBeUndefined();
|
|
355
357
|
});
|
|
356
358
|
});
|
|
359
|
+
|
|
360
|
+
describe("planResourceTick — rules evaluated once per observed resource (#2778)", () => {
|
|
361
|
+
const restart = when<ResourceSymptom>(eq("status", "drifted"), run("restart-service"), { id: "restart-drifted", why: "Restart a drifted service." });
|
|
362
|
+
const unknownR = when<ResourceSymptom>(eq("status", "unknown"), report("not observed"), { id: "report-unknown", why: "unknown never remediates." });
|
|
363
|
+
const resources: ObservedResource[] = [
|
|
364
|
+
{ name: "app", status: "drifted", detail: "stopped" },
|
|
365
|
+
{ name: "hud", status: "in-sync" },
|
|
366
|
+
{ name: "door", status: "drifted" },
|
|
367
|
+
{ name: "site", status: "unknown", detail: "no health" },
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
test("a fired run() is planned for each drifted resource, and names it", () => {
|
|
371
|
+
const plan = planResourceTick("box", resources, [restart, unknownR], [], "box-converge", "apply", 3);
|
|
372
|
+
expect(plan.firedRuleIds).toEqual(["restart-drifted", "report-unknown"]);
|
|
373
|
+
expect(plan.outcomes).toEqual([
|
|
374
|
+
{ ruleId: "restart-drifted", resource: "app", action: "ran", op: "restart-service" },
|
|
375
|
+
{ ruleId: "restart-drifted", resource: "door", action: "ran", op: "restart-service" },
|
|
376
|
+
{ ruleId: "report-unknown", resource: "site", action: "reported", reason: "not observed" },
|
|
377
|
+
]);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test("unknown never remediates, the dial and the budget hold per tick", () => {
|
|
381
|
+
const anyStatus = when<ResourceSymptom>(eq("env", "box"), run("restart-service"), { id: "restart-all", why: "x" });
|
|
382
|
+
const plan = planResourceTick("box", [{ name: "site", status: "unknown" }], [anyStatus], [], "box-converge", "apply", 3);
|
|
383
|
+
expect(plan.outcomes[0]).toMatchObject({ action: "reported", resource: "site", reason: expect.stringMatching(/unknown never remediates/) });
|
|
384
|
+
expect(planResourceTick("box", resources, [restart], [], "box-converge", "observe", 3).outcomes.map((o) => o.action)).toEqual(["reported", "reported"]);
|
|
385
|
+
expect(planResourceTick("box", resources, [restart], [], "box-converge", "apply", 1).outcomes.map((o) => o.action)).toEqual(["ran", "skipped-budget"]);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
test("flap damping counts one rule's fires for one resource, on this op's ticks", () => {
|
|
389
|
+
const fired = (resource: string, op = "box-converge") =>
|
|
390
|
+
tick({ op, firedRuleIds: ["restart-drifted"], outcomes: [{ ruleId: "restart-drifted", action: "ran", op: "restart-service", resource }] });
|
|
391
|
+
const prior = [fired("app"), fired("app"), fired("hud", "other-converge"), fired("app")];
|
|
392
|
+
expect(consecutiveResourceFires(prior, "box-converge", "restart-drifted", "app")).toBe(3);
|
|
393
|
+
expect(consecutiveResourceFires(prior, "box-converge", "restart-drifted", "door")).toBe(0);
|
|
394
|
+
const plan = planResourceTick("box", resources, [restart], prior, "box-converge", "apply", 3);
|
|
395
|
+
expect(plan.outcomes.map((o) => [o.resource, o.action])).toEqual([["app", "skipped-flap"], ["door", "ran"]]);
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
describe("parseResourceObservation (#2778)", () => {
|
|
400
|
+
test("reads an observation, or a shell result that prints one, and refuses anything else", () => {
|
|
401
|
+
const observation = { resources: [{ name: "app", status: "drifted", detail: "stopped" }] };
|
|
402
|
+
expect(parseResourceObservation(observation)).toEqual(observation);
|
|
403
|
+
expect(parseResourceObservation({ stdout: JSON.stringify(observation), stderr: "", exitCode: 0 })).toEqual(observation);
|
|
404
|
+
expect(() => parseResourceObservation({ stdout: "nope", stderr: "", exitCode: 0 })).toThrow(/not JSON/);
|
|
405
|
+
expect(() => parseResourceObservation({})).toThrow(/no `resources` array/);
|
|
406
|
+
expect(() => parseResourceObservation({ resources: [{ name: "app", status: "down" }] })).toThrow(/in-sync, drifted or unknown/);
|
|
407
|
+
expect(() => parseResourceObservation({ resources: [{ status: "drifted" }] })).toThrow(/has no name/);
|
|
408
|
+
expect(() => parseResourceObservation({ resources: [{ name: "a", status: "drifted" }, { name: "a", status: "in-sync" }] })).toThrow(/twice/);
|
|
409
|
+
});
|
|
410
|
+
});
|