@aiwg/cli 2026.10.1 → 2026.10.3
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/agentic/code/providers/capability-matrix.yaml +270 -0
- package/agentic/code/providers/model-capabilities.v1.json +3091 -24
- package/bin/aiwg.mjs +86 -21
- package/dist/src/a2a/codecs.js +9 -0
- package/dist/src/artifacts/corpus-tools/vision-extract.js +105 -15
- package/dist/src/artifacts/repair.js +9 -4
- package/dist/src/channel/manager.mjs +59 -10
- package/dist/src/cli/child-process-result.js +40 -0
- package/dist/src/cli/env.js +38 -16
- package/dist/src/cli/flag-parsing.js +236 -0
- package/dist/src/cli/handlers/decision.js +210 -4
- package/dist/src/cli/handlers/diagnose.js +9 -2
- package/dist/src/cli/handlers/feedback.js +14 -5
- package/dist/src/cli/handlers/init.js +245 -30
- package/dist/src/cli/handlers/mc.js +23 -0
- package/dist/src/cli/handlers/models.js +69 -6
- package/dist/src/cli/handlers/ralph.js +3 -0
- package/dist/src/cli/handlers/refresh.js +16 -0
- package/dist/src/cli/handlers/regenerate.js +14 -0
- package/dist/src/cli/handlers/runtime-info.js +24 -9
- package/dist/src/cli/handlers/script-runner.js +16 -6
- package/dist/src/cli/handlers/session.js +396 -62
- package/dist/src/cli/handlers/sessions.js +146 -40
- package/dist/src/cli/handlers/setup-manifest.js +439 -39
- package/dist/src/cli/handlers/setup.js +139 -39
- package/dist/src/cli/handlers/subcommands.js +3 -1
- package/dist/src/cli/handlers/team.js +18 -8
- package/dist/src/cli/handlers/use.js +13 -0
- package/dist/src/cli/handlers/utilities.js +106 -23
- package/dist/src/cli/prompt-utils.js +72 -0
- package/dist/src/cli/provider-resolution.js +11 -0
- package/dist/src/config/aiwg-config.js +268 -4
- package/dist/src/config/cli.js +146 -19
- package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
- package/dist/src/config/project-artifacts-health.mjs +14 -3
- package/dist/src/config/user-config.js +36 -10
- package/dist/src/decision/adapters/jev.js +75 -27
- package/dist/src/decision/driver.js +3 -1
- package/dist/src/decision/entry.js +38 -6
- package/dist/src/decision/heldout/collector.js +10 -1
- package/dist/src/decision/index.js +1 -0
- package/dist/src/decision/interop.js +60 -8
- package/dist/src/decision/ledger.js +839 -0
- package/dist/src/decision/validate.js +6 -3
- package/dist/src/effects/dispatch-verifier.js +252 -0
- package/dist/src/effects/index.js +1 -0
- package/dist/src/features/installer.js +2 -2
- package/dist/src/flow/graph-metadata.js +5 -0
- package/dist/src/gates/providers/loader.js +3 -1
- package/dist/src/installation/manager-command.mjs +1 -1
- package/dist/src/installation/manager.mjs +17 -2
- package/dist/src/lint/runner.js +2 -2
- package/dist/src/mcp/adapters/codex-runtime.js +360 -56
- package/dist/src/mcp/cli.mjs +587 -77
- package/dist/src/mcp/config-file.mjs +279 -0
- package/dist/src/mcp/config-layers.mjs +348 -0
- package/dist/src/mcp/credentials.mjs +484 -0
- package/dist/src/mcp/grok-build-config.mjs +16 -26
- package/dist/src/mcp/helpers.mjs +106 -2
- package/dist/src/mcp/omp-config.mjs +50 -29
- package/dist/src/mcp/profiles.js +97 -23
- package/dist/src/mcp/profiles.mjs +99 -27
- package/dist/src/mcp/registry.js +264 -57
- package/dist/src/mcp/registry.mjs +198 -45
- package/dist/src/mcp/server.mjs +403 -20
- package/dist/src/mcp/toml-string.mjs +9 -0
- package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
- package/dist/src/mcp/tool-filters.mjs +357 -0
- package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
- package/dist/src/mcp/tools/decision.mjs +21 -3
- package/dist/src/mcp/tools/orchestration.mjs +38 -0
- package/dist/src/mcp/tools/subsystems.mjs +39 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +1539 -0
- package/dist/src/mcp/tools/worker-shell-control.mjs +258 -0
- package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
- package/dist/src/memory/project-registry.js +2 -2
- package/dist/src/mission-protocol/codecs.js +639 -1
- package/dist/src/mission-protocol/types.js +110 -0
- package/dist/src/mission-protocol/worker-status.js +2 -0
- package/dist/src/models/config-loader.js +70 -13
- package/dist/src/models/grok-build-models.js +93 -41
- package/dist/src/models/model-capabilities.v1.json +3091 -24
- package/dist/src/models/model-discovery.js +862 -63
- package/dist/src/models/provider-policy.js +625 -11
- package/dist/src/models/qualification-digest.mjs +17 -0
- package/dist/src/models/resolver.js +259 -0
- package/dist/src/models/worker-direct-readiness.js +529 -0
- package/dist/src/models/worker-dispatch-offer.js +169 -0
- package/dist/src/models/worker-health-readiness.js +131 -0
- package/dist/src/models/worker-installation.mjs +879 -0
- package/dist/src/models/wrapper-route.js +18 -0
- package/dist/src/ops/registry.js +9 -14
- package/dist/src/plugins/standalone-packager.js +4 -3
- package/dist/src/process/bounded-child-process.mjs +387 -0
- package/dist/src/process/cli-command.mjs +75 -0
- package/dist/src/providers/capability-matrix.js +8 -0
- package/dist/src/providers/capability-matrix.yaml +270 -0
- package/dist/src/providers/grok-build-headless.js +43 -21
- package/dist/src/providers/provider-definitions.js +9 -1
- package/dist/src/providers/provider-definitions.mjs +9 -2
- package/dist/src/serve/executor-registry.js +16 -24
- package/dist/src/serve/fleet-mission-conductor.js +9 -0
- package/dist/src/serve/mission-conductor.js +9 -0
- package/dist/src/serve/shared-host-scheduler.js +2 -0
- package/dist/src/serve/worker-invocation.js +538 -0
- package/dist/src/serve/worker-stdin-frame.mjs +107 -0
- package/dist/src/sessions/adapter-registry.js +45 -0
- package/dist/src/sessions/adapters/generic.js +37 -3
- package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
- package/dist/src/sessions/adapters/grokbot.js +423 -24
- package/dist/src/sessions/adapters/muse-workspace-scan.js +108 -0
- package/dist/src/sessions/adapters/muse.js +68 -29
- package/dist/src/sessions/adapters/pi.js +1 -0
- package/dist/src/sessions/batch-contracts.js +13 -1
- package/dist/src/sessions/batch-import.js +23 -42
- package/dist/src/sessions/candidates.js +47 -11
- package/dist/src/sessions/contracts.js +35 -0
- package/dist/src/sessions/coverage-preflight.js +134 -0
- package/dist/src/sessions/discovery.js +3 -0
- package/dist/src/sessions/grok-build-cli.js +67 -5
- package/dist/src/sessions/importer.js +24 -8
- package/dist/src/sessions/index.js +2 -0
- package/dist/src/sessions/repository.js +54 -13
- package/dist/src/sessions/workspace-discovery.js +99 -37
- package/dist/src/skills/adapters/clawhub.js +10 -8
- package/dist/src/skills/adapters/openclaw.js +10 -7
- package/dist/src/smiths/context-pipeline/parallelism-section.js +192 -3
- package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
- package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
- package/dist/src/smiths/mcpsmith/example.js +1 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +10 -14
- package/dist/src/storage/backends/logseq.js +68 -7
- package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
- package/dist/src/testing/generators/test-code-generator.js +57 -30
- package/dist/src/uhp/client.js +11 -1
- package/dist/src/uhp/mission.js +5 -0
- package/dist/src/update/checker.mjs +5 -5
- package/dist/src/update/notifier.mjs +54 -2
- package/dist/src/writing/fidelity.js +18 -1
- package/package.json +18 -1
- package/schemas/mission-v1.schema.json +2429 -0
- package/schemas/models/model-catalog.v1.schema.json +301 -0
- package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
- package/schemas/models/model-policy.v1.schema.json +14 -0
- package/schemas/models/provider-model-capabilities.v1.schema.json +1066 -0
- package/tools/_resolve-impl.mjs +39 -0
- package/tools/agents/deploy-agents.mjs +15 -2
- package/tools/agents/providers/base.mjs +49 -32
- package/tools/agents/providers/grokbot.mjs +11 -12
- package/tools/agents/providers/hermes.mjs +6 -3
- package/tools/agents/providers/omp.mjs +5 -2
- package/tools/agents/providers/openclaw-translator.mjs +19 -5
- package/tools/providers/deepseek-harness-transport.mjs +358 -0
- package/tools/providers/omp-transport.mjs +192 -0
- package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
- package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
- package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
- package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
- package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
- package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
- package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
- package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
- package/tools/ralph-external/lib/pi-adapter.mjs +333 -0
- package/tools/ralph-external/lib/provider-adapter.mjs +690 -0
- package/tools/ralph-external/lib/worker-health.mjs +439 -0
- package/vscode-extension/schemas/aiwg.config.v1.json +1953 -0
|
@@ -4,8 +4,13 @@ import os from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { parseDocument, stringify } from 'yaml';
|
|
6
6
|
import { findPackageRoot } from '../find-package-root.js';
|
|
7
|
+
import { isInteractive } from '../env.js';
|
|
8
|
+
import { boundedSpawnSync } from '../../process/bounded-child-process.mjs';
|
|
7
9
|
import { sha256 } from '../../security/artifact-trust.js';
|
|
8
10
|
import { artifactVerifyHandler } from './artifact-verify.js';
|
|
11
|
+
import { requireFlagValue, MissingFlagValueError } from '../flag-parsing.js';
|
|
12
|
+
import { exitCodeForSpawnResult } from '../child-process-result.js';
|
|
13
|
+
import { askString, createPromptInterface } from '../prompt-utils.js';
|
|
9
14
|
const SETUP_SCHEMA_REL = 'agentic/code/addons/agentic-installer/schemas/v1/setup-manifest.schema.json';
|
|
10
15
|
const GENERATE_HELP = `aiwg setup-generate - generate a starter setup.aiwg.io/v1 SetupManifest
|
|
11
16
|
|
|
@@ -67,15 +72,29 @@ Safety:
|
|
|
67
72
|
Mutating execution refuses to run without explicit confirmation.
|
|
68
73
|
Provider-orchestrated manifests are never handed to an agent unless their
|
|
69
74
|
exact bytes have status verified under the explicit trust policy.
|
|
75
|
+
|
|
76
|
+
Headless input steps (#3062):
|
|
77
|
+
A 'type: ask' step resolves its declared 'params' the same way a 'script'
|
|
78
|
+
step's env vars do (--param/--params-file/env/default); if every declared
|
|
79
|
+
param is already resolved it runs headless, otherwise it is refused,
|
|
80
|
+
naming the missing param names — this CLI has no interactive-capture
|
|
81
|
+
mechanism for 'ask' steps, with or without a terminal. A step marked
|
|
82
|
+
'interactive: true' runs an arbitrary script whose questions cannot be
|
|
83
|
+
enumerated; without a terminal it is refused outright. Every selected
|
|
84
|
+
step (including nested 'platform-route' steps) is preflighted for both
|
|
85
|
+
conditions before any step executes — never partway through.
|
|
70
86
|
`;
|
|
87
|
+
/**
|
|
88
|
+
* A value-taking flag present without a usable value is a usage error, not
|
|
89
|
+
* "not given" (#3062 review item 11) — delegates to the shared strict
|
|
90
|
+
* parser. Callers (the three handlers below) catch `MissingFlagValueError`
|
|
91
|
+
* and report it before any preflight check, spawn, or write.
|
|
92
|
+
* `precedence: 'first'` matches this command's own pre-#3062 behavior (a
|
|
93
|
+
* hand-rolled loop that returned on the first match), unchanged by the
|
|
94
|
+
* shared parser's second-round fix (#3062 second review, finding 4).
|
|
95
|
+
*/
|
|
71
96
|
function flagValue(args, name) {
|
|
72
|
-
|
|
73
|
-
if (args[i] === name) {
|
|
74
|
-
const value = args[i + 1];
|
|
75
|
-
return value && !value.startsWith('--') ? value : undefined;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return undefined;
|
|
97
|
+
return requireFlagValue(args, {}, name);
|
|
79
98
|
}
|
|
80
99
|
function hasFlag(args, ...names) {
|
|
81
100
|
return args.some((arg) => names.includes(arg));
|
|
@@ -238,6 +257,83 @@ function allSteps(manifest) {
|
|
|
238
257
|
function existingRelative(manifestDir, rel) {
|
|
239
258
|
return !!rel && existsSync(path.resolve(manifestDir, rel));
|
|
240
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Detect `on_fail` reference cycles among recovery procedures themselves —
|
|
262
|
+
* go/no-go review blocker 3. A step's `on_fail` can name any recovery
|
|
263
|
+
* procedure, including (structurally, per the shared `SetupStep` type) a
|
|
264
|
+
* step *inside* a recovery procedure's own `steps`. A recovery procedure
|
|
265
|
+
* that (directly, or through another recovery procedure) names itself used
|
|
266
|
+
* to make the old, eager preflight recurse into it forever —
|
|
267
|
+
* `RangeError: Maximum call stack size exceeded`, reproduced in memory by
|
|
268
|
+
* the review.
|
|
269
|
+
*
|
|
270
|
+
* This is a one-time, bounded graph walk over `manifest.spec.recovery[]`
|
|
271
|
+
* only (at most `recovery.length` nodes) — a visited/"on the current path"
|
|
272
|
+
* marker per node means each node is fully explored exactly once, so this
|
|
273
|
+
* terminates and never re-enters a node already being explored; it reports
|
|
274
|
+
* one finding per distinct cycle instead of throwing. An `on_fail` that
|
|
275
|
+
* does not resolve to a known recovery id is reported separately by the
|
|
276
|
+
* existing unresolved-recovery check (`installerConsistencyChecks` above)
|
|
277
|
+
* and is not itself a cycle.
|
|
278
|
+
*
|
|
279
|
+
* This graph check is independent of, and does not change, how `on_fail`
|
|
280
|
+
* references are actually used (`collectPreflightBlockers()`/`runStep()`
|
|
281
|
+
* below): execution never follows an `on_fail` reference more than once
|
|
282
|
+
* (a failing recovery step reports failure directly, it does not itself
|
|
283
|
+
* trigger further recovery), so neither the main-sequence preflight nor a
|
|
284
|
+
* selected recovery's own preflight recurses through `on_fail` at all —
|
|
285
|
+
* see `collectPreflightBlockers()`'s own doc comment. This cycle check
|
|
286
|
+
* exists for the case the type system permits but execution never
|
|
287
|
+
* exercises: a recovery procedure's own steps declaring `on_fail`.
|
|
288
|
+
*/
|
|
289
|
+
function detectRecoveryReferenceCycles(manifest) {
|
|
290
|
+
const recoveries = manifest.spec.recovery ?? [];
|
|
291
|
+
if (recoveries.length === 0)
|
|
292
|
+
return [];
|
|
293
|
+
const onFailTargets = new Map();
|
|
294
|
+
for (const recovery of recoveries) {
|
|
295
|
+
const targets = [];
|
|
296
|
+
const collect = (steps) => {
|
|
297
|
+
steps?.forEach((step) => {
|
|
298
|
+
if (step.on_fail && step.on_fail !== 'recover')
|
|
299
|
+
targets.push(step.on_fail);
|
|
300
|
+
step.routes?.forEach((route) => collect(route.steps));
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
collect(recovery.steps);
|
|
304
|
+
onFailTargets.set(recovery.id, targets);
|
|
305
|
+
}
|
|
306
|
+
const findings = [];
|
|
307
|
+
const reportedCycles = new Set();
|
|
308
|
+
const state = new Map();
|
|
309
|
+
const visit = (id, path) => {
|
|
310
|
+
if (state.get(id) === 'done')
|
|
311
|
+
return;
|
|
312
|
+
if (state.get(id) === 'on-path') {
|
|
313
|
+
const cycle = [...path.slice(path.indexOf(id)), id];
|
|
314
|
+
const key = [...new Set(cycle)].sort().join('\u0000');
|
|
315
|
+
if (!reportedCycles.has(key)) {
|
|
316
|
+
reportedCycles.add(key);
|
|
317
|
+
findings.push({
|
|
318
|
+
severity: 'error',
|
|
319
|
+
path: '/spec/recovery',
|
|
320
|
+
rule: 'recoveryCycle',
|
|
321
|
+
message: `recovery reference cycle: ${cycle.join(' -> ')}`,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
state.set(id, 'on-path');
|
|
327
|
+
for (const next of onFailTargets.get(id) ?? []) {
|
|
328
|
+
if (onFailTargets.has(next))
|
|
329
|
+
visit(next, [...path, id]);
|
|
330
|
+
}
|
|
331
|
+
state.set(id, 'done');
|
|
332
|
+
};
|
|
333
|
+
for (const recovery of recoveries)
|
|
334
|
+
visit(recovery.id, []);
|
|
335
|
+
return findings;
|
|
336
|
+
}
|
|
241
337
|
function installerConsistencyChecks(manifest, manifestDir) {
|
|
242
338
|
if (!manifest)
|
|
243
339
|
return [];
|
|
@@ -262,6 +358,8 @@ function installerConsistencyChecks(manifest, manifestDir) {
|
|
|
262
358
|
findings.push({ severity: 'error', path: `/spec/steps/${index}/on_fail`, rule: 'on_fail', message: `unresolved recovery '${step.on_fail}'` });
|
|
263
359
|
}
|
|
264
360
|
}
|
|
361
|
+
// Go/no-go review blocker 3.
|
|
362
|
+
findings.push(...detectRecoveryReferenceCycles(manifest));
|
|
265
363
|
for (const { step, pointer } of allSteps(manifest)) {
|
|
266
364
|
if (step.type === 'script' && !existingRelative(manifestDir, step.script)) {
|
|
267
365
|
findings.push({ severity: 'error', path: `${pointer}/script`, rule: 'scriptExists', message: `script not found: ${step.script ?? '(missing)'}` });
|
|
@@ -602,13 +700,41 @@ function planLines(manifest, manifestPath, target, params, steps) {
|
|
|
602
700
|
});
|
|
603
701
|
return lines.join('\n') + '\n';
|
|
604
702
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
703
|
+
/**
|
|
704
|
+
* #3062 review item 7: a `null` status already falls through to `code = 1`
|
|
705
|
+
* (not success); this also surfaces the bounded helper's `error`/`signal`
|
|
706
|
+
* diagnostic (e.g. the enriched timeout message naming the bound and
|
|
707
|
+
* override variable) instead of silently dropping it.
|
|
708
|
+
*/
|
|
709
|
+
function commandResult(result) {
|
|
710
|
+
const outcome = exitCodeForSpawnResult(result);
|
|
711
|
+
if (outcome.message)
|
|
712
|
+
console.error(`[setup] ${outcome.message}`);
|
|
713
|
+
const code = result.status === null ? 1 : result.status;
|
|
714
|
+
return { ok: code === 0 && !result.error && !result.signal, status: code };
|
|
608
715
|
}
|
|
716
|
+
/**
|
|
717
|
+
* Run one manifest-author-defined shell command (#3062).
|
|
718
|
+
*
|
|
719
|
+
* Without a terminal, a command that tries to prompt must fail fast instead
|
|
720
|
+
* of hanging forever: bounded (long tier, stdin ignored). With a terminal,
|
|
721
|
+
* unchanged — inherited stdio, unbounded, so a human can actually answer a
|
|
722
|
+
* prompt the command issues.
|
|
723
|
+
*/
|
|
609
724
|
function runShell(command, cwd, env) {
|
|
725
|
+
if (!isInteractive()) {
|
|
726
|
+
const result = boundedSpawnSync(command, [], 'long', {
|
|
727
|
+
cwd, env, shell: true, stdio: ['ignore', 'inherit', 'inherit'],
|
|
728
|
+
});
|
|
729
|
+
return commandResult(result);
|
|
730
|
+
}
|
|
731
|
+
// sync-spawn: interactive manifest-shell-command — runs an arbitrary
|
|
732
|
+
// manifest-author-defined shell command with inherited stdio; it may
|
|
733
|
+
// itself prompt (see tools/testing/sync-spawn-allowlist.json). Reached
|
|
734
|
+
// only when isInteractive() is true (#3062) — the no-terminal path above
|
|
735
|
+
// uses the bounded helper instead. Not a candidate for a bounded timeout.
|
|
610
736
|
const result = spawnSync(command, { cwd, env, shell: true, stdio: 'inherit' });
|
|
611
|
-
return commandResult(result
|
|
737
|
+
return commandResult(result);
|
|
612
738
|
}
|
|
613
739
|
function isDestructiveScript(filePath) {
|
|
614
740
|
const name = path.basename(filePath);
|
|
@@ -619,9 +745,180 @@ function isDestructiveScript(filePath) {
|
|
|
619
745
|
const text = readFileSync(filePath, 'utf8');
|
|
620
746
|
return /\brm\s+-rf\b|\b(cp|mv)\s+-f\b|>\s*\S+/.test(text);
|
|
621
747
|
}
|
|
622
|
-
|
|
748
|
+
/**
|
|
749
|
+
* Param names a `type: ask` step resolves (#3062 review item 10). Reuses
|
|
750
|
+
* the same `params` field `type: script` steps already use to pass env
|
|
751
|
+
* vars — there is no separate "ask step input" field in the schema, and
|
|
752
|
+
* this is the same mechanism, just read by the `ask` branch below instead
|
|
753
|
+
* of passed to a script.
|
|
754
|
+
*/
|
|
755
|
+
function askStepParams(step) {
|
|
756
|
+
return step.params ?? [];
|
|
757
|
+
}
|
|
758
|
+
/** Which of an `ask` step's declared params are not yet resolved (missing from `--param`/params-file/env/default). */
|
|
759
|
+
function missingAskParams(step, params) {
|
|
760
|
+
return askStepParams(step).filter((name) => params[name] === undefined);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Preflight every step in `steps` (recursively into `platform-route` nested
|
|
764
|
+
* steps only) for conditions that would block it from running at all, and
|
|
765
|
+
* return one message per blocker — never a partial list halted at the
|
|
766
|
+
* first step (#3062 review item 13, and the second review's finding 7:
|
|
767
|
+
* refusal must happen before ANY step executes).
|
|
768
|
+
*
|
|
769
|
+
* Used for two distinct call sites, both passing only the steps that are
|
|
770
|
+
* actually about to run:
|
|
771
|
+
*
|
|
772
|
+
* 1. The main selected sequence, up front, before any of it runs
|
|
773
|
+
* (`runSetupManifest()`'s own preflight call, below).
|
|
774
|
+
* 2. A *specific* recovery procedure's own steps, called again at the
|
|
775
|
+
* moment a failed step selects it — completely, before that
|
|
776
|
+
* recovery's first step runs (go/no-go review blocker 3).
|
|
777
|
+
*
|
|
778
|
+
* This function never itself follows a step's `on_fail` into another
|
|
779
|
+
* recovery procedure, in either case — go/no-go review blocker 3's
|
|
780
|
+
* "preflight is too eager" finding: the previous version always recursed
|
|
781
|
+
* into every selected step's `on_fail` recovery during the main, up-front
|
|
782
|
+
* preflight, which (a) refused a manifest whose main sequence would
|
|
783
|
+
* succeed outright, solely because its *unused* recovery contained an
|
|
784
|
+
* unsupported step, and (b) had no cycle protection, so a recovery whose
|
|
785
|
+
* own steps' `on_fail` pointed back into a recovery already being
|
|
786
|
+
* preflighted recursed without bound (`RangeError: Maximum call stack
|
|
787
|
+
* size exceeded`, reproduced by the review). Not recursing into `on_fail`
|
|
788
|
+
* here also matches what execution itself does: a failing step triggers
|
|
789
|
+
* its *one* named recovery exactly once; a failing step *within* that
|
|
790
|
+
* recovery reports failure directly rather than following a further
|
|
791
|
+
* `on_fail` — so preflight never needs to follow one either. (A
|
|
792
|
+
* recovery-to-recovery `on_fail` reference cycle in the manifest itself is
|
|
793
|
+
* still caught — as a graph check over `manifest.spec.recovery[]`, not a
|
|
794
|
+
* recursive preflight — by `detectRecoveryReferenceCycles()` during
|
|
795
|
+
* manifest validation.)
|
|
796
|
+
*
|
|
797
|
+
* - `interactive: true` without a terminal AND without every declared
|
|
798
|
+
* `params` entry resolved: with every declared param supplied, the
|
|
799
|
+
* step runs headless instead (review item 10; second review finding
|
|
800
|
+
* 5b — the step itself is trusted not to need to prompt once its
|
|
801
|
+
* declared inputs are present). With no declared params at all
|
|
802
|
+
* ("undeclared interaction" — the step's questions cannot be
|
|
803
|
+
* enumerated or supplied via `--param`) this always requires a
|
|
804
|
+
* terminal.
|
|
805
|
+
* - `type: ask` with no declared `params`: always refused — unlike
|
|
806
|
+
* `interactive: true`, this CLI itself owns the prompting for `ask`
|
|
807
|
+
* steps (there is no separate script to hand a terminal to), and
|
|
808
|
+
* with nothing declared there is no destination to store an answer
|
|
809
|
+
* in. This is one of the two agreed, permanent exceptions (the other
|
|
810
|
+
* is the contributor sync-upstream strategy choice).
|
|
811
|
+
* - `type: ask` with declared params not all resolved, and no
|
|
812
|
+
* terminal: refused, naming the missing names so `--param` can
|
|
813
|
+
* supply them. With a terminal, this is *not* a blocker — the
|
|
814
|
+
* missing ones are prompted for when the step actually runs (second
|
|
815
|
+
* review finding 5b).
|
|
816
|
+
* - `type: agentic`/`type: chain`: `runStep()` refuses both
|
|
817
|
+
* unconditionally; preflighted the same way so an earlier, unrelated
|
|
818
|
+
* step is never executed ahead of this unconditional refusal (second
|
|
819
|
+
* review finding 7).
|
|
820
|
+
*/
|
|
821
|
+
function collectPreflightBlockers(steps, manifest, targetOs, params, terminalPresent) {
|
|
822
|
+
const blockers = [];
|
|
823
|
+
for (const step of steps) {
|
|
824
|
+
if (!stepPlatformMatches(targetOs, step))
|
|
825
|
+
continue;
|
|
826
|
+
if (step.interactive) {
|
|
827
|
+
const names = askStepParams(step);
|
|
828
|
+
const missing = missingAskParams(step, params);
|
|
829
|
+
const fullySupplied = names.length > 0 && missing.length === 0;
|
|
830
|
+
if (!fullySupplied && !terminalPresent) {
|
|
831
|
+
blockers.push(names.length === 0
|
|
832
|
+
? `step '${step.id}' is marked interactive (its prompts cannot be enumerated or supplied via --param) and requires a terminal`
|
|
833
|
+
: `step '${step.id}' is marked interactive and is missing required param(s): ${missing.join(', ')} (supply with --param <name>=<value>, or run with a terminal attached)`);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (step.type === 'ask') {
|
|
837
|
+
const names = askStepParams(step);
|
|
838
|
+
if (names.length === 0) {
|
|
839
|
+
blockers.push(`ask step '${step.id}' declares no params to resolve via --param; interactive capture for ask ` +
|
|
840
|
+
"steps is not implemented — declare 'params' on the step and supply them with --param <name>=<value>");
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
const missing = missingAskParams(step, params);
|
|
844
|
+
if (missing.length > 0 && !terminalPresent) {
|
|
845
|
+
blockers.push(`ask step '${step.id}' is missing required param(s): ${missing.join(', ')} (supply with --param ` +
|
|
846
|
+
'<name>=<value>, or run with a terminal attached to be prompted for them)');
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
if (step.type === 'agentic' || step.type === 'chain') {
|
|
851
|
+
blockers.push(`${step.type} step '${step.id}' is not supported by deterministic CLI execution and is always refused`);
|
|
852
|
+
}
|
|
853
|
+
if (step.type === 'platform-route') {
|
|
854
|
+
const route = step.routes?.find((item) => item.platform === targetOs);
|
|
855
|
+
if (route)
|
|
856
|
+
blockers.push(...collectPreflightBlockers(route.steps, manifest, targetOs, params, terminalPresent));
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
return blockers;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Preflight a *specific* recovery procedure's own steps — go/no-go review
|
|
863
|
+
* blocker 3. Called at the moment a failed step selects it, completely,
|
|
864
|
+
* before any of its steps run. Returns `undefined` when the recovery id
|
|
865
|
+
* does not resolve to a known procedure (the schema/consistency check
|
|
866
|
+
* already reports that as a manifest error; this function's caller treats
|
|
867
|
+
* an unresolved id as "no recovery available", same as before).
|
|
868
|
+
*/
|
|
869
|
+
function findRecoveryProcedure(manifest, recoveryId) {
|
|
870
|
+
return manifest.spec.recovery?.find((item) => item.id === recoveryId);
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Prompt interactively for each of `missingNames`, one per declared `ask`-
|
|
874
|
+
* step param still unresolved (#3062 second review, finding 5b: declared
|
|
875
|
+
* ask inputs missing AT a terminal are prompted for, not refused — this
|
|
876
|
+
* is reachable only when `isInteractive()` is true, so it is always safe
|
|
877
|
+
* to open a prompt interface here).
|
|
878
|
+
*/
|
|
879
|
+
async function promptForAskStep(step, missingNames) {
|
|
880
|
+
const rl = createPromptInterface();
|
|
881
|
+
const answers = {};
|
|
882
|
+
try {
|
|
883
|
+
if (step.message)
|
|
884
|
+
console.log(`[setup] ${step.message}`);
|
|
885
|
+
for (const name of missingNames) {
|
|
886
|
+
const answer = await askString(rl, ` ${name}: `, '', undefined);
|
|
887
|
+
if (answer)
|
|
888
|
+
answers[name] = answer;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
finally {
|
|
892
|
+
rl.close();
|
|
893
|
+
}
|
|
894
|
+
return answers;
|
|
895
|
+
}
|
|
896
|
+
async function runStep(step, manifest, manifestDir, params, targetOs, confirmed, recovery = false) {
|
|
623
897
|
if (!stepPlatformMatches(targetOs, step))
|
|
624
898
|
return { ok: true, status: 0 };
|
|
899
|
+
// A step marked `interactive: true` (#3062) declares that it prompts
|
|
900
|
+
// directly. For a top-level selected step this condition is already
|
|
901
|
+
// preflighted before any step runs (review item 13; second review
|
|
902
|
+
// finding 7); this remains the only gate for a recovery step, which
|
|
903
|
+
// isn't known until a step actually fails. With every declared `params`
|
|
904
|
+
// entry resolved, the step is trusted not to need to prompt and runs
|
|
905
|
+
// headless below like any other step (second review finding 5b — the
|
|
906
|
+
// bug this fixes: it used to be refused here even when fully supplied).
|
|
907
|
+
// With no declared params at all ("undeclared interaction") or some
|
|
908
|
+
// still missing, a terminal is required.
|
|
909
|
+
if (step.interactive) {
|
|
910
|
+
const names = askStepParams(step);
|
|
911
|
+
const missing = missingAskParams(step, params);
|
|
912
|
+
const fullySupplied = names.length > 0 && missing.length === 0;
|
|
913
|
+
if (!fullySupplied && !isInteractive()) {
|
|
914
|
+
console.error(names.length === 0
|
|
915
|
+
? `setup-run: step '${step.id}' is marked interactive (its prompts cannot be enumerated or supplied ` +
|
|
916
|
+
'via --param) and requires a terminal; re-run from an interactive shell.'
|
|
917
|
+
: `setup-run: step '${step.id}' is marked interactive and is missing required param(s): ` +
|
|
918
|
+
`${missing.join(', ')}; supply with --param <name>=<value>, or re-run from an interactive shell.`);
|
|
919
|
+
return { ok: false, status: 2, failedStep: step.id };
|
|
920
|
+
}
|
|
921
|
+
}
|
|
625
922
|
const env = { ...process.env, ...params };
|
|
626
923
|
console.log(`[setup] Step ${step.id} (${step.type})`);
|
|
627
924
|
if (step.type === 'script') {
|
|
@@ -634,8 +931,19 @@ function runStep(step, manifest, manifestDir, params, targetOs, confirmed, recov
|
|
|
634
931
|
console.error(`setup-run: refusing destructive step '${step.id}' without --yes/--confirm`);
|
|
635
932
|
return { ok: false, status: 2, failedStep: step.id };
|
|
636
933
|
}
|
|
637
|
-
|
|
638
|
-
|
|
934
|
+
// Without a terminal, a script that tries to prompt must fail fast
|
|
935
|
+
// instead of hanging forever: bounded (long tier, stdin ignored). With
|
|
936
|
+
// a terminal, unchanged (#3062).
|
|
937
|
+
const result = isInteractive()
|
|
938
|
+
// sync-spawn: interactive manifest-script-step — runs an arbitrary
|
|
939
|
+
// manifest-author-defined script file with inherited stdio; it may
|
|
940
|
+
// itself prompt (see tools/testing/sync-spawn-allowlist.json). Reached
|
|
941
|
+
// only when isInteractive() is true (#3062) — the no-terminal path
|
|
942
|
+
// uses the bounded helper instead. Not a candidate for a bounded
|
|
943
|
+
// timeout.
|
|
944
|
+
? spawnSync(scriptPath, [], { cwd: manifestDir, env, stdio: 'inherit' })
|
|
945
|
+
: boundedSpawnSync(scriptPath, [], 'long', { cwd: manifestDir, env, stdio: ['ignore', 'inherit', 'inherit'] });
|
|
946
|
+
const ran = commandResult(result);
|
|
639
947
|
if (!ran.ok)
|
|
640
948
|
return { ...ran, failedStep: step.id };
|
|
641
949
|
const verifies = Array.isArray(step.verify) ? step.verify : step.verify ? [step.verify] : [];
|
|
@@ -677,13 +985,51 @@ function runStep(step, manifest, manifestDir, params, targetOs, confirmed, recov
|
|
|
677
985
|
return { ok: false, status: 2, failedStep: step.id };
|
|
678
986
|
}
|
|
679
987
|
if (step.type === 'ask') {
|
|
680
|
-
|
|
681
|
-
|
|
988
|
+
// #3062 review item 10: a top-level selected step with all its declared
|
|
989
|
+
// params already resolved is already caught as *not* blocking by
|
|
990
|
+
// `collectPreflightBlockers` and runs headless here; this remains the
|
|
991
|
+
// gate for a recovery-path `ask` step, which isn't preflighted.
|
|
992
|
+
const names = askStepParams(step);
|
|
993
|
+
if (names.length === 0) {
|
|
994
|
+
// Agreed, permanent exception (second review finding 5b): this CLI
|
|
995
|
+
// owns the prompting for `ask` steps directly (there is no separate
|
|
996
|
+
// script to hand a terminal to), and with nothing declared there is
|
|
997
|
+
// no destination to store an answer in — always refused, with or
|
|
998
|
+
// without a terminal.
|
|
999
|
+
console.error(`setup-run: ask step '${step.id}' declares no params to resolve via --param; interactive capture ` +
|
|
1000
|
+
"for ask steps is not implemented — declare 'params' on the step and supply them with --param " +
|
|
1001
|
+
'<name>=<value>.');
|
|
1002
|
+
return { ok: false, status: 2, failedStep: step.id };
|
|
1003
|
+
}
|
|
1004
|
+
const missing = missingAskParams(step, params);
|
|
1005
|
+
if (missing.length === 0) {
|
|
1006
|
+
console.log(` ask: ${step.message ?? step.id} -> answered via --param (${names.join(', ')})`);
|
|
1007
|
+
return { ok: true, status: 0 };
|
|
1008
|
+
}
|
|
1009
|
+
if (!isInteractive()) {
|
|
1010
|
+
console.error(`setup-run: ask step '${step.id}' is missing required param(s): ${missing.join(', ')}; supply with ` +
|
|
1011
|
+
'--param <name>=<value>, or re-run from an interactive shell to be prompted for them.');
|
|
1012
|
+
return { ok: false, status: 2, failedStep: step.id };
|
|
1013
|
+
}
|
|
1014
|
+
// #3062 second review, finding 5b: declared ask inputs missing AT a
|
|
1015
|
+
// terminal are prompted for, not refused.
|
|
1016
|
+
const answers = await promptForAskStep(step, missing);
|
|
1017
|
+
const stillMissing = missing.filter((name) => !answers[name]);
|
|
1018
|
+
if (stillMissing.length > 0) {
|
|
1019
|
+
console.error(`setup-run: ask step '${step.id}' did not receive a value for: ${stillMissing.join(', ')}.`);
|
|
1020
|
+
return { ok: false, status: 2, failedStep: step.id };
|
|
1021
|
+
}
|
|
1022
|
+
// Merged into the same object reference the caller's loop (and every
|
|
1023
|
+
// later step) reads from, so a later step sees the interactively-
|
|
1024
|
+
// captured answer exactly like a `--param`-supplied one.
|
|
1025
|
+
Object.assign(params, answers);
|
|
1026
|
+
console.log(` ask: ${step.message ?? step.id} -> answered interactively (${missing.join(', ')})`);
|
|
1027
|
+
return { ok: true, status: 0 };
|
|
682
1028
|
}
|
|
683
1029
|
if (step.type === 'platform-route') {
|
|
684
1030
|
const route = step.routes?.find((item) => item.platform === targetOs);
|
|
685
1031
|
for (const nested of route?.steps ?? []) {
|
|
686
|
-
const result = runStep(nested, manifest, manifestDir, params, targetOs, confirmed);
|
|
1032
|
+
const result = await runStep(nested, manifest, manifestDir, params, targetOs, confirmed);
|
|
687
1033
|
if (!result.ok)
|
|
688
1034
|
return result;
|
|
689
1035
|
}
|
|
@@ -691,7 +1037,7 @@ function runStep(step, manifest, manifestDir, params, targetOs, confirmed, recov
|
|
|
691
1037
|
}
|
|
692
1038
|
return { ok: true, status: 0 };
|
|
693
1039
|
}
|
|
694
|
-
export function runSetupManifest(options) {
|
|
1040
|
+
export async function runSetupManifest(options) {
|
|
695
1041
|
const validation = validateSetupManifest({
|
|
696
1042
|
cwd: options.cwd,
|
|
697
1043
|
frameworkRoot: options.frameworkRoot,
|
|
@@ -735,15 +1081,44 @@ export function runSetupManifest(options) {
|
|
|
735
1081
|
if (!options.yes) {
|
|
736
1082
|
return { exitCode: 2, message: 'setup-run: mutating execution requires --yes or --confirm after reviewing the plan with --dry-run' };
|
|
737
1083
|
}
|
|
1084
|
+
// #3062 review item 13: preflight every selected step (recursively into
|
|
1085
|
+
// `platform-route` nesting) before executing any of them — the previous
|
|
1086
|
+
// behavior checked `interactive`/`ask` conditions inside the per-step
|
|
1087
|
+
// loop below, so an earlier normal step could already perform work
|
|
1088
|
+
// before a later step's refusal fired.
|
|
1089
|
+
const blockers = collectPreflightBlockers(steps, manifest, target.os, params.values, isInteractive());
|
|
1090
|
+
if (blockers.length > 0) {
|
|
1091
|
+
for (const blocker of blockers)
|
|
1092
|
+
console.error(`setup-run: ${blocker}.`);
|
|
1093
|
+
return {
|
|
1094
|
+
exitCode: 2,
|
|
1095
|
+
message: `setup-run: refusing before executing any step:\n${blockers.map((b) => ` - ${b}`).join('\n')}`,
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
738
1098
|
for (const step of steps) {
|
|
739
|
-
const result = runStep(step, manifest, validation.manifestDir, params.values, target.os, options.yes);
|
|
1099
|
+
const result = await runStep(step, manifest, validation.manifestDir, params.values, target.os, options.yes);
|
|
740
1100
|
if (!result.ok) {
|
|
741
1101
|
if (result.failedStep && step.on_fail) {
|
|
742
|
-
const recovery = manifest
|
|
1102
|
+
const recovery = findRecoveryProcedure(manifest, step.on_fail);
|
|
743
1103
|
if (recovery) {
|
|
1104
|
+
// Go/no-go review blocker 3: preflight the *selected* recovery's
|
|
1105
|
+
// own steps completely, now that a failure has actually chosen
|
|
1106
|
+
// it — not when the manifest was first loaded (that preflighted
|
|
1107
|
+
// the main sequence only, above) — and before any of its steps
|
|
1108
|
+
// run. Refuses with zero recovery steps executed, same
|
|
1109
|
+
// all-blockers-at-once shape as the main-sequence preflight.
|
|
1110
|
+
const recoveryBlockers = collectPreflightBlockers(recovery.steps, manifest, target.os, params.values, isInteractive());
|
|
1111
|
+
if (recoveryBlockers.length > 0) {
|
|
1112
|
+
for (const blocker of recoveryBlockers)
|
|
1113
|
+
console.error(`setup-run: [recovery '${recovery.id}'] ${blocker}.`);
|
|
1114
|
+
return {
|
|
1115
|
+
exitCode: 2,
|
|
1116
|
+
message: `setup-run: recovery '${recovery.id}' (for failed step '${result.failedStep}') refusing before executing any recovery step:\n${recoveryBlockers.map((b) => ` - ${b}`).join('\n')}`,
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
744
1119
|
console.error(`[setup] recovery '${recovery.id}' available for failed step '${result.failedStep}'`);
|
|
745
1120
|
for (const recoveryStep of recovery.steps) {
|
|
746
|
-
const recoveryResult = runStep(recoveryStep, manifest, validation.manifestDir, params.values, target.os, options.yes, true);
|
|
1121
|
+
const recoveryResult = await runStep(recoveryStep, manifest, validation.manifestDir, params.values, target.os, options.yes, true);
|
|
747
1122
|
if (!recoveryResult.ok)
|
|
748
1123
|
return { exitCode: recoveryResult.status || 1, message: `setup-run: recovery '${recovery.id}' failed` };
|
|
749
1124
|
}
|
|
@@ -771,11 +1146,22 @@ export const setupValidateHandler = {
|
|
|
771
1146
|
return { exitCode: 0 };
|
|
772
1147
|
}
|
|
773
1148
|
const strict = hasFlag(ctx.args, '--strict');
|
|
1149
|
+
let manifestPath;
|
|
1150
|
+
let schemaPath;
|
|
1151
|
+
try {
|
|
1152
|
+
manifestPath = flagValue(ctx.args, '--manifest') ?? positionalManifest(ctx.args);
|
|
1153
|
+
schemaPath = flagValue(ctx.args, '--schema');
|
|
1154
|
+
}
|
|
1155
|
+
catch (err) {
|
|
1156
|
+
if (err instanceof MissingFlagValueError)
|
|
1157
|
+
return { exitCode: 2, message: `${err.message}.` };
|
|
1158
|
+
throw err;
|
|
1159
|
+
}
|
|
774
1160
|
const result = validateSetupManifest({
|
|
775
1161
|
cwd: ctx.cwd,
|
|
776
1162
|
frameworkRoot: ctx.frameworkRoot,
|
|
777
|
-
manifestPath
|
|
778
|
-
schemaPath
|
|
1163
|
+
manifestPath,
|
|
1164
|
+
schemaPath,
|
|
779
1165
|
strict,
|
|
780
1166
|
});
|
|
781
1167
|
const payload = {
|
|
@@ -807,8 +1193,9 @@ export const setupGenerateHandler = {
|
|
|
807
1193
|
}
|
|
808
1194
|
catch (error) {
|
|
809
1195
|
return {
|
|
810
|
-
|
|
811
|
-
|
|
1196
|
+
// #3062 review item 11: a missing flag value is a usage error.
|
|
1197
|
+
exitCode: error instanceof MissingFlagValueError ? 2 : 1,
|
|
1198
|
+
message: error instanceof Error ? `${error.message}.` : String(error),
|
|
812
1199
|
};
|
|
813
1200
|
}
|
|
814
1201
|
},
|
|
@@ -824,21 +1211,34 @@ export const setupRunHandler = {
|
|
|
824
1211
|
process.stdout.write(RUN_HELP);
|
|
825
1212
|
return { exitCode: 0 };
|
|
826
1213
|
}
|
|
827
|
-
|
|
828
|
-
|
|
1214
|
+
let options;
|
|
1215
|
+
let policyFlag;
|
|
1216
|
+
let verificationArgs = [];
|
|
1217
|
+
try {
|
|
1218
|
+
options = parseRunOptions(ctx);
|
|
1219
|
+
policyFlag = flagValue(ctx.args, '--policy');
|
|
1220
|
+
if (policyFlag) {
|
|
1221
|
+
const manifestPathForVerification = options.manifestPath ?? 'setup.manifest.yaml';
|
|
1222
|
+
verificationArgs = [
|
|
1223
|
+
manifestPathForVerification,
|
|
1224
|
+
'--attestation', flagValue(ctx.args, '--attestation') ?? `${manifestPathForVerification}.aiwg-attestation.json`,
|
|
1225
|
+
'--policy', policyFlag,
|
|
1226
|
+
'--asset-type', flagValue(ctx.args, '--asset-type') ?? 'setup-manifest',
|
|
1227
|
+
'--namespace', flagValue(ctx.args, '--namespace') ?? 'aiwg',
|
|
1228
|
+
'--channel', flagValue(ctx.args, '--channel') ?? 'stable',
|
|
1229
|
+
'--json',
|
|
1230
|
+
...(flagValue(ctx.args, '--state') ? ['--state', flagValue(ctx.args, '--state')] : []),
|
|
1231
|
+
...(hasFlag(ctx.args, '--offline') ? ['--offline'] : []),
|
|
1232
|
+
];
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
catch (err) {
|
|
1236
|
+
if (err instanceof MissingFlagValueError)
|
|
1237
|
+
return { exitCode: 2, message: `setup-run: ${err.message}.` };
|
|
1238
|
+
throw err;
|
|
1239
|
+
}
|
|
829
1240
|
let artifactVerification;
|
|
830
|
-
if (
|
|
831
|
-
const verificationArgs = [
|
|
832
|
-
manifestPath,
|
|
833
|
-
'--attestation', flagValue(ctx.args, '--attestation') ?? `${manifestPath}.aiwg-attestation.json`,
|
|
834
|
-
'--policy', flagValue(ctx.args, '--policy'),
|
|
835
|
-
'--asset-type', flagValue(ctx.args, '--asset-type') ?? 'setup-manifest',
|
|
836
|
-
'--namespace', flagValue(ctx.args, '--namespace') ?? 'aiwg',
|
|
837
|
-
'--channel', flagValue(ctx.args, '--channel') ?? 'stable',
|
|
838
|
-
'--json',
|
|
839
|
-
...(flagValue(ctx.args, '--state') ? ['--state', flagValue(ctx.args, '--state')] : []),
|
|
840
|
-
...(hasFlag(ctx.args, '--offline') ? ['--offline'] : []),
|
|
841
|
-
];
|
|
1241
|
+
if (policyFlag) {
|
|
842
1242
|
const verification = await artifactVerifyHandler.execute({ ...ctx, args: verificationArgs, rawArgs: verificationArgs });
|
|
843
1243
|
try {
|
|
844
1244
|
artifactVerification = JSON.parse(verification.message ?? '');
|