@intentius/chant 0.124.14 → 0.124.16
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/build.d.ts +6 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +1 -0
- package/dist/change-set.d.ts +24 -2
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +50 -1
- package/dist/ci-jobs.d.ts +227 -0
- package/dist/ci-jobs.d.ts.map +1 -0
- package/dist/ci-jobs.js +448 -0
- package/dist/cli/flush.d.ts +16 -0
- package/dist/cli/flush.d.ts.map +1 -0
- package/dist/cli/flush.js +42 -0
- package/dist/cli/handlers/approve.d.ts +98 -0
- package/dist/cli/handlers/approve.d.ts.map +1 -0
- package/dist/cli/handlers/approve.js +495 -0
- package/dist/cli/handlers/operator.d.ts +1 -95
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/operator.js +4 -488
- package/dist/cli/handlers/override-approve.js +1 -1
- package/dist/cli/main.d.ts +4 -15
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +4 -1062
- package/dist/cli/parse-args.d.ts +6 -0
- package/dist/cli/parse-args.d.ts.map +1 -0
- package/dist/cli/parse-args.js +1028 -0
- package/dist/components/fan-out-record.d.ts +1 -1
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/fan-out-record.js +3 -7
- package/dist/components/fan-out-run.d.ts +5 -3
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +7 -5
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +3 -2
- package/dist/composite.d.ts +10 -2
- package/dist/composite.d.ts.map +1 -1
- package/dist/composite.js +8 -0
- package/dist/discovery/collect.d.ts +2 -1
- package/dist/discovery/collect.d.ts.map +1 -1
- package/dist/discovery/collect.js +16 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-import.js +2 -107
- package/dist/discovery/host-composite.d.ts +35 -0
- package/dist/discovery/host-composite.d.ts.map +1 -0
- package/dist/discovery/host-composite.js +93 -0
- package/dist/discovery/index.d.ts +9 -0
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/index.js +1 -1
- package/dist/gate-decision.d.ts +20 -9
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +72 -19
- package/dist/gated-waves.d.ts +25 -6
- package/dist/gated-waves.d.ts.map +1 -1
- package/dist/gated-waves.js +21 -6
- package/dist/lifecycle/gate-audit.d.ts +69 -2
- package/dist/lifecycle/gate-audit.d.ts.map +1 -1
- package/dist/lifecycle/gate-audit.js +76 -2
- package/dist/lifecycle/gate-ledger.d.ts +24 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +9 -1
- package/dist/op/activities/activity-contracts.d.ts +5 -5
- package/dist/op/activities/activity-contracts.js +1 -1
- package/dist/op/activities/change-set.d.ts +8 -3
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +5 -2
- package/dist/op/activities/reconcile.d.ts +28 -16
- package/dist/op/activities/reconcile.d.ts.map +1 -1
- package/dist/op/activities/reconcile.js +34 -20
- package/dist/op/builders.d.ts +1 -1
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +1 -1
- package/dist/op/op-waves-run.d.ts +2 -2
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +8 -9
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/op-waves.js +4 -8
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +10 -0
- package/dist/wave-engine.d.ts +62 -0
- package/dist/wave-engine.d.ts.map +1 -0
- package/dist/wave-engine.js +59 -0
- package/dist/wave-layout.d.ts +29 -0
- package/dist/wave-layout.d.ts.map +1 -0
- package/dist/wave-layout.js +41 -0
- package/dist/wave-runtime.d.ts +29 -0
- package/dist/wave-runtime.d.ts.map +1 -0
- package/dist/wave-runtime.js +103 -0
- package/dist/wave-runtime.mjs +331 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts +7 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.js +17 -1
- package/dist/workspace/__fixtures__/sessions.d.ts +1 -1
- package/dist/workspace/__fixtures__/sessions.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/sessions.js +3 -3
- package/dist/workspace/ajv2020.d.ts +5 -0
- package/dist/workspace/ajv2020.d.ts.map +1 -0
- package/dist/workspace/ajv2020.js +14 -0
- package/dist/workspace/change-set.schema.json +5 -3
- package/dist/workspace/ci-green-workflow.d.ts +3 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +5 -2
- package/dist/workspace/class-data.d.ts +84 -0
- package/dist/workspace/class-data.d.ts.map +1 -0
- package/dist/workspace/class-data.js +238 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +4 -8
- package/dist/workspace/kinds.d.ts +3 -7
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +8 -45
- package/dist/workspace/points.d.ts.map +1 -1
- package/dist/workspace/points.js +2 -5
- package/dist/workspace/principal-classes.d.ts +4 -11
- package/dist/workspace/principal-classes.d.ts.map +1 -1
- package/dist/workspace/principal-classes.js +13 -99
- package/package.json +5 -3
- package/src/build.ts +8 -0
- package/src/change-set.test.ts +48 -0
- package/src/change-set.ts +52 -2
- package/src/ci-jobs.test.ts +49 -0
- package/src/ci-jobs.ts +515 -0
- package/src/cli/flush.ts +44 -0
- package/src/cli/handlers/approve.ts +618 -0
- package/src/cli/handlers/operator.ts +10 -608
- package/src/cli/handlers/override-approve.test.ts +1 -1
- package/src/cli/handlers/override-approve.ts +1 -1
- package/src/cli/main.ts +5 -816
- package/src/cli/parse-args.ts +781 -0
- package/src/components/fan-out-record.ts +3 -7
- package/src/components/fan-out-run.ts +7 -5
- package/src/components/pr-pipeline.ts +3 -2
- package/src/composite.ts +15 -3
- package/src/discovery/collect.ts +15 -1
- package/src/discovery/fold-build-parity.test.ts +71 -0
- package/src/discovery/fold-import.ts +2 -113
- package/src/discovery/fold-project-provenance.test.ts +21 -4
- package/src/discovery/host-composite.ts +101 -0
- package/src/discovery/index.ts +11 -1
- package/src/gate-decision-bundle.test.ts +6 -4
- package/src/gate-decision-identity.test.ts +59 -6
- package/src/gate-decision.ts +81 -21
- package/src/gated-waves.ts +28 -6
- package/src/lifecycle/gate-audit.test.ts +55 -1
- package/src/lifecycle/gate-audit.ts +116 -3
- package/src/lifecycle/gate-ledger.test.ts +20 -1
- package/src/lifecycle/gate-ledger.ts +33 -1
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +11 -3
- package/src/op/activities/lexicon-upgrade.test.ts +2 -0
- package/src/op/activities/reconcile.test.ts +62 -2
- package/src/op/activities/reconcile.ts +46 -22
- package/src/op/builders.ts +1 -1
- package/src/op/op-waves-run.ts +9 -9
- package/src/op/op-waves.test.ts +2 -0
- package/src/op/op-waves.ts +4 -8
- package/src/op/work-lease-run.test.ts +12 -4
- package/src/package-version.ts +11 -0
- package/src/wave-engine.test.ts +107 -0
- package/src/wave-engine.ts +98 -0
- package/src/wave-layout.ts +44 -0
- package/src/wave-runtime-bundle.test.ts +70 -0
- package/src/wave-runtime.e2e.test.ts +177 -0
- package/src/wave-runtime.ts +104 -0
- package/src/workspace/__fixtures__/contract-repo.ts +17 -1
- package/src/workspace/__fixtures__/sessions.ts +3 -3
- package/src/workspace/ajv2020.ts +17 -0
- package/src/workspace/change-set.schema.json +5 -3
- package/src/workspace/ci-green-workflow.test.ts +4 -4
- package/src/workspace/ci-green-workflow.ts +5 -2
- package/src/workspace/class-data.test.ts +64 -0
- package/src/workspace/class-data.ts +236 -0
- package/src/workspace/declaration.ts +4 -10
- package/src/workspace/kinds.ts +8 -40
- package/src/workspace/points.ts +2 -5
- package/src/workspace/principal-classes.ts +13 -99
- package/src/workspace/records-formats.test.ts +7 -2
- package/src/workspace/records-sessions-write.test.ts +3 -3
- package/src/workspace/status-contract.e2e.test.ts +37 -0
- package/src/workspace/status-contract.test.ts +23 -21
package/src/cli/main.ts
CHANGED
|
@@ -14,8 +14,12 @@ import { armSandboxPolicyExecution } from "../lint/policy-import";
|
|
|
14
14
|
import { ENV_VAR, unknownEnvError } from "../env";
|
|
15
15
|
import { initRuntime } from "../runtime-adapter";
|
|
16
16
|
import { installCompiledCli } from "../ts-loader";
|
|
17
|
-
import {
|
|
17
|
+
import { dispatchCommandGroup, collectCommandGroups, formatCommandGroupsHelp, type CommandGroup } from "./command-group";
|
|
18
18
|
import type { LexiconPlugin } from "../lexicon";
|
|
19
|
+
import { parseArgs } from "./parse-args";
|
|
20
|
+
import { flushAndExit, waitForStreamDrain } from "./flush";
|
|
21
|
+
|
|
22
|
+
export { parseArgs, waitForStreamDrain };
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
25
|
* #3878 — each command's handler module loads when that command runs, not on
|
|
@@ -125,780 +129,6 @@ const loadPlugins: typeof import("./plugins").loadPlugins = async (...a) => (awa
|
|
|
125
129
|
const resolveProjectLexicons: typeof import("./plugins").resolveProjectLexicons = async (...a) =>
|
|
126
130
|
(await import("./plugins")).resolveProjectLexicons(...a);
|
|
127
131
|
|
|
128
|
-
/**
|
|
129
|
-
* Long-form flags that are pure booleans in {@link parseArgs} — their branch
|
|
130
|
-
* below sets a field to `true` and never consumes a following array element.
|
|
131
|
-
* Used only to reject a joined `--flag=value` form for these (chant #1127):
|
|
132
|
-
* a boolean has no value to assign, and silently reinterpreting the joined
|
|
133
|
-
* value as the next positional argument (path, component name, ...) would be
|
|
134
|
-
* exactly the kind of silent misparse this issue exists to close. `--report`
|
|
135
|
-
* is deliberately excluded — it's context-sensitive (bare boolean vs a SARIF
|
|
136
|
-
* path, decided by lookahead), so a joined value for it is legitimate and
|
|
137
|
-
* already handled correctly once split.
|
|
138
|
-
*/
|
|
139
|
-
const BOOLEAN_FLAGS = new Set([
|
|
140
|
-
"--help",
|
|
141
|
-
"--open",
|
|
142
|
-
"--version",
|
|
143
|
-
"--agents",
|
|
144
|
-
"--agent",
|
|
145
|
-
"--all-projects",
|
|
146
|
-
"--force",
|
|
147
|
-
"--fix",
|
|
148
|
-
"--watch",
|
|
149
|
-
"--verbose",
|
|
150
|
-
"--live",
|
|
151
|
-
"--overlay",
|
|
152
|
-
"--explain",
|
|
153
|
-
"--owned",
|
|
154
|
-
"--verbatim",
|
|
155
|
-
"--apply-rewrites",
|
|
156
|
-
"--write",
|
|
157
|
-
"--strict",
|
|
158
|
-
"--validate",
|
|
159
|
-
"--use-composites",
|
|
160
|
-
"--composites",
|
|
161
|
-
"--stacks",
|
|
162
|
-
"--components",
|
|
163
|
-
"--up",
|
|
164
|
-
"--down",
|
|
165
|
-
"--include-dependents",
|
|
166
|
-
"--local",
|
|
167
|
-
"--json",
|
|
168
|
-
"--progress-json",
|
|
169
|
-
"--update-snapshot",
|
|
170
|
-
"--update-baseline",
|
|
171
|
-
"--run-examples",
|
|
172
|
-
"--check",
|
|
173
|
-
"--bump",
|
|
174
|
-
"--no-release-record",
|
|
175
|
-
"--fold",
|
|
176
|
-
"--no-fold",
|
|
177
|
-
"--no-cache",
|
|
178
|
-
"--sandbox",
|
|
179
|
-
"--yes",
|
|
180
|
-
"--confirm-prod",
|
|
181
|
-
"--once",
|
|
182
|
-
"--expire",
|
|
183
|
-
"--check-live",
|
|
184
|
-
"--check-snapshot",
|
|
185
|
-
"--fail-on-drift",
|
|
186
|
-
"--durable-requests",
|
|
187
|
-
"--skip-mcp",
|
|
188
|
-
"--current",
|
|
189
|
-
"--uncommitted",
|
|
190
|
-
"--allow-code",
|
|
191
|
-
"--root-only",
|
|
192
|
-
"--generated",
|
|
193
|
-
"--decide",
|
|
194
|
-
"--record-plans",
|
|
195
|
-
]);
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Parse command line arguments
|
|
199
|
-
*/
|
|
200
|
-
export function parseArgs(args: string[]): ParsedArgs {
|
|
201
|
-
// Local mutable copy — chant #1127's joined-`--flag=value` splitting below
|
|
202
|
-
// rewrites the array in place (one token becomes two), so this must not
|
|
203
|
-
// mutate whatever array the caller passed in (e.g. `process.argv.slice(2)`
|
|
204
|
-
// is already a fresh copy, but callers shouldn't have to know that).
|
|
205
|
-
args = args.slice();
|
|
206
|
-
|
|
207
|
-
const result: ParsedArgs = {
|
|
208
|
-
command: "",
|
|
209
|
-
path: ".",
|
|
210
|
-
extraPositional: undefined,
|
|
211
|
-
extraPositional2: undefined,
|
|
212
|
-
output: undefined,
|
|
213
|
-
format: "",
|
|
214
|
-
force: undefined,
|
|
215
|
-
fix: false,
|
|
216
|
-
lexicon: undefined,
|
|
217
|
-
template: undefined,
|
|
218
|
-
watch: false,
|
|
219
|
-
verbose: false,
|
|
220
|
-
help: false,
|
|
221
|
-
param: undefined,
|
|
222
|
-
paramsFile: undefined,
|
|
223
|
-
report: undefined,
|
|
224
|
-
local: undefined,
|
|
225
|
-
profile: undefined,
|
|
226
|
-
json: undefined,
|
|
227
|
-
live: false,
|
|
228
|
-
migrateFrom: undefined,
|
|
229
|
-
migrateTo: undefined,
|
|
230
|
-
emit: undefined,
|
|
231
|
-
strict: false,
|
|
232
|
-
validate: false,
|
|
233
|
-
useComposites: false,
|
|
234
|
-
reportFile: undefined,
|
|
235
|
-
skill: undefined,
|
|
236
|
-
skipMcp: undefined,
|
|
237
|
-
src: undefined,
|
|
238
|
-
env: undefined,
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
// chant #1127 — generic joined `--flag=value` support, factored out to
|
|
242
|
-
// ./command-group.ts (chant #1078) so a lexicon's own mounted command can
|
|
243
|
-
// apply the identical splitting discipline to its own flag vocabulary.
|
|
244
|
-
// Every value-taking flag below is matched by an exact `arg === "--flag"`
|
|
245
|
-
// check and then consumes the *next* array element (`args[++i]`) as its
|
|
246
|
-
// value; a joined token like `--env=prod` never matches any of those,
|
|
247
|
-
// doesn't match the trailing positional branch either (it starts with
|
|
248
|
-
// `-`), and used to vanish with no error. Splitting the token at its FIRST
|
|
249
|
-
// `=` and re-dispatching as two array elements makes every flag below see
|
|
250
|
-
// the exact shape it already handles — including a flag like `--param`
|
|
251
|
-
// whose own value legitimately contains `=` (`--param=tier=production`
|
|
252
|
-
// splits to flag `--param`, value `tier=production`, not further split on
|
|
253
|
-
// the second `=`).
|
|
254
|
-
args = splitJoinedFlags(args, BOOLEAN_FLAGS);
|
|
255
|
-
|
|
256
|
-
let i = 0;
|
|
257
|
-
while (i < args.length) {
|
|
258
|
-
const arg = args[i];
|
|
259
|
-
|
|
260
|
-
if (arg === "--help" || arg === "-h") {
|
|
261
|
-
result.help = true;
|
|
262
|
-
} else if (arg === "--version" || arg === "-V") {
|
|
263
|
-
result.version = true;
|
|
264
|
-
} else if (arg === "--output" || arg === "-o") {
|
|
265
|
-
result.output = args[++i];
|
|
266
|
-
} else if (arg === "--format" || arg === "-f") {
|
|
267
|
-
result.format = args[++i];
|
|
268
|
-
} else if (arg === "--lexicon" || arg === "-d") {
|
|
269
|
-
result.lexicon = args[++i];
|
|
270
|
-
} else if (arg === "--template" || arg === "-t") {
|
|
271
|
-
result.template = args[++i];
|
|
272
|
-
} else if (arg === "--force") {
|
|
273
|
-
result.force = true;
|
|
274
|
-
} else if (arg === "--fix") {
|
|
275
|
-
result.fix = true;
|
|
276
|
-
} else if (arg === "--watch" || arg === "-w") {
|
|
277
|
-
result.watch = true;
|
|
278
|
-
} else if (arg === "--verbose" || arg === "-v") {
|
|
279
|
-
result.verbose = true;
|
|
280
|
-
} else if (arg === "--profile" || arg === "-p") {
|
|
281
|
-
result.profile = args[++i];
|
|
282
|
-
} else if (arg === "--report") {
|
|
283
|
-
// --report alone is the boolean (used by `run`); --report <path> is
|
|
284
|
-
// the migrate-command file path. Look ahead for a non-flag.
|
|
285
|
-
const next = args[i + 1];
|
|
286
|
-
if (next && !next.startsWith("-")) {
|
|
287
|
-
result.reportFile = next;
|
|
288
|
-
i++;
|
|
289
|
-
} else {
|
|
290
|
-
result.report = true;
|
|
291
|
-
}
|
|
292
|
-
} else if (arg === "--live") {
|
|
293
|
-
result.live = true;
|
|
294
|
-
} else if (arg === "--overlay") {
|
|
295
|
-
result.overlay = true;
|
|
296
|
-
} else if (arg === "--between") {
|
|
297
|
-
result.betweenA = args[++i];
|
|
298
|
-
result.betweenB = args[++i];
|
|
299
|
-
if (!result.betweenA || !result.betweenB) throw new Error("--between needs two snapshot refs: --between <refA> <refB>");
|
|
300
|
-
} else if (arg === "--traffic") {
|
|
301
|
-
const v = args[++i];
|
|
302
|
-
if (!v) throw new Error('--traffic needs a level, passed to the engine verbatim: --traffic "100 rps, p50"');
|
|
303
|
-
result.traffic = v;
|
|
304
|
-
} else if (arg === "--overlay-anchor") {
|
|
305
|
-
const v = args[++i];
|
|
306
|
-
if (v !== "source" && v !== "live") throw new Error(`--overlay-anchor must be 'source' or 'live', got '${v}'`);
|
|
307
|
-
result.overlayAnchor = v;
|
|
308
|
-
} else if (arg === "--from") {
|
|
309
|
-
// Shared by `migrate --from <lexicon>`, `import --from <env>`,
|
|
310
|
-
// `components promote --from <env>` and `init --from <repo>@<ref>`;
|
|
311
|
-
// the commands never run together, so one field carries all four.
|
|
312
|
-
result.migrateFrom = args[++i];
|
|
313
|
-
} else if (arg === "--kustomize") {
|
|
314
|
-
// `chant import --kustomize <dir>` (#1548): render the overlay, import
|
|
315
|
-
// the output through the k8s template parser.
|
|
316
|
-
result.kustomize = args[++i];
|
|
317
|
-
} else if (arg === "--parser-option") {
|
|
318
|
-
// `chant import --parser-option key[=value]` (#2994), repeatable: checked
|
|
319
|
-
// against the lexicon's parserOptions() by the import command.
|
|
320
|
-
const v = args[++i];
|
|
321
|
-
if (!v || v.startsWith("-")) throw new Error("--parser-option needs key or key=value: --parser-option acceptLossyV1");
|
|
322
|
-
(result.parserOption ??= []).push(v);
|
|
323
|
-
} else if (arg === "--type") {
|
|
324
|
-
result.selectType = args[++i];
|
|
325
|
-
} else if (arg === "--name") {
|
|
326
|
-
result.selectName = args[++i];
|
|
327
|
-
} else if (arg === "--owned") {
|
|
328
|
-
result.owned = true;
|
|
329
|
-
} else if (arg === "--namespace") {
|
|
330
|
-
// The live read's namespace default (#1629), not a kubectl `-n`: it fills
|
|
331
|
-
// in for entities that declare no namespace and leaves the ones that do
|
|
332
|
-
// alone. No `-n` short form — that spelling belongs to `chant kube`,
|
|
333
|
-
// where it means kubectl's scope selector.
|
|
334
|
-
result.namespace = args[++i];
|
|
335
|
-
if (!result.namespace || result.namespace.startsWith("-")) throw new Error("--namespace needs a namespace: --namespace <ns>");
|
|
336
|
-
} else if (arg === "--verbatim") {
|
|
337
|
-
result.verbatim = true;
|
|
338
|
-
} else if (arg === "--state") {
|
|
339
|
-
result.statePath = args[++i];
|
|
340
|
-
} else if (arg === "--select") {
|
|
341
|
-
result.selectAddress = args[++i];
|
|
342
|
-
} else if (arg === "--live-name") {
|
|
343
|
-
result.liveName = args[++i];
|
|
344
|
-
} else if (arg === "--apply-rewrites") {
|
|
345
|
-
result.applyRewrites = true;
|
|
346
|
-
} else if (arg === "--stack") {
|
|
347
|
-
result.carveStack = args[++i];
|
|
348
|
-
} else if (arg === "--write") {
|
|
349
|
-
result.write = true;
|
|
350
|
-
} else if (arg === "--write-source") {
|
|
351
|
-
result.writeSource = true;
|
|
352
|
-
} else if (arg === "--to") {
|
|
353
|
-
result.migrateTo = args[++i];
|
|
354
|
-
} else if (arg === "--emit") {
|
|
355
|
-
result.emit = args[++i];
|
|
356
|
-
} else if (arg === "--dry-run") {
|
|
357
|
-
result.dryRun = true;
|
|
358
|
-
} else if (arg === "--yes") {
|
|
359
|
-
result.yes = true;
|
|
360
|
-
} else if (arg === "--confirm-prod") {
|
|
361
|
-
result.confirmProd = true;
|
|
362
|
-
} else if (arg === "--strict") {
|
|
363
|
-
result.strict = true;
|
|
364
|
-
} else if (arg === "--validate") {
|
|
365
|
-
result.validate = true;
|
|
366
|
-
} else if (arg === "--use-composites") {
|
|
367
|
-
result.useComposites = true;
|
|
368
|
-
} else if (arg === "--skill") {
|
|
369
|
-
result.skill = args[++i];
|
|
370
|
-
} else if (arg === "--skip-mcp") {
|
|
371
|
-
result.skipMcp = true;
|
|
372
|
-
} else if (arg === "--src") {
|
|
373
|
-
result.src = args[++i];
|
|
374
|
-
} else if (arg === "--env") {
|
|
375
|
-
result.env = args[++i];
|
|
376
|
-
} else if (arg === "--port") {
|
|
377
|
-
const value = args[++i];
|
|
378
|
-
if (!value || value.startsWith("-")) throw new Error("--port needs a port: --port <container-port>=<host-port>");
|
|
379
|
-
(result.port ??= []).push(value);
|
|
380
|
-
} else if (arg === "--promote-to") {
|
|
381
|
-
result.promoteTo = args[++i];
|
|
382
|
-
if (!result.promoteTo || result.promoteTo.startsWith("-")) throw new Error("--promote-to needs an environment: --promote-to <env>");
|
|
383
|
-
} else if (arg === "--tier") {
|
|
384
|
-
result.tier = args[++i];
|
|
385
|
-
} else if (arg === "--agents") {
|
|
386
|
-
result.agents = true;
|
|
387
|
-
} else if (arg === "--scope") {
|
|
388
|
-
result.scope = args[++i];
|
|
389
|
-
} else if (arg === "--all-projects") {
|
|
390
|
-
result.allProjects = true;
|
|
391
|
-
} else if (arg === "--runtime") {
|
|
392
|
-
result.runtime = args[++i];
|
|
393
|
-
} else if (arg === "--fail-on") {
|
|
394
|
-
result.failOn = args[++i];
|
|
395
|
-
} else if (arg === "--max-files") {
|
|
396
|
-
// Validated by the audit handler, like `--limit` below.
|
|
397
|
-
result.maxFiles = Number(args[++i]);
|
|
398
|
-
} else if (arg === "--theme") {
|
|
399
|
-
result.theme = args[++i];
|
|
400
|
-
} else if (arg === "--stacks") {
|
|
401
|
-
result.stacks = true;
|
|
402
|
-
} else if (arg === "--components") {
|
|
403
|
-
result.components = true;
|
|
404
|
-
} else if (arg === "--generate") {
|
|
405
|
-
result.generate = args[++i];
|
|
406
|
-
} else if (arg === "--spec") {
|
|
407
|
-
result.opsSpec = args[++i];
|
|
408
|
-
} else if (arg === "--dump-outputs") {
|
|
409
|
-
result.dumpOutputs = args[++i];
|
|
410
|
-
} else if (arg === "--digest-file") {
|
|
411
|
-
result.digestFile = args[++i];
|
|
412
|
-
} else if (arg === "--seed-outputs") {
|
|
413
|
-
(result.seedOutputs ??= []).push(args[++i]);
|
|
414
|
-
} else if (arg === "--detail") {
|
|
415
|
-
result.detail = Number(args[++i]);
|
|
416
|
-
} else if (arg === "--lens") {
|
|
417
|
-
result.lens = args[++i];
|
|
418
|
-
} else if (arg === "--explain") {
|
|
419
|
-
result.explain = true;
|
|
420
|
-
} else if (arg === "--show") {
|
|
421
|
-
result.show = args[++i];
|
|
422
|
-
} else if (arg === "--up") {
|
|
423
|
-
result.up = true;
|
|
424
|
-
} else if (arg === "--down") {
|
|
425
|
-
result.down = true;
|
|
426
|
-
} else if (arg === "--node-sizes") {
|
|
427
|
-
result.nodeSizes = args[++i];
|
|
428
|
-
} else if (arg === "--layout-engine") {
|
|
429
|
-
result.layoutEngine = args[++i];
|
|
430
|
-
} else if (arg === "--base") {
|
|
431
|
-
result.base = args[++i];
|
|
432
|
-
} else if (arg === "--head") {
|
|
433
|
-
result.head = args[++i];
|
|
434
|
-
} else if (arg === "--include-dependents") {
|
|
435
|
-
result.includeDependents = true;
|
|
436
|
-
} else if (arg === "--from-affected") {
|
|
437
|
-
result.fromAffected = args[++i];
|
|
438
|
-
} else if (arg === "--gate") {
|
|
439
|
-
result.gate = args[++i];
|
|
440
|
-
} else if (arg === "--wave-gate") {
|
|
441
|
-
result.waveGate = args[++i];
|
|
442
|
-
if (!result.waveGate || result.waveGate.startsWith("-")) throw new Error("--wave-gate needs a gate name: --wave-gate <name>");
|
|
443
|
-
} else if (arg === "--wave") {
|
|
444
|
-
const raw = args[++i];
|
|
445
|
-
const wave = Number(raw);
|
|
446
|
-
if (!Number.isInteger(wave) || wave < 1) throw new Error(`--wave needs a wave number from 1: got "${raw ?? ""}"`);
|
|
447
|
-
result.wave = wave;
|
|
448
|
-
} else if (arg === "--decide") {
|
|
449
|
-
result.decide = true;
|
|
450
|
-
} else if (arg === "--record-plans") {
|
|
451
|
-
result.recordPlans = true;
|
|
452
|
-
} else if (arg === "--share") {
|
|
453
|
-
const raw = args[++i];
|
|
454
|
-
const share = Number(raw);
|
|
455
|
-
if (!Number.isInteger(share) || share < 1) throw new Error(`--share needs a share number from 1: got "${raw ?? ""}"`);
|
|
456
|
-
result.share = share;
|
|
457
|
-
} else if (arg === "--canary") {
|
|
458
|
-
const raw = args[++i];
|
|
459
|
-
if (!raw || raw.startsWith("-")) throw new Error("--canary needs a component name: --canary <name>[,<name>...]");
|
|
460
|
-
(result.canary ??= []).push(...raw.split(",").map((n) => n.trim()).filter(Boolean));
|
|
461
|
-
} else if (arg === "--pr") {
|
|
462
|
-
const raw = args[++i];
|
|
463
|
-
const pr = Number(raw);
|
|
464
|
-
if (!Number.isInteger(pr) || pr < 1) throw new Error(`--pr needs a pull or merge request number: got "${raw ?? ""}"`);
|
|
465
|
-
result.pr = pr;
|
|
466
|
-
} else if (arg === "--forge") {
|
|
467
|
-
result.forge = args[++i];
|
|
468
|
-
if (!result.forge || result.forge.startsWith("-")) throw new Error("--forge needs a forge: --forge github|gitlab|forgejo");
|
|
469
|
-
} else if (arg === "--require-review") {
|
|
470
|
-
result.requireReview = true;
|
|
471
|
-
} else if (arg === "--pr-loop") {
|
|
472
|
-
result.prLoop = true;
|
|
473
|
-
} else if (arg === "--resume") {
|
|
474
|
-
// `chant approve <op> <gate> --resume` (#3683) takes no value; the
|
|
475
|
-
// fan-out and pull-request apply take the attempt file they resume.
|
|
476
|
-
const next = args[i + 1];
|
|
477
|
-
if (next === undefined || next.startsWith("-")) result.resumeRun = true;
|
|
478
|
-
else result.resume = args[++i];
|
|
479
|
-
} else if (arg === "--local") {
|
|
480
|
-
result.local = true;
|
|
481
|
-
} else if (arg === "--json") {
|
|
482
|
-
result.json = true;
|
|
483
|
-
} else if (arg === "--progress-json") {
|
|
484
|
-
result.progressJson = true;
|
|
485
|
-
} else if (arg === "--gated-exit") {
|
|
486
|
-
// `chant run <op> --gated-exit <code>` (#2243) — remap only the gated
|
|
487
|
-
// outcome's exit code. Parsed as a number here and range-checked in the
|
|
488
|
-
// handler, where the refusal can name the flag alongside the run.
|
|
489
|
-
result.gatedExit = Number(args[++i]);
|
|
490
|
-
} else if (arg === "--durable-requests") {
|
|
491
|
-
// `chant run approve ... --on <lexicon> --durable-requests` (#2126) —
|
|
492
|
-
// resolve the gate on the hosting runtime's own request path rather
|
|
493
|
-
// than by posting a follow-up prompt. Core only carries the flag; the
|
|
494
|
-
// runtime decides whether it has such a path.
|
|
495
|
-
result.durableRequests = true;
|
|
496
|
-
} else if (arg === "--update-snapshot") {
|
|
497
|
-
result.updateSnapshot = true;
|
|
498
|
-
} else if (arg === "--update-baseline") {
|
|
499
|
-
result.updateBaseline = true;
|
|
500
|
-
} else if (arg === "--deep") {
|
|
501
|
-
result.deep = true;
|
|
502
|
-
} else if (arg === "--at") {
|
|
503
|
-
result.at = args[++i];
|
|
504
|
-
} else if (arg === "--kind") {
|
|
505
|
-
// `chant workspace records|graph|check --kind <kind file>` (#2546, #2549)
|
|
506
|
-
result.kind = args[++i];
|
|
507
|
-
if (!result.kind || result.kind.startsWith("-")) throw new Error("--kind needs a kind file: --kind <path>");
|
|
508
|
-
// Repeatable for `workspace graph --intent` (#2651); the others read the last one.
|
|
509
|
-
(result.kinds ??= []).push(result.kind);
|
|
510
|
-
} else if (arg === "--composites") {
|
|
511
|
-
// `chant workspace graph --composites` (#2662)
|
|
512
|
-
result.composites = true;
|
|
513
|
-
} else if (arg === "--intent") {
|
|
514
|
-
// `chant workspace graph --intent <path[:start-end]|path#symbol>` (#2651), or `--intent --record <id>` with no region.
|
|
515
|
-
const value = args[i + 1];
|
|
516
|
-
if (value !== undefined && !value.startsWith("-")) result.intent = args[++i];
|
|
517
|
-
else if (args.includes("--record")) result.intent = "";
|
|
518
|
-
else throw new Error("--intent needs a region: --intent <path[:start-end]|path#symbol>, or --intent --record <id>");
|
|
519
|
-
} else if (arg === "--follow-squash") {
|
|
520
|
-
// `chant workspace graph --intent ... --follow-squash` and `chant workspace runs --follow-squash` (#3035)
|
|
521
|
-
result.followSquash = true;
|
|
522
|
-
} else if (arg === "--record") {
|
|
523
|
-
// `chant workspace graph --intent --record <id>`
|
|
524
|
-
result.record = args[++i];
|
|
525
|
-
if (!result.record || result.record.startsWith("-")) throw new Error("--record needs a record id: --record <id>");
|
|
526
|
-
} else if (arg === "--path") {
|
|
527
|
-
// `chant workspace patch <range> --path <p>`, repeatable
|
|
528
|
-
const value = args[++i];
|
|
529
|
-
if (!value || value.startsWith("-")) throw new Error("--path needs a path: --path <path>");
|
|
530
|
-
(result.paths ??= []).push(value);
|
|
531
|
-
} else if (arg === "--worktree") {
|
|
532
|
-
// `chant workspace patch [<commit>] --worktree`
|
|
533
|
-
result.worktree = true;
|
|
534
|
-
} else if (arg === "--max-bytes") {
|
|
535
|
-
// `chant workspace patch <range> --max-bytes <n>`
|
|
536
|
-
const value = Number(args[++i]);
|
|
537
|
-
if (!Number.isInteger(value) || value < 1) throw new Error("--max-bytes needs a whole number of bytes above 0");
|
|
538
|
-
result.maxBytes = value;
|
|
539
|
-
} else if (arg === "--changes") {
|
|
540
|
-
// `chant workspace check --changes <base>..<head>` (#2773)
|
|
541
|
-
result.changes = args[++i];
|
|
542
|
-
if (!result.changes || result.changes.startsWith("-")) throw new Error("--changes needs a range: --changes <base>..<head>");
|
|
543
|
-
} else if (arg === "--severity") {
|
|
544
|
-
// `chant workspace check --changes <range> --severity off|warn|fail` (#2773)
|
|
545
|
-
result.severity = args[++i];
|
|
546
|
-
if (!result.severity || result.severity.startsWith("-")) throw new Error("--severity needs off, warn or fail");
|
|
547
|
-
} else if (arg === "--current") {
|
|
548
|
-
result.current = true;
|
|
549
|
-
} else if (arg === "--uncommitted") {
|
|
550
|
-
// `chant workspace records --uncommitted` (#3160)
|
|
551
|
-
result.uncommitted = true;
|
|
552
|
-
} else if (arg === "--set") {
|
|
553
|
-
// `chant workspace records amend <id> --set <file|->` (#2670)
|
|
554
|
-
result.set = args[++i];
|
|
555
|
-
if (!result.set || (result.set.startsWith("-") && result.set !== "-")) throw new Error("--set needs a JSON file, or - for standard input: --set <file|->");
|
|
556
|
-
} else if (arg === "--cover") {
|
|
557
|
-
// `chant workspace box listing set <member> --cover <image>` (#3308)
|
|
558
|
-
result.cover = args[++i];
|
|
559
|
-
if (!result.cover || result.cover.startsWith("-")) throw new Error("--cover needs a PNG, JPEG or WebP file: --cover <image>");
|
|
560
|
-
} else if (arg === "--cover-path") {
|
|
561
|
-
// `chant workspace box listing set <member> --cover <image> --cover-path <path>` (#3308)
|
|
562
|
-
result.coverPath = args[++i];
|
|
563
|
-
if (!result.coverPath || result.coverPath.startsWith("-")) throw new Error("--cover-path needs a path from the workspace root: --cover-path <path>");
|
|
564
|
-
} else if (arg === "--records") {
|
|
565
|
-
// `chant workspace box publish <member> --records` (#3165): the records kept uncommitted, not a work item.
|
|
566
|
-
result.records = true;
|
|
567
|
-
} else if (arg === "--expect") {
|
|
568
|
-
// `chant workspace records amend|review|close <id> --expect <digest>` (#3173): the record's digest the caller last read.
|
|
569
|
-
result.expect = args[++i];
|
|
570
|
-
if (!result.expect || result.expect.startsWith("-")) throw new Error("--expect needs the record's digest, as records --json prints it: --expect <digest>");
|
|
571
|
-
} else if (arg === "--label") {
|
|
572
|
-
// `chant workspace wip save --label <text>` (#3172)
|
|
573
|
-
result.label = args[++i];
|
|
574
|
-
if (!result.label || result.label.startsWith("-")) throw new Error("--label needs the snapshot's name, such as a turn id: --label <text>");
|
|
575
|
-
} else if (arg === "--branch") {
|
|
576
|
-
// `chant workspace wip --branch <branch>` (#3172)
|
|
577
|
-
result.branch = args[++i];
|
|
578
|
-
if (!result.branch || result.branch.startsWith("-")) throw new Error("--branch needs a branch name: --branch <branch>");
|
|
579
|
-
} else if (arg === "--workflow") {
|
|
580
|
-
// `chant ci workflow --workflow <name>`, repeatable (#3573)
|
|
581
|
-
const name = args[++i];
|
|
582
|
-
if (!name || name.startsWith("-")) throw new Error("--workflow needs a workflow's name: --workflow <name>");
|
|
583
|
-
result.ciWorkflows = [...(result.ciWorkflows ?? []), name];
|
|
584
|
-
} else if (arg === "--chant") {
|
|
585
|
-
// `chant ci workflow --chant <command>` (#3573): what the tick step runs chant with.
|
|
586
|
-
result.ciChant = args[++i];
|
|
587
|
-
if (!result.ciChant || result.ciChant.startsWith("-")) throw new Error("--chant needs the command that runs chant, such as \"npx tsx packages/core/src/cli/main.ts\": --chant <command>");
|
|
588
|
-
} else if (arg === "--install") {
|
|
589
|
-
// `chant ci workflow --install <command>` (#3573): a step before the tick that installs what --chant runs.
|
|
590
|
-
result.ciInstall = args[++i];
|
|
591
|
-
if (!result.ciInstall || result.ciInstall.startsWith("-")) throw new Error("--install needs the install command, such as \"npm install\": --install <command>");
|
|
592
|
-
} else if (arg === "--token-secret") {
|
|
593
|
-
// `chant ci workflow --token-secret <NAME>` (#3573): the secret the tick's tag push authenticates with.
|
|
594
|
-
result.ciTokenSecret = args[++i];
|
|
595
|
-
if (!result.ciTokenSecret || result.ciTokenSecret.startsWith("-")) throw new Error("--token-secret needs a repository secret's name, such as CI_GREEN_TOKEN: --token-secret <NAME>");
|
|
596
|
-
} else if (arg === "--app-id-var") {
|
|
597
|
-
// `chant ci workflow --app-id-var <VAR> --app-key-secret <NAME>` (#3573): a GitHub App token pushes the tags.
|
|
598
|
-
result.ciAppIdVar = args[++i];
|
|
599
|
-
if (!result.ciAppIdVar || result.ciAppIdVar.startsWith("-")) throw new Error("--app-id-var needs the Actions variable holding the App's id: --app-id-var <VAR>");
|
|
600
|
-
} else if (arg === "--app-key-secret") {
|
|
601
|
-
result.ciAppKeySecret = args[++i];
|
|
602
|
-
if (!result.ciAppKeySecret || result.ciAppKeySecret.startsWith("-")) throw new Error("--app-key-secret needs the secret holding the App's private key: --app-key-secret <NAME>");
|
|
603
|
-
} else if (arg === "--verdict") {
|
|
604
|
-
// `chant workspace records review <id> --verdict agree|dissent|abstain` (#2670)
|
|
605
|
-
result.verdict = args[++i];
|
|
606
|
-
if (!result.verdict || result.verdict.startsWith("-")) throw new Error("--verdict needs agree, dissent or abstain");
|
|
607
|
-
} else if (arg === "--by") {
|
|
608
|
-
// `chant workspace records review <id> --by <principal>` (#2670): whoever the caller says.
|
|
609
|
-
result.by = args[++i];
|
|
610
|
-
if (!result.by || result.by.startsWith("-")) throw new Error("--by needs the reviewer: --by <principal>");
|
|
611
|
-
// Repeatable for `workspace points answer` (#2739): each person who answered.
|
|
612
|
-
(result.bys ??= []).push(result.by);
|
|
613
|
-
} else if (arg === "--open") {
|
|
614
|
-
// `chant workspace points --open` (#2739): only the questions still open.
|
|
615
|
-
result.open = true;
|
|
616
|
-
} else if (arg === "--inputs") {
|
|
617
|
-
// `chant workspace points ask <point> --inputs <file|-|json>` (#2739; JSON itself, #3403)
|
|
618
|
-
result.inputs = args[++i];
|
|
619
|
-
if (!result.inputs || (result.inputs.startsWith("-") && result.inputs !== "-")) throw new Error("--inputs needs a JSON file, - for standard input, or the JSON itself: --inputs <file|-|json>");
|
|
620
|
-
} else if (arg === "--candidates") {
|
|
621
|
-
// `chant workspace points ask <point> --candidates <file|-|json>` (#3403): an ad-hoc point's question and candidates.
|
|
622
|
-
result.candidates = args[++i];
|
|
623
|
-
if (!result.candidates || (result.candidates.startsWith("-") && result.candidates !== "-")) throw new Error("--candidates needs a JSON file, - for standard input, or the JSON itself: --candidates <file|-|json>");
|
|
624
|
-
} else if (arg === "--response") {
|
|
625
|
-
// `chant workspace points ask <point> --response <file>` (#2739): a POST /v1/systemone response the caller got.
|
|
626
|
-
result.response = args[++i];
|
|
627
|
-
if (!result.response || result.response.startsWith("-")) throw new Error("--response needs a JSON file: --response <file>");
|
|
628
|
-
} else if (arg === "--subject") {
|
|
629
|
-
// `chant workspace points ask <point> --subject <id>` (#2739): what the question is about.
|
|
630
|
-
result.subject = args[++i];
|
|
631
|
-
if (!result.subject || result.subject.startsWith("-")) throw new Error("--subject needs what the question is about, such as a work item id: --subject <id>");
|
|
632
|
-
} else if (arg === "--store") {
|
|
633
|
-
// `chant workspace points ask <point> --store ledger` (#3815): where a new question goes.
|
|
634
|
-
const store = args[++i];
|
|
635
|
-
if (store !== "tree" && store !== "ledger") throw new Error("--store is tree (the answer kind's directory in the working tree) or ledger (chant/lifecycle): --store <tree|ledger>");
|
|
636
|
-
result.store = store;
|
|
637
|
-
} else if (arg === "--answer") {
|
|
638
|
-
// `chant workspace points answer <id> --answer <value>` (#2739)
|
|
639
|
-
result.answer = args[++i];
|
|
640
|
-
if (result.answer === undefined || result.answer === "") throw new Error("--answer needs one of the question's candidates: --answer <value>");
|
|
641
|
-
} else if (arg === "--sign") {
|
|
642
|
-
// `chant workspace records review <id> --sign [<key file>]` (#2687): seal the verdict.
|
|
643
|
-
// `records new` and `records amend` take it too, to seal the record's author (#2688).
|
|
644
|
-
// `chant approve <op> <gate> --sign [<key file>]` seals a gate approval (#3163).
|
|
645
|
-
// With no key file, git's user.signingkey, as `git commit -S` reads it.
|
|
646
|
-
const next = args[i + 1];
|
|
647
|
-
result.sign = next !== undefined && !next.startsWith("-") ? args[++i] : true;
|
|
648
|
-
} else if (arg === "--session") {
|
|
649
|
-
// `chant workspace records review <id> --session <id>` (#2670)
|
|
650
|
-
result.session = args[++i];
|
|
651
|
-
if (!result.session || result.session.startsWith("-")) throw new Error("--session needs a session id: --session <id>");
|
|
652
|
-
} else if (arg === "--prefix") {
|
|
653
|
-
// `chant workspace records new <kind> --prefix <prefix>` (#2670): the id prefix to allocate under.
|
|
654
|
-
result.prefix = args[++i];
|
|
655
|
-
if (!result.prefix || result.prefix.startsWith("-")) throw new Error("--prefix needs an id prefix: --prefix <prefix>");
|
|
656
|
-
} else if (arg === "--key" || arg === "--check-id" || arg === "--claim" || arg === "--environment" || arg === "--envelope" || arg === "--threshold") {
|
|
657
|
-
// `chant workspace evidence sign|verify` and `chant workspace signers` (#2553)
|
|
658
|
-
const value = args[++i];
|
|
659
|
-
if (value === undefined || value.startsWith("-")) throw new Error(`${arg} needs a value`);
|
|
660
|
-
const field = ({ "--key": "key", "--check-id": "checkId", "--claim": "claim", "--environment": "environment", "--envelope": "envelope", "--threshold": "threshold" } as const)[arg];
|
|
661
|
-
result[field] = value;
|
|
662
|
-
} else if (arg === "--require") {
|
|
663
|
-
// `chant workspace records|verify --require attested` (#2547)
|
|
664
|
-
result.require = args[++i];
|
|
665
|
-
if (!result.require || result.require.startsWith("-")) throw new Error("--require needs a provenance level: --require attested");
|
|
666
|
-
} else if (arg === "--ambient") {
|
|
667
|
-
result.ambient = true;
|
|
668
|
-
} else if (arg === "--check-live") {
|
|
669
|
-
result.checkLive = true;
|
|
670
|
-
} else if (arg === "--check-snapshot") {
|
|
671
|
-
result.checkSnapshot = true;
|
|
672
|
-
} else if (arg === "--fail-on-drift") {
|
|
673
|
-
result.failOnDrift = true;
|
|
674
|
-
} else if (arg === "--run-examples") {
|
|
675
|
-
result.runExamples = true;
|
|
676
|
-
} else if (arg === "--pinned-digest") {
|
|
677
|
-
result.pinnedDigest = args[++i];
|
|
678
|
-
} else if (arg === "--check") {
|
|
679
|
-
result.check = true;
|
|
680
|
-
} else if (arg === "--bump") {
|
|
681
|
-
result.bump = true;
|
|
682
|
-
} else if (arg === "--component") {
|
|
683
|
-
result.component = args[++i];
|
|
684
|
-
} else if (arg === "--digest") {
|
|
685
|
-
result.digest = args[++i];
|
|
686
|
-
if (result.digest !== undefined) (result.digests ??= []).push(result.digest);
|
|
687
|
-
} else if (arg === "--release-plan") {
|
|
688
|
-
result.releasePlanFile = args[++i];
|
|
689
|
-
} else if (arg === "--git-sha") {
|
|
690
|
-
result.gitSha = args[++i];
|
|
691
|
-
} else if (arg === "--run-id") {
|
|
692
|
-
result.runId = args[++i];
|
|
693
|
-
} else if (arg === "--actor") {
|
|
694
|
-
result.actor = args[++i];
|
|
695
|
-
} else if (arg === "--approver") {
|
|
696
|
-
result.approver = args[++i];
|
|
697
|
-
} else if (arg === "--relayed-by") {
|
|
698
|
-
// `chant approve <op> <gate> --relayed-by <principal>` and `workspace points answer <id> --relayed-by <principal>` (#3402):
|
|
699
|
-
// who carried the approval or answer to chant for the person it names.
|
|
700
|
-
result.relayedBy = args[++i];
|
|
701
|
-
if (!result.relayedBy || result.relayedBy.startsWith("-")) throw new Error("--relayed-by needs the principal that relayed it: --relayed-by <principal>");
|
|
702
|
-
} else if (arg === "--on") {
|
|
703
|
-
// `chant run ... --on <lexicon>` (#2121) — which runtime hosts the run.
|
|
704
|
-
result.on = args[++i];
|
|
705
|
-
if (!result.on || result.on.startsWith("-")) throw new Error("--on needs a runtime name: --on <lexicon>");
|
|
706
|
-
} else if (arg === "--compare-to") {
|
|
707
|
-
result.compareTo = args[++i];
|
|
708
|
-
} else if (arg === "--no-release-record") {
|
|
709
|
-
result.noReleaseRecord = true;
|
|
710
|
-
} else if (arg === "--fold") {
|
|
711
|
-
result.fold = true;
|
|
712
|
-
} else if (arg === "--no-cache") {
|
|
713
|
-
// `chant workspace graph --no-cache` (#2876): read every member.
|
|
714
|
-
result.noCache = true;
|
|
715
|
-
} else if (arg === "--no-fold") {
|
|
716
|
-
// chant #1134 — fold is the default build path; this is the explicit
|
|
717
|
-
// opt-out, and like --fold it beats chant.config.ts's build.fold.
|
|
718
|
-
result.fold = false;
|
|
719
|
-
} else if (arg === "--sandbox") {
|
|
720
|
-
result.sandbox = true;
|
|
721
|
-
} else if (arg === "--fold-rank") {
|
|
722
|
-
// chant #1083 — same context-sensitive shape as --report above:
|
|
723
|
-
// `--fold-rank` alone prints the ranked-blocker report; `--fold-rank
|
|
724
|
-
// <path>` ALSO writes the Brendan Gregg collapsed-format export there.
|
|
725
|
-
const next = args[i + 1];
|
|
726
|
-
if (next && !next.startsWith("-")) {
|
|
727
|
-
result.foldRankCollapsedFile = next;
|
|
728
|
-
i++;
|
|
729
|
-
} else {
|
|
730
|
-
result.foldRank = true;
|
|
731
|
-
}
|
|
732
|
-
} else if (arg === "--param") {
|
|
733
|
-
// chant #1118/#1127 — `--param name=value` (space-separated) and
|
|
734
|
-
// `--param=name=value` (joined, split above at its first `=` into flag
|
|
735
|
-
// `--param` + value `name=value`) both land here and behave
|
|
736
|
-
// identically; there is no separate joined-form error anymore (the
|
|
737
|
-
// #1118 hard error this superseded only existed because the parser
|
|
738
|
-
// didn't support joined forms at all — now that it does, the joined
|
|
739
|
-
// form is just as valid as the space-separated one).
|
|
740
|
-
(result.param ??= []).push(args[++i]);
|
|
741
|
-
} else if (arg === "--lexicon-output") {
|
|
742
|
-
// `--lexicon-output <lexicon>=<path>` (repeatable); the joined form
|
|
743
|
-
// `--lexicon-output=otel=a.yml` arrives here already split at the first `=`.
|
|
744
|
-
(result.lexiconOutput ??= []).push(args[++i]);
|
|
745
|
-
} else if (arg === "--params-file") {
|
|
746
|
-
result.paramsFile = args[++i];
|
|
747
|
-
} else if (arg === "--projection") {
|
|
748
|
-
result.projection = args[++i];
|
|
749
|
-
} else if (arg === "--interval") {
|
|
750
|
-
result.interval = args[++i];
|
|
751
|
-
} else if (arg === "--lease-ttl") {
|
|
752
|
-
result.leaseTtl = args[++i];
|
|
753
|
-
} else if (arg === "--steward") {
|
|
754
|
-
// #2731 — the name is optional: a project with one steward runs it
|
|
755
|
-
// with a bare `--steward`.
|
|
756
|
-
const next = args[i + 1];
|
|
757
|
-
if (next !== undefined && !next.startsWith("-")) {
|
|
758
|
-
result.steward = next;
|
|
759
|
-
i++;
|
|
760
|
-
} else {
|
|
761
|
-
result.steward = "";
|
|
762
|
-
}
|
|
763
|
-
} else if (arg === "--once") {
|
|
764
|
-
result.once = true;
|
|
765
|
-
} else if (arg === "--work") {
|
|
766
|
-
// `chant run <op> --work <id>` (#2748)
|
|
767
|
-
const value = args[++i];
|
|
768
|
-
if (!value || value.startsWith("-")) throw new Error("--work needs a work item id: --work <id>");
|
|
769
|
-
result.work = value;
|
|
770
|
-
} else if (arg === "--holder" || arg === "--ttl" || arg === "--token" || arg === "--outcome") {
|
|
771
|
-
// `chant workspace work claim|renew|release <id>` (#2732)
|
|
772
|
-
const value = args[++i];
|
|
773
|
-
if (!value || value.startsWith("-")) throw new Error(`${arg} needs a value: ${arg} <${arg.slice(2)}>`);
|
|
774
|
-
result[arg.slice(2) as "holder" | "ttl" | "token" | "outcome"] = value;
|
|
775
|
-
} else if (arg === "--signer") {
|
|
776
|
-
// `chant workspace runs statement <id> --signer <principal>` (#3192): the runner principal that will sign.
|
|
777
|
-
const value = args[++i];
|
|
778
|
-
if (!value || value.startsWith("-")) throw new Error("--signer needs a principal: --signer <principal>");
|
|
779
|
-
result.signer = value;
|
|
780
|
-
} else if (arg === "--unit" || arg === "--decision") {
|
|
781
|
-
// `chant workspace runs --unit <id> | --decision <id>` (#3033): the runs on one work item, or for one decision.
|
|
782
|
-
const value = args[++i];
|
|
783
|
-
if (!value || value.startsWith("-")) throw new Error(`${arg} needs an id: ${arg} <id>`);
|
|
784
|
-
result[arg.slice(2) as "unit" | "decision"] = value;
|
|
785
|
-
} else if (arg === "--note") {
|
|
786
|
-
result.note = args[++i];
|
|
787
|
-
} else if (arg === "--reason") {
|
|
788
|
-
// `chant approve policy-override <subject> --reason <text>` (#3760): why the denied plan goes out anyway.
|
|
789
|
-
result.reason = args[++i];
|
|
790
|
-
if (result.reason === undefined || result.reason.startsWith("-")) throw new Error("--reason needs the text of the reason: --reason <text>");
|
|
791
|
-
} else if (arg === "--rule") {
|
|
792
|
-
// `chant approve policy-override <subject> --rule <id>` (#3760), once per rule that denied the plan.
|
|
793
|
-
const value = args[++i];
|
|
794
|
-
if (!value || value.startsWith("-")) throw new Error("--rule needs a rule id: --rule <id>");
|
|
795
|
-
(result.rules ??= []).push(value);
|
|
796
|
-
} else if (arg === "--expire") {
|
|
797
|
-
result.expire = true;
|
|
798
|
-
} else if (arg === "--role") {
|
|
799
|
-
// #2508 — a role the approver holds, for a gate whose quorum names
|
|
800
|
-
// roles. Repeatable, and a comma list works too.
|
|
801
|
-
const value = args[++i] ?? "";
|
|
802
|
-
result.roles = [...(result.roles ?? []), ...value.split(",").map((r) => r.trim()).filter(Boolean)];
|
|
803
|
-
} else if (arg === "--agent") {
|
|
804
|
-
// #2508 — record the approval as an agent's rather than a person's.
|
|
805
|
-
result.agent = true;
|
|
806
|
-
} else if (arg === "--allow-code") {
|
|
807
|
-
// #2550 — `chant workspace upgrade` runs a template's code migrations
|
|
808
|
-
// only when asked to.
|
|
809
|
-
result.allowCode = true;
|
|
810
|
-
} else if (arg === "--source") {
|
|
811
|
-
// #2551 — `chant workspace upgrade --source <repo>[#<member>]`.
|
|
812
|
-
result.source = args[++i];
|
|
813
|
-
if (!result.source || result.source.startsWith("-")) throw new Error("--source needs a template: --source <repo>[#<member>]");
|
|
814
|
-
} else if (arg === "--tags") {
|
|
815
|
-
// #2551 — `chant workspace adopt-lineage --tags <glob>`, also hash-index and versions.
|
|
816
|
-
result.tags = args[++i];
|
|
817
|
-
if (!result.tags || result.tags.startsWith("-")) throw new Error("--tags needs a tag glob: --tags 'v*'");
|
|
818
|
-
} else if (arg === "--index") {
|
|
819
|
-
// #2551 — `chant workspace adopt-lineage --index <file>`.
|
|
820
|
-
result.index = args[++i];
|
|
821
|
-
if (!result.index || result.index.startsWith("-")) throw new Error("--index needs a hash index file: --index <file>");
|
|
822
|
-
} else if (arg === "--remove") {
|
|
823
|
-
// #2552 — `chant workspace import --remove` removes the export member instead of writing it again.
|
|
824
|
-
result.remove = true;
|
|
825
|
-
} else if (arg === "--available") {
|
|
826
|
-
// #2551 — `chant workspace versions --available` lists the template's version tags.
|
|
827
|
-
result.available = true;
|
|
828
|
-
} else if (arg === "--root-only") {
|
|
829
|
-
// #2537 — `chant build` and `chant lint` at a declared workspace root
|
|
830
|
-
// run on the root project alone instead of refusing with WSP000.
|
|
831
|
-
result.rootOnly = true;
|
|
832
|
-
} else if (arg === "--generated") {
|
|
833
|
-
// #2641 — `chant workspace check --generated` runs each declared
|
|
834
|
-
// generator and compares its output with the file in the tree.
|
|
835
|
-
result.generated = true;
|
|
836
|
-
} else if (arg === "--member") {
|
|
837
|
-
// #2537 — `chant workspace build|lint|audit|graph --member <name>`.
|
|
838
|
-
// Repeatable, and a comma list works too.
|
|
839
|
-
const value = args[++i];
|
|
840
|
-
if (!value || value.startsWith("-")) throw new Error("--member needs a member or group name: --member <name>");
|
|
841
|
-
result.members = [...(result.members ?? []), ...value.split(",").map((m) => m.trim()).filter(Boolean)];
|
|
842
|
-
} else if (arg === "--allow-same-origin") {
|
|
843
|
-
// chant#2384 — record a resolution the same-origin rule would refuse,
|
|
844
|
-
// deliberately. Flagged on the record, not just accepted quietly.
|
|
845
|
-
result.allowSameOrigin = true;
|
|
846
|
-
} else if (arg === "--plan") {
|
|
847
|
-
result.plan = args[++i];
|
|
848
|
-
} else if (arg === "--url") {
|
|
849
|
-
result.url = args[++i];
|
|
850
|
-
} else if (arg === "--op") {
|
|
851
|
-
result.op = args[++i];
|
|
852
|
-
} else if (arg === "--since") {
|
|
853
|
-
result.since = args[++i];
|
|
854
|
-
} else if (arg === "--limit") {
|
|
855
|
-
// Parsed here, validated by the handler — `parseArgs` reports shape, not
|
|
856
|
-
// policy, the same split every other value flag here uses.
|
|
857
|
-
result.limit = Number(args[++i]);
|
|
858
|
-
} else if (arg.startsWith("--")) {
|
|
859
|
-
// chant #1127 — every recognized flag is matched above; anything left
|
|
860
|
-
// starting with `--` is unrecognized, whether it arrived bare
|
|
861
|
-
// (`--bogus`) or joined (`--bogus=value`, already split into
|
|
862
|
-
// `--bogus` + `value` above). This used to fall through silently (the
|
|
863
|
-
// "ignores unknown flags" case) — a typo'd or misremembered flag would
|
|
864
|
-
// vanish with no diagnostic, exactly like the silent-drop this issue
|
|
865
|
-
// closes for joined values. Point at --help rather than enumerating
|
|
866
|
-
// every flag here: this parser's flag set is one flat list shared by
|
|
867
|
-
// every command, not scoped per-command, so "the command's known
|
|
868
|
-
// flags" isn't something this loop can name in isolation.
|
|
869
|
-
throw new Error(`Unknown flag: ${arg}\nRun "chant --help" to see supported flags.`);
|
|
870
|
-
} else if (!arg.startsWith("-")) {
|
|
871
|
-
if (result.command) (result.positionals ??= []).push(arg);
|
|
872
|
-
if (!result.command) {
|
|
873
|
-
result.command = arg;
|
|
874
|
-
} else if (result.path === ".") {
|
|
875
|
-
result.path = arg;
|
|
876
|
-
} else if (!result.extraPositional) {
|
|
877
|
-
result.extraPositional = arg;
|
|
878
|
-
} else {
|
|
879
|
-
result.extraPositional2 = arg;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
i++;
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
// #2603 — `--promote-to` (#2575) adds a job to the pipeline that generate
|
|
887
|
-
// mode synthesizes; no other command or mode reads it. Checked here, once
|
|
888
|
-
// the whole command line is known, rather than in the build handler, so
|
|
889
|
-
// `chant build --promote-to prod` and `chant run --promote-to prod` both
|
|
890
|
-
// fail instead of running as if the flag were absent. A lexicon-mounted
|
|
891
|
-
// command that takes its own `--promote-to` still gets it: `main` tries the
|
|
892
|
-
// plugin commands before rethrowing a parse error.
|
|
893
|
-
if (result.promoteTo && !(result.command === "build" && result.components && result.generate)) {
|
|
894
|
-
throw new Error(
|
|
895
|
-
"--promote-to needs build --components --generate <lexicon>: it adds a promote job to the generated CI pipeline, and only generate mode emits one.",
|
|
896
|
-
);
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
return result;
|
|
900
|
-
}
|
|
901
|
-
|
|
902
132
|
/**
|
|
903
133
|
* Print help message. `groups` — lexicon-contributed command groups
|
|
904
134
|
* (chant #1078), best-effort loaded from the current project; composed in
|
|
@@ -2271,47 +1501,6 @@ async function main(): Promise<void> {
|
|
|
2271
1501
|
await flushAndExit(await match.def.handler(ctx));
|
|
2272
1502
|
}
|
|
2273
1503
|
|
|
2274
|
-
/**
|
|
2275
|
-
* Wait until a writable stream has flushed its buffer. `process.exit()` discards
|
|
2276
|
-
* data still buffered for an async sink (a pipe or file), truncating large output
|
|
2277
|
-
* at the ~64 KB pipe buffer — so `chant graph --format ir` piped into a consumer
|
|
2278
|
-
* loses everything past 64 KB and its JSON won't parse. A TTY writes
|
|
2279
|
-
* synchronously (`writableLength` stays 0), so this is a no-op there. Resolves on
|
|
2280
|
-
* `error`/`close` too, so a reader that closes early (EPIPE) can't hang exit.
|
|
2281
|
-
* Exported for testing.
|
|
2282
|
-
*/
|
|
2283
|
-
export function waitForStreamDrain(stream: NodeJS.WriteStream): Promise<void> {
|
|
2284
|
-
return new Promise((resolve) => {
|
|
2285
|
-
const tick = (): void => {
|
|
2286
|
-
if (stream.writableLength === 0 || stream.writableEnded || stream.destroyed) {
|
|
2287
|
-
cleanup();
|
|
2288
|
-
resolve();
|
|
2289
|
-
return;
|
|
2290
|
-
}
|
|
2291
|
-
stream.once("drain", tick);
|
|
2292
|
-
};
|
|
2293
|
-
const stop = (): void => {
|
|
2294
|
-
cleanup();
|
|
2295
|
-
resolve();
|
|
2296
|
-
};
|
|
2297
|
-
const cleanup = (): void => {
|
|
2298
|
-
stream.off("drain", tick);
|
|
2299
|
-
stream.off("error", stop);
|
|
2300
|
-
stream.off("close", stop);
|
|
2301
|
-
};
|
|
2302
|
-
stream.once("error", stop);
|
|
2303
|
-
stream.once("close", stop);
|
|
2304
|
-
tick();
|
|
2305
|
-
});
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
/** Flush stdout+stderr, then exit — so a large piped payload isn't truncated. */
|
|
2309
|
-
async function flushAndExit(code: number): Promise<never> {
|
|
2310
|
-
await waitForStreamDrain(process.stdout);
|
|
2311
|
-
await waitForStreamDrain(process.stderr);
|
|
2312
|
-
process.exit(code);
|
|
2313
|
-
}
|
|
2314
|
-
|
|
2315
1504
|
// Only run main when executed directly, not when imported. Robust to symlinked
|
|
2316
1505
|
// invocation paths — see isEntryPoint (a raw string compare silently no-ops the
|
|
2317
1506
|
// whole CLI through the npm .bin shim / a symlinked checkout).
|