@intentius/chant 0.91.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/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-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/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/boxes.d.ts +34 -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 +3 -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/declaration.d.ts +52 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +114 -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.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.map +1 -1
- package/dist/workspace/points.d.ts +1 -1
- package/dist/workspace/reason-codes.d.ts +14 -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 +59 -1
- package/dist/workspace/status-stewards.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +16 -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 +19 -0
- 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/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 +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 +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 +313 -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/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 +4 -2
- package/src/workspace/check.schema.json +15 -5
- package/src/workspace/checks/boxes.test.ts +80 -1
- package/src/workspace/checks/boxes.ts +136 -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 +8 -1
- 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/declaration.schema.json +114 -1
- package/src/workspace/declaration.test.ts +58 -0
- package/src/workspace/declaration.ts +104 -0
- package/src/workspace/declared-kinds.test.ts +5 -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.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 +14 -3
- package/src/workspace/points-write.schema.json +11 -1
- package/src/workspace/points.schema.json +33 -0
- package/src/workspace/points.test.ts +1 -1
- package/src/workspace/points.ts +1 -1
- package/src/workspace/read-contract.test.ts +1 -1
- package/src/workspace/reason-codes.test.ts +11 -1
- package/src/workspace/reason-codes.ts +18 -2
- package/src/workspace/records-amend.schema.json +2 -0
- package/src/workspace/records-cli.ts +13 -3
- package/src/workspace/records-close.schema.json +2 -0
- 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 +36 -2
- package/src/workspace/records.test.ts +48 -3
- package/src/workspace/records.ts +109 -3
- package/src/workspace/status-contract.test.ts +13 -8
- package/src/workspace/status-gates.ts +9 -4
- package/src/workspace/status-stewards.ts +108 -4
- package/src/workspace/status.schema.json +111 -7
- package/src/workspace/status.ts +36 -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.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
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chud-lexicon-exit-ship-inputs` (#2811): the release Op asks the ship-skip
|
|
3
|
+
* point with the inputs the point declares.
|
|
4
|
+
*
|
|
5
|
+
* The release Op `chud-lexicon-exit` (0.92.0) wrote asks `ship-skip` with no
|
|
6
|
+
* inputs, so the point's table can only give its default row. This migration
|
|
7
|
+
* makes the Op compute the point's `release.*` inputs when it loads, from the
|
|
8
|
+
* diff between the commit the `fly` site serves (the last release in its
|
|
9
|
+
* ledger) and HEAD, and pass the ones the point declares to `decide`:
|
|
10
|
+
*
|
|
11
|
+
* - `first_release`: no release in the ledger;
|
|
12
|
+
* - `new_migrations`: `.sql` files added or changed under the app's
|
|
13
|
+
* migrations folder;
|
|
14
|
+
* - `files_changed`: paths changed;
|
|
15
|
+
* - `app_changed`: a path under the app member;
|
|
16
|
+
* - `work_changed`: a path under the directory a declared work kind keeps its
|
|
17
|
+
* items in (chud's `contracts_changed`);
|
|
18
|
+
* - `units`: work item files added or changed.
|
|
19
|
+
*
|
|
20
|
+
* A first release, or one whose serving commit this clone lacks, counts every
|
|
21
|
+
* file on HEAD, as chud's release plan did. The inputs are not part of the
|
|
22
|
+
* release plan, which keeps the answer and its decider, so a retry of a
|
|
23
|
+
* shipped commit plans the same digest.
|
|
24
|
+
*
|
|
25
|
+
* The plan is empty unless the member's release Op is the one
|
|
26
|
+
* `chud-lexicon-exit` wrote and still asks `ship-skip` with no inputs. A
|
|
27
|
+
* release Op the project changed so that an anchor is gone is a conflict.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
31
|
+
import { join, posix } from "node:path";
|
|
32
|
+
import type { ChantMigration, ChantMigrationContext, ChantMigrationPlan, PlanConflict, PlannedChange } from "../chant-migrations";
|
|
33
|
+
import { CHUD_LEXICON_EXIT } from "./chud-lexicon-exit";
|
|
34
|
+
|
|
35
|
+
export const CHUD_LEXICON_EXIT_SHIP_INPUTS = "chud-lexicon-exit-ship-inputs";
|
|
36
|
+
|
|
37
|
+
const DESCRIPTION = "have the release Op ask ship-skip with the inputs the point declares, from the diff since the serving release (#2811)";
|
|
38
|
+
|
|
39
|
+
/** The call chud-lexicon-exit wrote: no inputs. */
|
|
40
|
+
const ASKED_BARE = 'const shipSkip = decide("ship-skip", { id: "shipSkip" });';
|
|
41
|
+
|
|
42
|
+
/** Where a declared work kind keeps its items, from the workspace root: what `release.work_changed` and `release.units` count. */
|
|
43
|
+
export interface WorkItems {
|
|
44
|
+
dir: string;
|
|
45
|
+
/** The kind's `location.match`, a regular expression over a file's name. */
|
|
46
|
+
match: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface Declaration {
|
|
50
|
+
members?: Array<{ name?: string; dir?: string; kind?: string; records?: Array<{ kind?: string }> }>;
|
|
51
|
+
records?: Array<{ kind?: string }>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readText(dir: string, path: string): string | undefined {
|
|
55
|
+
const abs = join(dir, path);
|
|
56
|
+
return existsSync(abs) ? readFileSync(abs, "utf-8") : undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Where each declared work kind keeps its items, read from the kind file's
|
|
61
|
+
* text: a kind with a `work` block, its `location.dir` and `location.match`.
|
|
62
|
+
*/
|
|
63
|
+
export function workItemsOf(dir: string, decl: Declaration | null): WorkItems[] {
|
|
64
|
+
const out: WorkItems[] = [];
|
|
65
|
+
const kinds = [...(decl?.records ?? []), ...(decl?.members ?? []).flatMap((m) => (m.records ?? []).map((r) => ({ kind: r.kind && m.dir ? posix.join(m.dir, r.kind) : undefined })))];
|
|
66
|
+
for (const { kind } of kinds) {
|
|
67
|
+
if (!kind) continue;
|
|
68
|
+
const text = readText(dir, kind);
|
|
69
|
+
if (!text || !/\bwork:\s*\{/.test(text)) continue;
|
|
70
|
+
const loc = /location:\s*\{\s*dir:\s*("(?:[^"\\]|\\.)*"),\s*match:\s*("(?:[^"\\]|\\.)*")/.exec(text);
|
|
71
|
+
if (!loc) continue;
|
|
72
|
+
try {
|
|
73
|
+
out.push({ dir: posix.normalize(posix.join(posix.dirname(kind), JSON.parse(loc[1]) as string)), match: JSON.parse(loc[2]) as string });
|
|
74
|
+
} catch {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The code that computes the inputs and asks the point with them, in place of {@link ASKED_BARE}. */
|
|
82
|
+
export function askedWithInputs(rootRel: string, appDir: string, work: WorkItems[]): string {
|
|
83
|
+
return `/** The workspace root, which the diff names paths from. */
|
|
84
|
+
const root = fileURLToPath(new URL(${JSON.stringify(rootRel === "." ? "./" : `${rootRel}/`)}, import.meta.url));
|
|
85
|
+
/** The app member and the work items, from the workspace root. */
|
|
86
|
+
const APP = ${JSON.stringify(appDir)};
|
|
87
|
+
const WORK: Array<{ dir: string; match: string }> = ${JSON.stringify(work)};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The ship-skip point's inputs: what this release would change since the
|
|
91
|
+
* commit the site serves, the last release in the ledger. A first release
|
|
92
|
+
* (or one whose serving commit this clone lacks) counts every file on HEAD.
|
|
93
|
+
*/
|
|
94
|
+
async function shipSkipInputs(): Promise<Record<string, boolean | number>> {
|
|
95
|
+
const git = (...args: string[]) => execFileSync("git", args, { cwd: root, encoding: "utf-8" });
|
|
96
|
+
const lines = (text: string) => text.split("\\n").filter(Boolean);
|
|
97
|
+
const { records } = await readReleaseLedger(ENV, { cwd: fileURLToPath(new URL("../", import.meta.url)) });
|
|
98
|
+
const serving = records.at(-1)?.gitSha;
|
|
99
|
+
let known = false;
|
|
100
|
+
if (serving) {
|
|
101
|
+
try {
|
|
102
|
+
git("cat-file", "-e", \`\${serving}^{commit}\`);
|
|
103
|
+
known = true;
|
|
104
|
+
} catch {
|
|
105
|
+
known = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const all = known ? lines(git("diff", "--name-only", "--relative", serving!, "HEAD")) : lines(git("ls-tree", "-r", "--name-only", "HEAD"));
|
|
109
|
+
const added = known ? lines(git("diff", "--name-only", "--relative", "--diff-filter=AM", serving!, "HEAD")) : all;
|
|
110
|
+
const under = (dir: string, path: string) => dir === "." || path.startsWith(\`\${dir}/\`);
|
|
111
|
+
const migrations = posix.join(APP, params.appMigrations.default);
|
|
112
|
+
const workItems = added.filter((p) => WORK.some((w) => posix.dirname(p) === posix.normalize(w.dir) && new RegExp(w.match).test(posix.basename(p))));
|
|
113
|
+
return {
|
|
114
|
+
"release.first_release": !serving,
|
|
115
|
+
"release.new_migrations": added.filter((p) => under(migrations, p) && p.endsWith(".sql")).length,
|
|
116
|
+
"release.files_changed": all.length,
|
|
117
|
+
"release.app_changed": all.some((p) => under(APP, p)),
|
|
118
|
+
"release.work_changed": all.some((p) => WORK.some((w) => under(posix.normalize(w.dir), p))),
|
|
119
|
+
"release.units": workItems.length,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Only the inputs the point declares: a point that declares fewer is asked with those. */
|
|
124
|
+
const declared = new Set(Object.keys(shipSkipPoint.inputs));
|
|
125
|
+
const inputs = Object.fromEntries(Object.entries(await shipSkipInputs()).filter(([name]) => declared.has(name)));
|
|
126
|
+
const shipSkip = decide("ship-skip", { id: "shipSkip", inputs });`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Each edit: the text chud-lexicon-exit wrote, and what it becomes. A \`find\` may be a pattern, for text that differs between the exit's versions. */
|
|
130
|
+
function edits(rootRel: string, appDir: string, work: WorkItems[]): Array<{ find: string | RegExp; replace: string; what: string; optional?: boolean }> {
|
|
131
|
+
return [
|
|
132
|
+
{ find: ASKED_BARE, replace: askedWithInputs(rootRel, appDir, work), what: "the ship-skip decide step" },
|
|
133
|
+
{ find: 'import { readFileSync } from "node:fs";\n', replace: 'import { readFileSync } from "node:fs";\nimport { posix } from "node:path";\n', what: "the node:fs import" },
|
|
134
|
+
{
|
|
135
|
+
find: 'import { parsePoints, quorumOf } from "@intentius/chant/workspace/points";\n',
|
|
136
|
+
replace: 'import { parsePoints, quorumOf } from "@intentius/chant/workspace/points";\nimport { readReleaseLedger } from "@intentius/chant/lifecycle/release-ledger";\n',
|
|
137
|
+
what: "the workspace/points import",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
// 0.92.0 named the systemone lexicon's decide; later exits name chant's.
|
|
141
|
+
find: /( \* workspace root, through (?:the systemone lexicon's|chant's) `decide` activity), and\n \* writes the release plan:/,
|
|
142
|
+
replace:
|
|
143
|
+
"$1, with\n * the inputs it declares, computed from the diff between the commit the\n * `fly` site serves (the last release in its ledger) and HEAD: whether\n * this is the first release, how many migrations would fire, how many files\n * changed, whether the app or the work items changed, and how many work\n * items did (on a first release, every file on HEAD counts). It\n * writes the release plan:",
|
|
144
|
+
what: "the release Op's comment on Plan",
|
|
145
|
+
// The comment is prose: a project that reworded it keeps its words.
|
|
146
|
+
optional: true,
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function planShipInputs(ctx: ChantMigrationContext): ChantMigrationPlan | null {
|
|
152
|
+
const { dir } = ctx;
|
|
153
|
+
let decl: Declaration | null = null;
|
|
154
|
+
try {
|
|
155
|
+
decl = JSON.parse(readText(dir, "chant.workspace.json") ?? "null") as Declaration | null;
|
|
156
|
+
} catch {
|
|
157
|
+
decl = null;
|
|
158
|
+
}
|
|
159
|
+
const candidates = (decl?.members ?? []).filter((m) => m.kind === "chant" && m.dir).map((m) => posix.normalize(m.dir!));
|
|
160
|
+
if (!candidates.includes("delivery")) candidates.push("delivery");
|
|
161
|
+
const appDir = decl?.members?.find((m) => m.name === "app")?.dir ?? "app";
|
|
162
|
+
const work = workItemsOf(dir, decl);
|
|
163
|
+
|
|
164
|
+
const changes: PlannedChange[] = [];
|
|
165
|
+
const conflicts: PlanConflict[] = [];
|
|
166
|
+
for (const d of candidates) {
|
|
167
|
+
const path = posix.join(d, "ops/release.op.ts");
|
|
168
|
+
const text = readText(dir, path);
|
|
169
|
+
if (text === undefined || !text.includes(`its migration ${CHUD_LEXICON_EXIT}`) || !text.includes("flyRelease(")) continue;
|
|
170
|
+
if (!text.includes(ASKED_BARE)) continue;
|
|
171
|
+
let next = text;
|
|
172
|
+
const missing: string[] = [];
|
|
173
|
+
for (const e of edits(posix.relative(posix.join(d, "ops"), ".") || ".", posix.normalize(appDir), work)) {
|
|
174
|
+
const hit = typeof e.find === "string" ? next.includes(e.find) : e.find.test(next);
|
|
175
|
+
if (!hit) {
|
|
176
|
+
if (!e.optional) missing.push(e.what);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
next = typeof e.find === "string" ? next.replace(e.find, () => e.replace) : next.replace(e.find, e.replace);
|
|
180
|
+
}
|
|
181
|
+
if (missing.length > 0) {
|
|
182
|
+
conflicts.push({ path, reason: `cannot find ${missing.join("; ")}. Pass ship-skip its inputs by hand, then run the upgrade again` });
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
changes.push({ path, action: "write", why: "ship-skip is asked with the inputs the point declares, from the diff since the serving release", data: Buffer.from(next) });
|
|
186
|
+
}
|
|
187
|
+
if (changes.length === 0 && conflicts.length === 0) return null;
|
|
188
|
+
return { id: CHUD_LEXICON_EXIT_SHIP_INPUTS, description: DESCRIPTION, changes, notMoved: [], conflicts };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const chudLexiconExitShipInputs: ChantMigration = {
|
|
192
|
+
id: CHUD_LEXICON_EXIT_SHIP_INPUTS,
|
|
193
|
+
description: DESCRIPTION,
|
|
194
|
+
plan: planShipInputs,
|
|
195
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chud-lexicon-exit-ship-policy` (#2810): let a person pass the ship gate
|
|
3
|
+
* in a repo `chud-lexicon-exit` migrated.
|
|
4
|
+
*
|
|
5
|
+
* `chud-lexicon-exit` (0.92.0) kept chud's decisions/ship-skip.cedar.ts,
|
|
6
|
+
* which permits an agent when the ship-skip table said yes and permits no
|
|
7
|
+
* person. Cedar denies what nothing permits, so it decided `deny` on a
|
|
8
|
+
* person's approval too, and only `log-only` let one through. This migration
|
|
9
|
+
* adds a permit for `Chant::Human` under the same floor, which still forbids
|
|
10
|
+
* an agent unless the table said yes. At `enforce`, Cedar then decides
|
|
11
|
+
* `allow` for a person and `deny` for an agent.
|
|
12
|
+
*
|
|
13
|
+
* The plan is empty unless the policy is the one `chud-lexicon-exit` left
|
|
14
|
+
* (it reads the decide step's `shipSkipBy`), and once the permit is there. A
|
|
15
|
+
* policy the project changed so that an anchor is gone is a conflict.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { posix } from "node:path";
|
|
19
|
+
import type { ChantMigration, ChantMigrationContext, ChantMigrationPlan, PlanConflict, PlannedChange } from "../chant-migrations";
|
|
20
|
+
import { applyEdits, readText, type Edit } from "./chud-lexicon-exit";
|
|
21
|
+
|
|
22
|
+
export const CHUD_LEXICON_EXIT_SHIP_POLICY = "chud-lexicon-exit-ship-policy";
|
|
23
|
+
|
|
24
|
+
const DESCRIPTION = "let a person pass the ship gate: the Cedar policy chud-lexicon-exit kept permits no person (#2810)";
|
|
25
|
+
|
|
26
|
+
/** The policy `chud-lexicon-exit` left: chud's, reading the decide step's answer and decider. */
|
|
27
|
+
function isExitPolicy(text: string): boolean {
|
|
28
|
+
return text.includes('context.shipSkipBy == "table"') && text.includes("agentSkipsOnTableYes") && !/export const personApproves\b/.test(text);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const SHIP_POLICY_EDITS: Edit[] = [
|
|
32
|
+
{
|
|
33
|
+
find: `import { DenyByDefaultSet, Policy, gatePolicy, GATE_AGENT_TYPE, PASS_GATE_ACTION } from "@intentius/chant-lexicon-cedar";`,
|
|
34
|
+
replace: `import { DenyByDefaultSet, Policy, gatePolicy, GATE_AGENT_TYPE, GATE_HUMAN_TYPE, PASS_GATE_ACTION } from "@intentius/chant-lexicon-cedar";`,
|
|
35
|
+
required: "the import from @intentius/chant-lexicon-cedar",
|
|
36
|
+
unless: /GATE_HUMAN_TYPE/,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
find: "const agent = GATE_AGENT_TYPE as never;\n",
|
|
40
|
+
replace: "const person = GATE_HUMAN_TYPE as never;\nconst agent = GATE_AGENT_TYPE as never;\n",
|
|
41
|
+
required: "the `agent` principal type",
|
|
42
|
+
unless: /const person = GATE_HUMAN_TYPE/,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
find: "export const agentSkipsOnTableYes = new Policy({",
|
|
46
|
+
replace: `/** A person may pass the gate: it is where a person approves the release. */
|
|
47
|
+
export const personApproves = new Policy({
|
|
48
|
+
effect: "permit",
|
|
49
|
+
principal: { is: person },
|
|
50
|
+
action: { eq: passGate },
|
|
51
|
+
annotations: { id: "a-person-approves" },
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const agentSkipsOnTableYes = new Policy({`,
|
|
55
|
+
required: "the agentSkipsOnTableYes policy",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
find: " policies: [agentSkipsOnTableYes],\n",
|
|
59
|
+
replace: " policies: [personApproves, agentSkipsOnTableYes],\n",
|
|
60
|
+
required: "the DenyByDefaultSet's `policies`",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
find: " * The rule: an agent may pass the gate only when the decision table said yes.\n",
|
|
64
|
+
replace: " * The rule: a person may always pass the gate, and an agent only when the\n * decision table said yes.\n",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
find: " * every release until someone adds a row, so by default a person always\n * approves.\n",
|
|
68
|
+
replace: " * every release until someone adds a row, so by default a person always\n * approves. In `enforce` mode Cedar decides `allow` on a person's approval\n * and `deny` on an agent's.\n",
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
interface Declaration {
|
|
73
|
+
members?: Array<{ dir?: string; kind?: string }>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function planShipPolicy(ctx: ChantMigrationContext): ChantMigrationPlan | null {
|
|
77
|
+
const { dir } = ctx;
|
|
78
|
+
let decl: Declaration | null = null;
|
|
79
|
+
try {
|
|
80
|
+
decl = JSON.parse(readText(dir, "chant.workspace.json") ?? "null") as Declaration | null;
|
|
81
|
+
} catch {
|
|
82
|
+
decl = null;
|
|
83
|
+
}
|
|
84
|
+
const candidates = (decl?.members ?? []).filter((m) => m.kind === "chant" && m.dir).map((m) => posix.normalize(m.dir!));
|
|
85
|
+
if (!candidates.includes("delivery")) candidates.push("delivery");
|
|
86
|
+
|
|
87
|
+
const changes: PlannedChange[] = [];
|
|
88
|
+
const conflicts: PlanConflict[] = [];
|
|
89
|
+
for (const d of candidates) {
|
|
90
|
+
const path = posix.join(d, "decisions/ship-skip.cedar.ts");
|
|
91
|
+
const text = readText(dir, path);
|
|
92
|
+
if (text === undefined || !isExitPolicy(text)) continue;
|
|
93
|
+
const edited = applyEdits(text, SHIP_POLICY_EDITS);
|
|
94
|
+
if (edited.missing.length > 0) {
|
|
95
|
+
conflicts.push({ path, reason: `cannot find ${edited.missing.join("; ")}. Add a permit for Chant::Human by hand, then run the upgrade again` });
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
changes.push({ path, action: "write", why: "a person may pass the ship gate; an agent only when the table said yes", data: Buffer.from(edited.text) });
|
|
99
|
+
}
|
|
100
|
+
if (changes.length === 0 && conflicts.length === 0) return null;
|
|
101
|
+
return { id: CHUD_LEXICON_EXIT_SHIP_POLICY, description: DESCRIPTION, changes, notMoved: [], conflicts };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const chudLexiconExitShipPolicy: ChantMigration = {
|
|
105
|
+
id: CHUD_LEXICON_EXIT_SHIP_POLICY,
|
|
106
|
+
description: DESCRIPTION,
|
|
107
|
+
plan: planShipPolicy,
|
|
108
|
+
};
|