@intentius/chant 0.124.31 → 0.124.32
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/bin/chant +7 -2
- package/dist/cli/commands/check-lexicon-plugin.d.ts +7 -4
- package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-plugin.js +10 -7
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.js +18 -12
- package/dist/cli/commands/import.d.ts +10 -0
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +37 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.js +4 -3
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/commands/onboard.js +8 -4
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +2 -1
- package/dist/cli/dependencies.d.ts +18 -0
- package/dist/cli/dependencies.d.ts.map +1 -0
- package/dist/cli/dependencies.js +120 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +23 -4
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +12 -4
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +16 -6
- package/dist/cli/handlers/lint.d.ts.map +1 -1
- package/dist/cli/handlers/lint.js +6 -0
- package/dist/cli/handlers/operator.d.ts +2 -2
- package/dist/cli/handlers/operator.js +3 -3
- package/dist/cli/handlers/pr.d.ts +14 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +488 -32
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +3 -1
- package/dist/cli/handlers/run.d.ts +13 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +38 -15
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +44 -16
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +15 -0
- package/dist/cli/registry.d.ts +13 -4
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +6 -2
- package/dist/codegen/generate-post-synth-barrel.js +2 -2
- package/dist/codegen/lexicon-regen.d.ts +4 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.js +1 -1
- package/dist/codegen/pinned-upgrade.js +2 -2
- package/dist/components/capability.d.ts +44 -3
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/capability.js +21 -0
- package/dist/components/changed-files.d.ts +7 -1
- package/dist/components/changed-files.d.ts.map +1 -1
- package/dist/components/changed-files.js +9 -1
- package/dist/components/driver.d.ts +38 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +47 -6
- package/dist/components/fan-out-record.d.ts +6 -1
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/fan-out-record.js +24 -0
- package/dist/components/fan-out-run.d.ts +20 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +21 -1
- package/dist/components/pr-pipeline.d.ts +65 -2
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +107 -15
- package/dist/components/pr-run.d.ts +127 -29
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +290 -70
- package/dist/components/wave-plan.d.ts +5 -2
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +12 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-import.js +16 -6
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.js +6 -0
- package/dist/discovery/specifier-resolve.d.ts.map +1 -1
- package/dist/discovery/specifier-resolve.js +8 -2
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/fold/fold.js +68 -1
- package/dist/fold/subset.d.ts +37 -0
- package/dist/fold/subset.d.ts.map +1 -1
- package/dist/fold/subset.js +88 -0
- package/dist/lexicon-module.d.ts +10 -0
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lexicon-module.js +53 -8
- package/dist/lexicon-plugin-helpers.d.ts.map +1 -1
- package/dist/lexicon-plugin-helpers.js +6 -4
- package/dist/lexicon.d.ts +2 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/affected.d.ts.map +1 -1
- package/dist/lifecycle/affected.js +7 -1
- package/dist/lifecycle/release-ledger.d.ts +21 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.js +24 -0
- package/dist/lifecycle/work-dir.d.ts +45 -0
- package/dist/lifecycle/work-dir.d.ts.map +1 -0
- package/dist/lifecycle/work-dir.js +78 -0
- package/dist/lint/discover.d.ts +17 -9
- package/dist/lint/discover.d.ts.map +1 -1
- package/dist/lint/discover.js +62 -54
- package/dist/module-source.d.ts +57 -0
- package/dist/module-source.d.ts.map +1 -0
- package/dist/module-source.js +104 -0
- package/dist/op/activities/factory.js +1 -1
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +13 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +3 -0
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +20 -5
- package/dist/op/operator.d.ts +2 -2
- package/dist/op/operator.js +2 -2
- package/dist/op/steward.d.ts +6 -4
- package/dist/op/steward.d.ts.map +1 -1
- package/dist/op/steward.js +5 -3
- package/dist/op/work-lease-run.d.ts +20 -7
- package/dist/op/work-lease-run.d.ts.map +1 -1
- package/dist/op/work-lease-run.js +56 -12
- package/dist/pr-forge.d.ts +10 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +39 -0
- package/dist/pr-loop.d.ts +141 -4
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +122 -6
- package/dist/pr-report-url.d.ts +2 -2
- package/dist/pr-report-url.d.ts.map +1 -1
- package/dist/pr-report-url.js +5 -5
- package/dist/ts-loader.d.ts +38 -4
- package/dist/ts-loader.d.ts.map +1 -1
- package/dist/ts-loader.js +190 -16
- package/dist/wave-runtime.mjs +208 -208
- package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts +34 -0
- package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/fountain-retired-kinds.js +176 -0
- package/dist/workspace/chant-migrations.d.ts.map +1 -1
- package/dist/workspace/chant-migrations.js +2 -0
- package/dist/workspace/checks/boxes.d.ts +6 -6
- package/dist/workspace/checks/boxes.js +9 -9
- package/dist/workspace/ci-green-forge.d.ts +6 -4
- package/dist/workspace/ci-green-forge.d.ts.map +1 -1
- package/dist/workspace/ci-green.d.ts +28 -12
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +49 -21
- package/dist/workspace/ci-list.schema.json +12 -6
- package/dist/workspace/ci-report-url.d.ts +18 -0
- package/dist/workspace/ci-report-url.d.ts.map +1 -0
- package/dist/workspace/ci-report-url.js +33 -0
- package/dist/workspace/ci-run-index.d.ts +12 -0
- package/dist/workspace/ci-run-index.d.ts.map +1 -1
- package/dist/workspace/ci-run-index.js +6 -4
- package/dist/workspace/ci-run-index.schema.json +5 -3
- package/dist/workspace/ci-run.d.ts +75 -2
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +195 -53
- package/dist/workspace/ci-runner-key.d.ts +16 -3
- package/dist/workspace/ci-runner-key.d.ts.map +1 -1
- package/dist/workspace/ci-runner-key.js +30 -10
- package/dist/workspace/ci-serve.d.ts +54 -4
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +175 -26
- package/dist/workspace/declaration.d.ts +8 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +11 -2
- package/dist/workspace/declaration.schema.json +7 -2
- package/dist/workspace/export.d.ts +1 -1
- package/dist/workspace/export.d.ts.map +1 -1
- package/dist/workspace/export.js +7 -3
- package/dist/workspace/ls.d.ts +6 -1
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +1 -0
- package/dist/workspace/ls.schema.json +7 -1
- package/dist/workspace/pin-integrity.d.ts.map +1 -1
- package/dist/workspace/pin-integrity.js +3 -2
- package/dist/workspace/pr-report.schema.json +74 -7
- package/dist/workspace/reason-codes.d.ts +1 -1
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +2 -2
- package/dist/workspace/run-event.schema.json +3 -1
- package/dist/workspace/status.schema.json +3 -1
- package/dist/workspace/write-scope.d.ts +9 -0
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/workspace/write-scope.js +11 -1
- package/package.json +1 -1
- package/src/__fixtures__/pr-loop/pr-apply-wave-waiting.note.golden.md +48 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +3 -3
- package/src/cli/commands/audit.test.ts +2 -2
- package/src/cli/commands/check-lexicon-plugin.test.ts +9 -0
- package/src/cli/commands/check-lexicon-plugin.ts +11 -8
- package/src/cli/commands/check-lexicon.test.ts +1 -1
- package/src/cli/commands/check-lexicon.ts +16 -11
- package/src/cli/commands/import.ts +40 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +4 -3
- package/src/cli/commands/init-lexicon.test.ts +8 -5
- package/src/cli/commands/onboard.test.ts +45 -0
- package/src/cli/commands/onboard.ts +8 -4
- package/src/cli/commands/update.test.ts +6 -0
- package/src/cli/commands/update.ts +4 -1
- package/src/cli/compiled-cli.e2e.test.ts +76 -11
- package/src/cli/dependencies.e2e.test.ts +101 -0
- package/src/cli/dependencies.test.ts +93 -0
- package/src/cli/dependencies.ts +122 -0
- package/src/cli/handlers/build.test.ts +69 -0
- package/src/cli/handlers/build.ts +20 -4
- package/src/cli/handlers/fan-out.test.ts +73 -0
- package/src/cli/handlers/fan-out.ts +11 -4
- package/src/cli/handlers/graph.test.ts +76 -0
- package/src/cli/handlers/graph.ts +19 -12
- package/src/cli/handlers/lint.test.ts +42 -0
- package/src/cli/handlers/lint.ts +6 -0
- package/src/cli/handlers/operator.ts +3 -3
- package/src/cli/handlers/pr-waves.test.ts +449 -0
- package/src/cli/handlers/pr.test.ts +134 -0
- package/src/cli/handlers/pr.ts +523 -31
- package/src/cli/handlers/promote.test.ts +26 -1
- package/src/cli/handlers/promote.ts +3 -2
- package/src/cli/handlers/run-components-exit.test.ts +99 -0
- package/src/cli/handlers/run-signer.test.ts +79 -0
- package/src/cli/handlers/run.ts +34 -16
- package/src/cli/main.test.ts +18 -0
- package/src/cli/main.ts +43 -16
- package/src/cli/parse-args.ts +12 -0
- package/src/cli/registry.ts +19 -6
- package/src/codegen/generate-post-synth-barrel.ts +2 -2
- package/src/codegen/lexicon-regen.ts +1 -1
- package/src/codegen/pinned-upgrade.ts +2 -2
- package/src/codegen/post-synth-barrel-guards.test.ts +6 -11
- package/src/components/capability.ts +51 -3
- package/src/components/changed-files.test.ts +16 -1
- package/src/components/changed-files.ts +9 -1
- package/src/components/driver.test.ts +36 -1
- package/src/components/driver.ts +76 -4
- package/src/components/fan-out-record.ts +29 -1
- package/src/components/fan-out-run.test.ts +35 -0
- package/src/components/fan-out-run.ts +40 -1
- package/src/components/pr-pipeline.test.ts +100 -0
- package/src/components/pr-pipeline.ts +132 -17
- package/src/components/pr-run.test.ts +323 -18
- package/src/components/pr-run.ts +354 -75
- package/src/components/wave-plan.ts +16 -4
- package/src/discovery/fold-host-method.test.ts +87 -0
- package/src/discovery/fold-import.ts +15 -5
- package/src/discovery/fold-package-composite.test.ts +27 -0
- package/src/discovery/fold-specifiers.test.ts +8 -0
- package/src/discovery/sandbox/bundle.ts +6 -0
- package/src/discovery/specifier-resolve.ts +8 -2
- package/src/fold/fold.test.ts +72 -0
- package/src/fold/fold.ts +71 -0
- package/src/fold/subset.test.ts +31 -0
- package/src/fold/subset.ts +99 -0
- package/src/lexicon-dist.e2e.test.ts +254 -0
- package/src/lexicon-module.test.ts +47 -0
- package/src/lexicon-module.ts +49 -7
- package/src/lexicon-plugin-helpers.ts +6 -4
- package/src/lexicon.ts +2 -0
- package/src/lifecycle/affected.test.ts +7 -0
- package/src/lifecycle/affected.ts +6 -1
- package/src/lifecycle/release-ledger.ts +34 -0
- package/src/lifecycle/work-dir.test.ts +77 -0
- package/src/lifecycle/work-dir.ts +82 -0
- package/src/lint/discover.test.ts +46 -2
- package/src/lint/discover.ts +55 -49
- package/src/module-source.test.ts +85 -0
- package/src/module-source.ts +112 -0
- package/src/op/activities/factory.ts +1 -1
- package/src/op/discover-root.test.ts +31 -2
- package/src/op/discover.ts +14 -4
- package/src/op/gate.test.ts +30 -0
- package/src/op/gate.ts +3 -0
- package/src/op/op-waves-run.ts +20 -5
- package/src/op/op-waves.test.ts +49 -0
- package/src/op/operator.ts +2 -2
- package/src/op/steward.ts +6 -4
- package/src/op/work-lease-run.test.ts +88 -2
- package/src/op/work-lease-run.ts +52 -12
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +42 -0
- package/src/pr-forge.ts +40 -0
- package/src/pr-loop-bundle.test.ts +2 -1
- package/src/pr-loop.test.ts +117 -1
- package/src/pr-loop.ts +252 -10
- package/src/pr-report-url.ts +5 -5
- package/src/terraform/__fixtures__/advise.test.ts +21 -2
- package/src/ts-loader.test.ts +89 -1
- package/src/ts-loader.ts +180 -13
- package/src/workspace/changes.test.ts +1 -1
- package/src/workspace/chant-migrations/fountain-retired-kinds.test.ts +33 -0
- package/src/workspace/chant-migrations/fountain-retired-kinds.ts +190 -0
- package/src/workspace/chant-migrations.e2e.test.ts +5 -0
- package/src/workspace/chant-migrations.ts +2 -0
- package/src/workspace/checks/boxes.ts +9 -9
- package/src/workspace/ci-green-forge.ts +6 -4
- package/src/workspace/ci-green-runs.test.ts +53 -11
- package/src/workspace/ci-green.test.ts +1 -1
- package/src/workspace/ci-green.ts +50 -22
- package/src/workspace/ci-list.schema.json +12 -6
- package/src/workspace/ci-report-url.test.ts +220 -0
- package/src/workspace/ci-report-url.ts +33 -0
- package/src/workspace/ci-run-index.schema.json +5 -3
- package/src/workspace/ci-run-index.test.ts +42 -3
- package/src/workspace/ci-run-index.ts +18 -4
- package/src/workspace/ci-run.test.ts +185 -7
- package/src/workspace/ci-run.ts +224 -54
- package/src/workspace/ci-runner-key.test.ts +55 -17
- package/src/workspace/ci-runner-key.ts +36 -11
- package/src/workspace/ci-serve.test.ts +150 -6
- package/src/workspace/ci-serve.ts +169 -25
- package/src/workspace/declaration.schema.json +7 -2
- package/src/workspace/declaration.test.ts +23 -0
- package/src/workspace/declaration.ts +19 -3
- package/src/workspace/export.ts +6 -3
- package/src/workspace/ls.schema.json +7 -1
- package/src/workspace/ls.ts +7 -2
- package/src/workspace/pin-integrity.test.ts +5 -0
- package/src/workspace/pin-integrity.ts +3 -2
- package/src/workspace/pr-report.schema.json +74 -7
- package/src/workspace/reason-codes.ts +2 -2
- package/src/workspace/run-event.schema.json +3 -1
- package/src/workspace/status.schema.json +3 -1
- package/src/workspace/write-scope.test.ts +29 -1
- package/src/workspace/write-scope.ts +12 -1
package/src/workspace/export.ts
CHANGED
|
@@ -44,6 +44,7 @@ import { parseJsonText } from "./jsonc";
|
|
|
44
44
|
import { fileHash, LOCK_FILE, LockError, parseLock, renderLock, type Lineage, type LineageLock } from "./lineage-lock";
|
|
45
45
|
import { loadRecordKind } from "./records";
|
|
46
46
|
import { workingTree } from "./tree";
|
|
47
|
+
import { isWorkDir } from "../lifecycle/work-dir";
|
|
47
48
|
|
|
48
49
|
/** The role that marks the member an export is written into. */
|
|
49
50
|
export const EXPORT_ROLE = "export";
|
|
@@ -142,7 +143,7 @@ export function gitTopOf(dir: string): string | undefined {
|
|
|
142
143
|
/**
|
|
143
144
|
* The files under `dir` (absolute) that git tracks or would track, relative
|
|
144
145
|
* to `dir`, that exist in the working tree. Outside git, every file, leaving
|
|
145
|
-
* out `.git` and
|
|
146
|
+
* out `.git`, `node_modules` and `.chant/work`.
|
|
146
147
|
*/
|
|
147
148
|
export function listFiles(dir: string): string[] {
|
|
148
149
|
if (!existsSync(dir)) return [];
|
|
@@ -167,8 +168,10 @@ export function listFiles(dir: string): string[] {
|
|
|
167
168
|
for (const d of readdirSync(join(dir, rel), { withFileTypes: true })) {
|
|
168
169
|
if (d.name === ".git" || d.name === "node_modules") continue;
|
|
169
170
|
const p = rel ? `${rel}/${d.name}` : d.name;
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
// `.chant/work` holds work worktrees, each a copy of the checkout (#2893).
|
|
172
|
+
if (d.isDirectory()) {
|
|
173
|
+
if (!isWorkDir(p)) walk(p);
|
|
174
|
+
} else if (d.isFile()) out.push(p);
|
|
172
175
|
}
|
|
173
176
|
};
|
|
174
177
|
walk("");
|
|
@@ -103,7 +103,13 @@
|
|
|
103
103
|
{
|
|
104
104
|
"type": "object",
|
|
105
105
|
"required": ["green"],
|
|
106
|
-
"properties": {
|
|
106
|
+
"properties": {
|
|
107
|
+
"green": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/ciGreen" }] },
|
|
108
|
+
"reportUrl": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "Added in contract 1 by chant 0.124.32 (#4160). The declaration's ci.reportUrl, an s3:// or file:// URL without a trailing slash, present only when it is set. The run index is at <reportUrl>/runs/index.json (ci-run-index), and each job's report under <reportUrl>/<pr>/<commit>[/<member>]/."
|
|
111
|
+
}
|
|
112
|
+
}
|
|
107
113
|
}
|
|
108
114
|
]
|
|
109
115
|
},
|
package/src/workspace/ls.ts
CHANGED
|
@@ -186,8 +186,12 @@ export type LsDocument =
|
|
|
186
186
|
groups: LsGroup[];
|
|
187
187
|
/** Every declared diagram, the workspace's own first, then each member's, in file order (#2764). */
|
|
188
188
|
diagrams: LsDiagram[];
|
|
189
|
-
/**
|
|
190
|
-
|
|
189
|
+
/**
|
|
190
|
+
* What the workspace's CI decides about its commits (#3573), or null
|
|
191
|
+
* with no `ci` block. `reportUrl` (#4160) is the declared report URL,
|
|
192
|
+
* where the run index is kept, present only when it is set.
|
|
193
|
+
*/
|
|
194
|
+
ci: { green: LsCiGreen | null; reportUrl?: string } | null;
|
|
191
195
|
summary: { members: number; unreadable: number; groups: number; matches: number };
|
|
192
196
|
}
|
|
193
197
|
| {
|
|
@@ -330,6 +334,7 @@ function readListing(query: LsQuery): { doc: LsDocument; declaration?: Declarati
|
|
|
330
334
|
...(declaration.ci.green.source === "runs" ? { source: "runs" as const } : {}),
|
|
331
335
|
}
|
|
332
336
|
: null,
|
|
337
|
+
...(declaration.ci.reportUrl !== null ? { reportUrl: declaration.ci.reportUrl } : {}),
|
|
333
338
|
}
|
|
334
339
|
: null,
|
|
335
340
|
summary: {
|
|
@@ -51,6 +51,11 @@ describe("integrityOf", () => {
|
|
|
51
51
|
expect(integrityOf(join(dir({ "d/a": "1", "d/b": "2", "d/e": "" }), "d")).integrity).not.toBe(base);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
test("a work worktree under .chant/work is left out, and the rest of .chant is hashed (#2893)", () => {
|
|
55
|
+
const root = dir({ "d/a": "1", "d/.chant/work/W-1/a": "copy", "d/.chant/work/m/W-2/a": "copy", "d/.chant/notes": "n" });
|
|
56
|
+
expect(pinnedFiles(join(root, "d"))).toEqual([".chant/notes", "a"]);
|
|
57
|
+
});
|
|
58
|
+
|
|
54
59
|
test("node_modules and .git are left out, and a symbolic link is refused", () => {
|
|
55
60
|
const root = dir({ "d/a": "1", "d/node_modules/x/index.js": "x", "d/.git/HEAD": "ref" });
|
|
56
61
|
expect(pinnedFiles(join(root, "d"))).toEqual(["a"]);
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import { createHash } from "node:crypto";
|
|
29
29
|
import { lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
30
30
|
import { join } from "node:path";
|
|
31
|
+
import { isWorkDir } from "../lifecycle/work-dir";
|
|
31
32
|
|
|
32
33
|
export type IntegrityAlgorithm = "sha256" | "sha384" | "sha512";
|
|
33
34
|
|
|
@@ -39,7 +40,7 @@ export function parseIntegrity(value: string): { algorithm: IntegrityAlgorithm;
|
|
|
39
40
|
return m ? { algorithm: m[1] as IntegrityAlgorithm, digest: m[2] } : undefined;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
/** Directories a plugin hash never looks inside. */
|
|
43
|
+
/** Directories a plugin hash never looks inside, with `.chant/work`, where work worktrees are (#2893). */
|
|
43
44
|
const SKIPPED_DIRS = new Set(["node_modules", ".git"]);
|
|
44
45
|
|
|
45
46
|
/** Thrown when a path can't be hashed: it is missing, or holds a symbolic link. */
|
|
@@ -50,7 +51,7 @@ function walk(dir: string, prefix: string, out: string[]): void {
|
|
|
50
51
|
const rel = prefix === "" ? entry.name : `${prefix}/${entry.name}`;
|
|
51
52
|
if (entry.isSymbolicLink()) throw new PinHashError(`${rel} is a symbolic link, which a pinned plugin may not contain`);
|
|
52
53
|
if (entry.isDirectory()) {
|
|
53
|
-
if (!SKIPPED_DIRS.has(entry.name)) walk(join(dir, entry.name), rel, out);
|
|
54
|
+
if (!SKIPPED_DIRS.has(entry.name) && !isWorkDir(rel)) walk(join(dir, entry.name), rel, out);
|
|
54
55
|
} else if (entry.isFile()) {
|
|
55
56
|
out.push(rel);
|
|
56
57
|
}
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"description": "The change-set digest of what this stage planned: computePlanDigest(\"change-set\", ...) over every member's { member, planDigest }. What the gate binds."
|
|
34
34
|
},
|
|
35
35
|
"status": {
|
|
36
|
-
"enum": ["planned", "plan-failed", "nothing", "applied", "failed", "refused"],
|
|
37
|
-
"description": "planned: every member planned (plan stage). plan-failed: a member failed to plan, so nothing can apply. nothing: no component deploys what the change touches. applied: every member applied. failed: a member failed to apply and its dependents did not run. refused: nothing applied, see refusal."
|
|
36
|
+
"enum": ["planned", "plan-failed", "nothing", "applied", "failed", "wave-applied", "refused", "waiting"],
|
|
37
|
+
"description": "planned: every member planned (plan stage). plan-failed: a member failed to plan, so nothing can apply. nothing: no component deploys what the change touches. applied: every member applied. failed: a member failed to apply and its dependents did not run. wave-applied (#4003, chant 0.124.32 and newer): with --wave-gate and --wave, the wave applied and a later wave is still to run. refused: nothing applied, see refusal. waiting (#3999): the approved plans applied except members held back after an upstream applied, which wait on an approval of the plan the last of rounds made."
|
|
38
38
|
},
|
|
39
39
|
"refusal": {
|
|
40
|
-
"enum": ["not-approved", "plan-changed", "not-a-reviewer", "no-pull-request"],
|
|
41
|
-
"description": "Why an apply refused. plan-changed: an approval stands for another digest, so the plan changed after review."
|
|
40
|
+
"enum": ["not-approved", "plan-changed", "not-a-reviewer", "author-approved", "no-pull-request", "wave-not-approved", "wave-plan-changed", "earlier-wave"],
|
|
41
|
+
"description": "Why an apply refused. plan-changed: an approval stands for another digest, so the plan changed after review. author-approved (#4000): under --require-review, an approval names the pull request's author or an author or committer of one of its commits. With --wave-gate (#4003, chant 0.124.32 and newer): wave-not-approved, a wave's new plan is not covered by the approved one and no approval of its gate stands for it; wave-plan-changed, an approval of its gate stands for another digest; earlier-wave, an earlier wave has work left or no record says it applied. The waves that applied before a wave refused stay applied; waves says which."
|
|
42
42
|
},
|
|
43
43
|
"message": { "type": "string", "description": "The refusal or failure as printed." },
|
|
44
44
|
"resumed": {
|
|
@@ -54,6 +54,61 @@
|
|
|
54
54
|
"description": "Added within contract version 1 by #4104, written by chant 0.124.30 and newer. Per dependency a member was planned against, the names of the outputs read from the deployed estate through its capability's outputs, sorted. A dependency outside the change is listed here too, and one whose stack is not deployed yet lists []. Outputs given with --seed-outputs, or carried from an earlier attempt's record, are not listed. Absent when no dependency was read, and on a resumed apply.",
|
|
55
55
|
"additionalProperties": { "type": "array", "items": { "type": "string" } }
|
|
56
56
|
},
|
|
57
|
+
"waveGate": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Added within contract version 1 by #4003, written by chant 0.124.32 and newer. pr-apply --wave-gate <name>: the apply runs a wave at a time, each planned after the one before it applied, and wave k waits on <name>-wave-<k> under op when its plan moved. Absent without it."
|
|
60
|
+
},
|
|
61
|
+
"waves": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"description": "With waveGate: each wave reached so far, in order, with the approval it applied or waits under.",
|
|
64
|
+
"items": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"required": ["wave", "components", "status", "approval", "gate", "digest"],
|
|
67
|
+
"properties": {
|
|
68
|
+
"wave": { "type": "integer", "minimum": 1, "description": "1-based, from selection.waves." },
|
|
69
|
+
"components": { "type": "array", "items": { "type": "string" }, "description": "The components planned in it on the run that reached it." },
|
|
70
|
+
"status": { "enum": ["applied", "failed", "plan-failed", "waiting"] },
|
|
71
|
+
"approval": { "enum": ["pull-request", "wave"], "description": "pull-request: the approved change set covers the wave's plan, and it applies under the pull request's approval (gate and digest are the report's). wave: its plan moved, and it needs an approval of its own gate for its new plan." },
|
|
72
|
+
"gate": { "type": "string", "description": "The gate it applied or waits under: the report's gate, or <waveGate>-wave-<k>." },
|
|
73
|
+
"digest": { "type": "string", "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$", "description": "The digest that gate binds: the report's digest, or the change-set digest of the wave's new plan." },
|
|
74
|
+
"approvedBy": { "type": "array", "items": { "type": "string" } },
|
|
75
|
+
"approved": { "type": "string", "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$", "description": "Waiting: an approval of the wave's gate stands for this other digest." },
|
|
76
|
+
"moved": { "type": "array", "items": { "type": "string" }, "description": "Why the approved change set does not cover the wave's plan, one line per member." }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"plannedOutputs": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"description": "Added within contract version 1 by #3999, written by chant 0.124.32 and newer. Per dependency in the change that a member was planned against, the names of the outputs its plan knows, sorted. An output a member reads that is not listed is known only after apply, and the member lists it under unknownInputs. Absent when no member read one.",
|
|
83
|
+
"additionalProperties": { "type": "array", "items": { "type": "string" } }
|
|
84
|
+
},
|
|
85
|
+
"rounds": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"description": "Added within contract version 1 by #3999. Apply stage: the rounds planned after an upstream applied, in order. A member whose plan read an upstream output that applied as another value, or was known only after apply, is held back and planned again against the outputs the apply left; each round has its own gate and digest. Absent when nothing was held.",
|
|
88
|
+
"items": {
|
|
89
|
+
"type": "object",
|
|
90
|
+
"required": ["round", "gate", "digest", "components", "approval", "status", "changeSet"],
|
|
91
|
+
"properties": {
|
|
92
|
+
"round": { "type": "integer", "minimum": 2 },
|
|
93
|
+
"gate": { "type": "string", "description": "The gate the round waits on: <gate>-round-<round>." },
|
|
94
|
+
"digest": { "type": "string", "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$", "description": "The change-set digest of what the round planned. What its gate binds." },
|
|
95
|
+
"components": { "type": "array", "items": { "type": "string" }, "description": "The components planned again, in apply order." },
|
|
96
|
+
"approval": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"required": ["status"],
|
|
99
|
+
"description": "Where the approval stands for digest, as the top-level approval.",
|
|
100
|
+
"properties": {
|
|
101
|
+
"status": { "enum": ["approved", "changed", "pending"] },
|
|
102
|
+
"approvedBy": { "type": "array", "items": { "type": "string" } },
|
|
103
|
+
"approved": { "type": "string", "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$" }
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"status": { "enum": ["applied", "failed", "waiting", "plan-failed"] },
|
|
107
|
+
"message": { "type": "string", "description": "With waiting: why an approval that stands does not count under --require-review." },
|
|
108
|
+
"changeSet": { "type": "object", "description": "The change-set document the round planned. Its digest equals digest." }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
57
112
|
"approval": {
|
|
58
113
|
"type": "object",
|
|
59
114
|
"required": ["status"],
|
|
@@ -85,7 +140,7 @@
|
|
|
85
140
|
"member": { "type": "string", "description": "The member's name in the change set: the root, for a terraform-family step." },
|
|
86
141
|
"component": { "type": "string" },
|
|
87
142
|
"planDigest": { "type": ["string", "null"], "description": "What a gate on this member alone binds. null when it failed to plan." },
|
|
88
|
-
"status": { "enum": ["planned", "plan-failed", "applied", "failed", "blocked"] },
|
|
143
|
+
"status": { "enum": ["planned", "plan-failed", "applied", "failed", "blocked", "waiting"], "description": "waiting (#3999): held back because its plan read an upstream output that applied as another value, or was known only after apply; it waits on an approval of its plan in rounds." },
|
|
89
144
|
"counts": {
|
|
90
145
|
"type": "object",
|
|
91
146
|
"required": ["create", "update", "replace", "delete"],
|
|
@@ -100,8 +155,20 @@
|
|
|
100
155
|
"inputsMoved": {
|
|
101
156
|
"type": "array",
|
|
102
157
|
"items": { "type": "string" },
|
|
103
|
-
"description": "Apply stage: components this one depends on whose outputs changed when they applied. It applied the plan it was approved with; the next run plans it against the new values."
|
|
104
|
-
}
|
|
158
|
+
"description": "Apply stage: components this one depends on whose outputs changed when they applied. It applied the plan it was approved with; the next run plans it against the new values. Not written by chant 0.124.32 and newer, which holds such a member back instead (held, round)."
|
|
159
|
+
},
|
|
160
|
+
"unknownInputs": {
|
|
161
|
+
"type": "array",
|
|
162
|
+
"items": { "type": "string" },
|
|
163
|
+
"description": "#3999: the upstream outputs its plan read that the change's plans could not say, as <component>.<output>, sorted. Known only after that upstream applies; the approval does not cover what this member does with them."
|
|
164
|
+
},
|
|
165
|
+
"buildInputs": {
|
|
166
|
+
"type": "array",
|
|
167
|
+
"items": { "type": "string" },
|
|
168
|
+
"description": "#3999: the published artifact identities its plan read from a build in the same change, as <component>.publish.<field>, sorted. Known only after the build runs and never approved again: the build's provenance binds them, so the member applies without a later round."
|
|
169
|
+
},
|
|
170
|
+
"round": { "type": "integer", "minimum": 2, "description": "Apply stage (#3999): the round whose plan it applied or waits on, when not the first. planDigest and counts are that round's." },
|
|
171
|
+
"held": { "type": "string", "description": "Apply stage (#3999): why the first round's plan did not apply." }
|
|
105
172
|
}
|
|
106
173
|
}
|
|
107
174
|
},
|
|
@@ -232,8 +232,8 @@ export const REASONS = {
|
|
|
232
232
|
// A box that holds a credential (check, #2726). Each is also a WSP finding.
|
|
233
233
|
"box-credential-declared": "A file in a box member's directory carries a literal secret: a credential's shape, or a literal where a credential goes. A variable or secret-manager reference is not one.",
|
|
234
234
|
"box-capability-unbrokered": "A capability in a member's box block names no broker, so the box would hold its credential.",
|
|
235
|
-
// The credential fountain itself hands a
|
|
236
|
-
"box-fountain-callback-undeclared": "A box member builds a fountain Box, whose
|
|
235
|
+
// The credential fountain itself hands a box (check, #2780). Also a WSP finding.
|
|
236
|
+
"box-fountain-callback-undeclared": "A box member builds a fountain Box, whose sandbox fountain gives a callback token scoped to its owner, and the member's box block does not declare the fountain-callback capability brokered by fountain with scope owner.",
|
|
237
237
|
// A box's intent, the decision record its box block names (check, #2850). Each is also a WSP finding.
|
|
238
238
|
"box-intent-unknown": "A box block names an intent, and no record of a declared kind named decision has that id.",
|
|
239
239
|
"box-intent-unconstrained": "The decision record a box names as its intent constrains no member or path of this workspace: no member: entry for a declared member and no path: entry at, above or inside one's directory.",
|
|
@@ -54,7 +54,9 @@
|
|
|
54
54
|
"description": "github: a GitHub Actions run, also the spelling Forgejo Actions uses. gitlab: a CI pipeline. op: a steward's run, named by its Op run id. local: a run on the machine that started it, outside CI. chant: a pull-request job the chant runner ran (chant ci run, #4094), named by its Op run id; added within contract version 1 and written by chant 0.124.30 and newer, so a reader that switches on forge keeps a case for a value it does not know."
|
|
55
55
|
},
|
|
56
56
|
"repo": { "type": "string", "description": "The repository or project slug on the forge, when the environment named one." },
|
|
57
|
-
"url": { "type": "string", "description": "A link to the run, when the environment gave enough to build one." }
|
|
57
|
+
"url": { "type": "string", "description": "A link to the run, when the environment gave enough to build one." },
|
|
58
|
+
"jobId": { "type": "string", "description": "The forge's id for the job within the run: GITHUB_JOB on GitHub and Forgejo, CI_JOB_ID on GitLab. Added within contract 1 by #4156 and written by chant 0.124.32 and newer, only by chant ci run in a forge job." },
|
|
59
|
+
"attempt": { "type": "integer", "minimum": 1, "description": "The run's attempt, GITHUB_RUN_ATTEMPT on GitHub and Forgejo. Added within contract 1 by #4156 and written by chant 0.124.32 and newer, only by chant ci run in a forge job." }
|
|
58
60
|
}
|
|
59
61
|
},
|
|
60
62
|
"settleStatus": {
|
|
@@ -451,7 +451,9 @@
|
|
|
451
451
|
"properties": {
|
|
452
452
|
"forge": { "enum": ["github", "gitlab", "op", "local", "chant"], "description": "chant: a pull-request job the chant runner ran (chant ci run, #4094), added within contract 1 and written by chant 0.124.30 and newer." },
|
|
453
453
|
"repo": { "type": "string" },
|
|
454
|
-
"url": { "type": "string" }
|
|
454
|
+
"url": { "type": "string" },
|
|
455
|
+
"jobId": { "type": "string", "description": "The forge's job id within the run. Added within contract 1 by #4156 and written by chant 0.124.32 and newer, only by chant ci run in a forge job." },
|
|
456
|
+
"attempt": { "type": "integer", "minimum": 1, "description": "The run's attempt on GitHub and Forgejo. Added within contract 1 by #4156 and written by chant 0.124.32 and newer, only by chant ci run in a forge job." }
|
|
455
457
|
}
|
|
456
458
|
},
|
|
457
459
|
"failure": {
|
|
@@ -28,7 +28,7 @@ import { parseDeclaration, WorkspaceReadError } from "./declaration";
|
|
|
28
28
|
import { parseFrontMatter } from "./records";
|
|
29
29
|
import { amendRecord, newRecord, renderRecord, reviewRecord } from "./records-write";
|
|
30
30
|
import { emptyPolicy } from "./trust/policy";
|
|
31
|
-
import { judgePath, judgeRecord, onlyKeysChanged, principalClass, resolveWriter, WriteScopeError } from "./write-scope";
|
|
31
|
+
import { FACTORY_CHECK_LOG, judgePath, judgeRecord, onlyKeysChanged, principalClass, resolveWriter, WriteScopeError } from "./write-scope";
|
|
32
32
|
import { createWorkspaceTools } from "../cli/mcp/workspace-tools";
|
|
33
33
|
|
|
34
34
|
const DECISIONS = join(REPO, "docs", "design", "decisions");
|
|
@@ -226,6 +226,34 @@ describe("judging a write", () => {
|
|
|
226
226
|
expect(judgeRecord(d, factory, screen, "amend")).toMatchObject({ ok: false, code: "write-scope-kind" });
|
|
227
227
|
});
|
|
228
228
|
|
|
229
|
+
test("the factory Op's own check log is in no member and is not judged by member scope (#3512)", () => {
|
|
230
|
+
const d = parseDeclaration(declaration(SCOPE, [...AGENTS, { name: "factory", members: ["app", "design"] }]), "chant.workspace.json");
|
|
231
|
+
const factory = resolveWriter(d, policy, { agent: "factory" });
|
|
232
|
+
expect(judgePath(d, factory, ".chant/factory/W-007/check.log")).toEqual({ ok: true });
|
|
233
|
+
const app = resolveWriter(d, policy, { agent: "app-agent" });
|
|
234
|
+
expect(judgePath(d, app, ".chant/factory/W-007/check.log")).toEqual({ ok: true });
|
|
235
|
+
// Only that file: the rest of .chant/ stays outside an agent's members.
|
|
236
|
+
expect(judgePath(d, factory, ".chant/factory/W-007/notes.md")).toMatchObject({ ok: false, code: "write-scope-member" });
|
|
237
|
+
expect(judgePath(d, factory, ".chant/factory/check.log")).toMatchObject({ ok: false, code: "write-scope-member" });
|
|
238
|
+
expect(judgePath(d, factory, ".chant/factory/W-007/sub/check.log")).toMatchObject({ ok: false, code: "write-scope-member" });
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("a protected entry still covers the factory check log (#3512)", () => {
|
|
242
|
+
const d = parseDeclaration(
|
|
243
|
+
declaration({ agent: { protected: [".chant/**"] } }, [{ name: "factory", members: ["app", "design"] }]),
|
|
244
|
+
"chant.workspace.json",
|
|
245
|
+
);
|
|
246
|
+
const factory = resolveWriter(d, policy, { agent: "factory" });
|
|
247
|
+
expect(judgePath(d, factory, ".chant/factory/W-007/check.log")).toMatchObject({ ok: false, code: "write-scope-protected" });
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test("the pattern matches the path factoryCheck writes", async () => {
|
|
251
|
+
const { readFileSync } = await import("node:fs");
|
|
252
|
+
const src = readFileSync(new URL("../op/activities/factory.ts", import.meta.url), "utf-8");
|
|
253
|
+
expect(src).toContain("const log = `.chant/factory/${lease.item}/check.log`;");
|
|
254
|
+
expect(FACTORY_CHECK_LOG.test(".chant/factory/W-007/check.log")).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
|
|
229
257
|
test("the declared name of a kind is a key for its records rule too", () => {
|
|
230
258
|
const d = parseDeclaration(declaration({ agent: { records: { screen: ["new"] } } }), "chant.workspace.json");
|
|
231
259
|
const design = resolveWriter(d, policy, { agent: "design-agent" });
|
|
@@ -308,6 +308,16 @@ export interface PathChange {
|
|
|
308
308
|
after(): string | null;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* The factory Op's check log, `.chant/factory/<item>/check.log` (#3512). The
|
|
313
|
+
* Check step writes it in the worktree (`../op/activities/factory.ts`,
|
|
314
|
+
* `factoryCheck`), attaches it as each criterion's evidence, and Record
|
|
315
|
+
* commits it with the build under the builder's Chant-Agent. It is chant's own
|
|
316
|
+
* output and in no member, so an agent's member scope would flag every build
|
|
317
|
+
* commit. The member check passes over it; a protected entry still covers it.
|
|
318
|
+
*/
|
|
319
|
+
export const FACTORY_CHECK_LOG = /^\.chant\/factory\/[^/]+\/check\.log$/;
|
|
320
|
+
|
|
311
321
|
/**
|
|
312
322
|
* Whether `writer` may write the file at `path`, from the workspace root:
|
|
313
323
|
* the path is in a member the writer may write, and no protected entry of
|
|
@@ -319,7 +329,8 @@ export function judgePath(declaration: Declaration | null, writer: Writer, path:
|
|
|
319
329
|
const scope = scopeOf(declaration, writer);
|
|
320
330
|
if (scope === null) return OK;
|
|
321
331
|
const member = memberHolding(path, declaration?.members ?? []);
|
|
322
|
-
|
|
332
|
+
const chantOutput = member === null && FACTORY_CHECK_LOG.test(path);
|
|
333
|
+
if (!chantOutput && !memberAllowed(writer, scope, member)) {
|
|
323
334
|
const where = member === null ? "is in no member" : `is in member ${member}`;
|
|
324
335
|
return {
|
|
325
336
|
ok: false,
|