@aiwg/cli 2026.10.1 → 2026.10.4
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/README.md +2 -2
- package/agentic/code/providers/capability-matrix.yaml +270 -0
- package/agentic/code/providers/model-capabilities.v1.json +3183 -24
- package/bin/aiwg.mjs +135 -47
- package/dist/src/a2a/codecs.js +9 -0
- package/dist/src/agents/grounding/knowledge-base.js +54 -6
- package/dist/src/artifacts/browser-export.js +6 -0
- package/dist/src/artifacts/checksum-manifest.js +1 -0
- package/dist/src/artifacts/citation-parser.js +173 -92
- package/dist/src/artifacts/citation-table-schema.js +59 -0
- package/dist/src/artifacts/cli.js +57 -18
- package/dist/src/artifacts/corpus-tools/snapshot.js +1 -1
- package/dist/src/artifacts/corpus-tools/vision-extract.js +107 -15
- package/dist/src/artifacts/corpus-views/ref-parser.js +3 -1
- package/dist/src/artifacts/corpus-views/renderers.js +3 -3
- package/dist/src/artifacts/discovery-eval.js +6 -4
- package/dist/src/artifacts/fortemi-core-query-adapter.js +36 -3
- package/dist/src/artifacts/fortemi-core-sync.js +166 -40
- package/dist/src/artifacts/framework-capabilities.js +171 -0
- package/dist/src/artifacts/framework-index-paths.js +73 -0
- package/dist/src/artifacts/framework-source-digest.js +75 -0
- package/dist/src/artifacts/index-builder.js +285 -131
- package/dist/src/artifacts/index-files.js +132 -18
- package/dist/src/artifacts/index-preparation.js +65 -0
- package/dist/src/artifacts/index-refresh.js +576 -0
- package/dist/src/artifacts/index-worker.mjs +9 -0
- package/dist/src/artifacts/prebuilt-build-lock.js +47 -4
- package/dist/src/artifacts/prebuilt-deployment.js +46 -0
- package/dist/src/artifacts/prebuilt-relations.js +80 -0
- package/dist/src/artifacts/query-engine.js +410 -88
- package/dist/src/artifacts/relations-builder.js +168 -0
- package/dist/src/artifacts/relations.js +148 -0
- package/dist/src/artifacts/repair.js +9 -4
- package/dist/src/artifacts/stats.js +5 -2
- package/dist/src/artifacts/types.js +30 -10
- package/dist/src/artifacts/watcher.js +1 -1
- package/dist/src/auth/credential-store.js +2 -1
- package/dist/src/catalog/cli.d.mts +5 -0
- package/dist/src/channel/manager.d.mts +20 -0
- package/dist/src/channel/manager.mjs +78 -12
- package/dist/src/cli/child-process-result.js +40 -0
- package/dist/src/cli/command-log.js +2 -3
- package/dist/src/cli/env.js +38 -16
- package/dist/src/cli/flag-parsing.js +236 -0
- package/dist/src/cli/handlers/artifacts.js +3 -0
- package/dist/src/cli/handlers/auth.js +3 -0
- package/dist/src/cli/handlers/decision.js +218 -5
- package/dist/src/cli/handlers/diagnose.js +13 -5
- package/dist/src/cli/handlers/effect.js +4 -2
- package/dist/src/cli/handlers/evidence.js +3 -0
- package/dist/src/cli/handlers/feedback.js +14 -5
- package/dist/src/cli/handlers/help.js +1 -0
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/init.js +248 -30
- package/dist/src/cli/handlers/lint.js +5 -0
- package/dist/src/cli/handlers/mc.js +23 -0
- package/dist/src/cli/handlers/models.js +169 -10
- package/dist/src/cli/handlers/ralph-launcher.js +2 -0
- package/dist/src/cli/handlers/ralph.js +3 -0
- package/dist/src/cli/handlers/refresh.js +28 -0
- package/dist/src/cli/handlers/regenerate.js +14 -0
- package/dist/src/cli/handlers/resource-versions.js +3 -0
- package/dist/src/cli/handlers/rules.js +195 -0
- package/dist/src/cli/handlers/run.js +4 -0
- package/dist/src/cli/handlers/runtime-info.js +25 -11
- package/dist/src/cli/handlers/script-runner.js +19 -8
- package/dist/src/cli/handlers/session.js +406 -62
- package/dist/src/cli/handlers/sessions.js +243 -76
- package/dist/src/cli/handlers/setup-manifest.js +474 -79
- package/dist/src/cli/handlers/setup.js +180 -39
- package/dist/src/cli/handlers/steward.js +11 -0
- package/dist/src/cli/handlers/subcommands.js +60 -3
- package/dist/src/cli/handlers/team.js +18 -8
- package/dist/src/cli/handlers/uhp.js +3 -0
- package/dist/src/cli/handlers/use.js +307 -55
- package/dist/src/cli/handlers/utilities.js +125 -26
- package/dist/src/cli/handlers/version.js +8 -0
- package/dist/src/cli/prompt-utils.js +72 -0
- package/dist/src/cli/provider-resolution.js +11 -0
- package/dist/src/cli/router.js +15 -1
- package/dist/src/cli/services/deployment-verification.js +19 -9
- package/dist/src/cli/services/provider-prepare-coordinator.js +24 -0
- package/dist/src/cli/skill-usage.js +2 -3
- package/dist/src/config/aiwg-config.js +349 -35
- package/dist/src/config/cli.js +256 -23
- package/dist/src/config/decision-config.js +106 -0
- package/dist/src/config/dispatch-thresholds-runtime.d.mts +8 -0
- package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
- package/dist/src/config/gitignore.js +50 -0
- package/dist/src/config/index-graph-overrides.js +36 -0
- package/dist/src/config/project-artifacts-health.d.mts +37 -0
- package/dist/src/config/project-artifacts-health.mjs +14 -3
- package/dist/src/config/project-artifacts-runtime.d.mts +16 -0
- package/dist/src/config/user-config-dir.d.mts +9 -0
- package/dist/src/config/user-config.js +38 -11
- package/dist/src/config/user-registry.js +23 -15
- package/dist/src/config/user-state.js +7 -0
- package/dist/src/decision/adapters/jev.js +75 -27
- package/dist/src/decision/ask.js +203 -43
- package/dist/src/decision/context-live-qualification.js +2 -2
- package/dist/src/decision/driver.js +14 -7
- package/dist/src/decision/ensemble/aggregate.js +23 -10
- package/dist/src/decision/ensemble-study/multifact-study.js +6 -2
- package/dist/src/decision/entry.js +25 -6
- package/dist/src/decision/graph-live-qualification.js +1 -1
- package/dist/src/decision/graph-run.js +9 -0
- package/dist/src/decision/heldout/collector.js +15 -14
- package/dist/src/decision/heldout/contract.js +30 -7
- package/dist/src/decision/index.js +1 -0
- package/dist/src/decision/interop.js +60 -8
- package/dist/src/decision/jev-credentials.js +15 -1
- package/dist/src/decision/ledger.js +942 -0
- package/dist/src/decision/offload-activation.js +137 -0
- package/dist/src/decision/offload.js +550 -0
- package/dist/src/decision/qualification/load.js +4 -6
- package/dist/src/decision/savings.js +28 -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/effects/types.js +5 -1
- package/dist/src/effects/verifiers/git.js +2 -1
- package/dist/src/effects/verifiers/tracker.js +26 -14
- package/dist/src/extensions/commands/definitions.js +19 -0
- package/dist/src/extensions/project-local-remove.js +36 -1
- package/dist/src/features/installer.js +2 -2
- package/dist/src/flow/graph-metadata.js +5 -0
- package/dist/src/gates/providers/loader.js +64 -18
- package/dist/src/installation/manager-command.d.mts +18 -0
- package/dist/src/installation/manager-command.mjs +15 -3
- package/dist/src/installation/manager.d.mts +49 -0
- package/dist/src/installation/manager.mjs +95 -5
- package/dist/src/issues/cli.js +4 -4
- package/dist/src/issues/local.js +24 -5
- package/dist/src/jobs/runner.js +1 -1
- package/dist/src/lint/cli.js +27 -1
- package/dist/src/lint/loader.js +2 -1
- package/dist/src/lint/reporters.js +25 -1
- package/dist/src/lint/rule-activation.js +43 -0
- package/dist/src/lint/runner.js +137 -62
- package/dist/src/mcp/adapters/codex-runtime.js +366 -56
- package/dist/src/mcp/claude-install.d.mts +4 -0
- package/dist/src/mcp/claude-install.mjs +41 -0
- package/dist/src/mcp/cli.d.mts +1 -0
- package/dist/src/mcp/cli.mjs +620 -85
- package/dist/src/mcp/config-file.d.mts +28 -0
- package/dist/src/mcp/config-file.mjs +279 -0
- package/dist/src/mcp/config-layers.d.mts +36 -0
- package/dist/src/mcp/config-layers.mjs +348 -0
- package/dist/src/mcp/credentials.d.mts +51 -0
- package/dist/src/mcp/credentials.mjs +484 -0
- package/dist/src/mcp/grok-build-config.d.mts +6 -0
- package/dist/src/mcp/grok-build-config.mjs +17 -27
- package/dist/src/mcp/helpers.mjs +109 -4
- package/dist/src/mcp/muse-native-config.d.mts +13 -0
- package/dist/src/mcp/muse-native-config.mjs +1 -0
- package/dist/src/mcp/omp-config.d.mts +4 -0
- 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 +248 -131
- package/dist/src/mcp/registry.mjs +169 -100
- package/dist/src/mcp/server-config.d.mts +3 -0
- package/dist/src/mcp/server-config.mjs +89 -0
- package/dist/src/mcp/server.mjs +127 -82
- package/dist/src/mcp/test-simple.mjs +2 -1
- package/dist/src/mcp/toml-editor.d.mts +4 -0
- package/dist/src/mcp/toml-string.d.mts +1 -0
- package/dist/src/mcp/toml-string.mjs +9 -0
- package/dist/src/mcp/toml-strip-mcp.d.mts +1 -0
- package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
- package/dist/src/mcp/tool-filters.d.mts +46 -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 +22 -3
- package/dist/src/mcp/tools/discovery.mjs +62 -55
- package/dist/src/mcp/tools/orchestration.mjs +50 -2
- package/dist/src/mcp/tools/subsystems.mjs +39 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +2856 -0
- package/dist/src/mcp/tools/worker-shell-control.mjs +289 -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 +647 -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 +76 -14
- package/dist/src/models/grok-build-models.js +93 -41
- package/dist/src/models/model-capabilities.v1.json +3183 -24
- package/dist/src/models/model-discovery.js +931 -67
- package/dist/src/models/provider-policy.js +719 -11
- package/dist/src/models/qualification-digest.d.mts +2 -0
- package/dist/src/models/qualification-digest.mjs +17 -0
- package/dist/src/models/resolver.js +261 -0
- package/dist/src/models/worker-direct-readiness.js +550 -0
- package/dist/src/models/worker-dispatch-offer.js +169 -0
- package/dist/src/models/worker-health-readiness.js +144 -0
- package/dist/src/models/worker-installation.d.mts +39 -0
- package/dist/src/models/worker-installation.mjs +986 -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.d.mts +84 -0
- package/dist/src/process/bounded-child-process.mjs +430 -0
- package/dist/src/process/cli-command.d.mts +16 -0
- package/dist/src/process/cli-command.mjs +75 -0
- package/dist/src/process/signal-child.d.mts +6 -0
- package/dist/src/process/signal-child.mjs +7 -0
- package/dist/src/providers/capability-matrix.js +8 -0
- package/dist/src/providers/capability-matrix.yaml +270 -0
- package/dist/src/providers/deployed-skill-roots.js +20 -0
- package/dist/src/providers/grok-build-acp.js +3 -2
- package/dist/src/providers/grok-build-headless.js +53 -23
- package/dist/src/providers/grok-build-inspect.js +1 -0
- package/dist/src/providers/omp-agent.d.mts +8 -0
- package/dist/src/providers/omp-diagnostics.d.mts +1 -0
- package/dist/src/providers/omp-paths.d.mts +13 -0
- package/dist/src/providers/provider-definitions.js +9 -1
- package/dist/src/providers/provider-definitions.mjs +9 -2
- package/dist/src/providers/skill-ownership.d.mts +9 -0
- package/dist/src/providers/skill-ownership.mjs +88 -0
- package/dist/src/rules/activation.d.mts +21 -0
- package/dist/src/rules/activation.mjs +62 -0
- package/dist/src/rules/inline-budget.d.mts +26 -0
- package/dist/src/rules/inline-budget.mjs +66 -0
- package/dist/src/rules/inventory.js +129 -0
- package/dist/src/rules/pin-state.js +73 -0
- package/dist/src/rules/pins.d.mts +14 -0
- package/dist/src/rules/pins.mjs +112 -0
- package/dist/src/rules/rule-frontmatter.schema.json +197 -0
- 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 +47 -12
- package/dist/src/serve/shared-host-scheduler.js +2 -0
- package/dist/src/serve/worker-invocation.js +558 -0
- package/dist/src/serve/worker-stdin-frame.d.mts +10 -0
- package/dist/src/serve/worker-stdin-frame.mjs +107 -0
- package/dist/src/sessions/adapter-registry.js +49 -0
- package/dist/src/sessions/adapters/claude.js +39 -54
- package/dist/src/sessions/adapters/codex.js +82 -67
- package/dist/src/sessions/adapters/copilot.js +4 -4
- package/dist/src/sessions/adapters/cursor.js +40 -57
- package/dist/src/sessions/adapters/deepseek-harness.js +15 -12
- package/dist/src/sessions/adapters/factory.js +31 -27
- package/dist/src/sessions/adapters/generic.js +43 -9
- package/dist/src/sessions/adapters/grok-build.js +11 -11
- package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
- package/dist/src/sessions/adapters/grokbot.js +434 -24
- package/dist/src/sessions/adapters/hermes.js +27 -29
- package/dist/src/sessions/adapters/muse-workspace-scan.js +128 -0
- package/dist/src/sessions/adapters/muse.js +200 -104
- package/dist/src/sessions/adapters/omp.js +28 -14
- package/dist/src/sessions/adapters/openclaw.js +89 -79
- package/dist/src/sessions/adapters/opencode.js +27 -24
- package/dist/src/sessions/adapters/openhuman.js +18 -60
- package/dist/src/sessions/adapters/pi.js +30 -14
- package/dist/src/sessions/adapters/warp.js +3 -3
- package/dist/src/sessions/adapters/windsurf.js +19 -48
- package/dist/src/sessions/batch-contracts.js +25 -5
- package/dist/src/sessions/batch-import.js +72 -51
- package/dist/src/sessions/candidates.js +47 -11
- package/dist/src/sessions/contracts.js +75 -2
- package/dist/src/sessions/coverage-preflight.js +134 -0
- package/dist/src/sessions/discovery.js +3 -0
- package/dist/src/sessions/export-plan.js +4 -3
- package/dist/src/sessions/grok-build-cli.js +67 -5
- package/dist/src/sessions/import-exclusions.js +72 -0
- package/dist/src/sessions/import-lease.js +34 -18
- package/dist/src/sessions/import-limits.js +37 -0
- package/dist/src/sessions/importer.js +84 -46
- package/dist/src/sessions/index.js +2 -0
- package/dist/src/sessions/lifecycle.js +45 -0
- package/dist/src/sessions/policy.js +133 -25
- package/dist/src/sessions/readers.js +106 -53
- package/dist/src/sessions/refresh.js +106 -0
- package/dist/src/sessions/repository.js +199 -63
- package/dist/src/sessions/workspace-discovery.js +315 -88
- package/dist/src/sessions/workspace-matching.js +107 -0
- package/dist/src/skills/adapters/clawhub.js +10 -8
- package/dist/src/skills/adapters/openclaw.js +10 -7
- package/dist/src/skills/importer.js +1 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +11 -0
- package/dist/src/smiths/context-pipeline/claude-hook.js +3 -26
- package/dist/src/smiths/context-pipeline/finalization.js +6 -5
- package/dist/src/smiths/context-pipeline/generator.js +21 -4
- package/dist/src/smiths/context-pipeline/parallelism-section.js +195 -14
- 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/mcpsmith/generator.js +1 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.d.mts +10 -0
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +85 -31
- package/dist/src/storage/backends/fs.js +18 -76
- package/dist/src/storage/backends/logseq.js +68 -7
- package/dist/src/storage/backends/obsidian.js +1 -0
- package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
- package/dist/src/testing/generators/test-code-generator.js +57 -30
- package/dist/src/tracker/forge-http.js +2 -1
- package/dist/src/uhp/client.js +11 -1
- package/dist/src/uhp/mission.js +5 -0
- package/dist/src/update/checker.d.mts +2 -0
- package/dist/src/update/checker.mjs +5 -5
- package/dist/src/update/notifier.mjs +54 -2
- package/dist/src/update/service.d.mts +22 -0
- package/dist/src/utils/contained-filesystem.d.mts +37 -0
- package/dist/src/utils/contained-filesystem.mjs +683 -0
- package/dist/src/utils/temporary-directory.js +36 -0
- package/dist/src/writing/example-generator.js +1 -1
- package/dist/src/writing/fidelity.js +18 -1
- package/package.json +32 -2
- 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 +1072 -0
- package/tools/_resolve-impl.mjs +39 -2
- package/tools/agents/deploy-agents.mjs +64 -23
- package/tools/agents/providers/base.mjs +153 -166
- package/tools/agents/providers/claude.mjs +8 -24
- package/tools/agents/providers/codex.mjs +18 -11
- package/tools/agents/providers/cursor.mjs +19 -18
- package/tools/agents/providers/grok-build.mjs +3 -1
- package/tools/agents/providers/grokbot.mjs +11 -12
- package/tools/agents/providers/hermes.mjs +62 -49
- package/tools/agents/providers/omp.mjs +5 -2
- package/tools/agents/providers/openclaw-translator.mjs +19 -5
- package/tools/agents/providers/openclaw.mjs +9 -4
- package/tools/agents/providers/pi.mjs +5 -0
- package/tools/agents/providers/provider-prepare-channel.mjs +5 -0
- package/tools/agents/providers/provider-prepare-coordinator.mjs +247 -0
- package/tools/agents/providers/provider-prepare-worker.mjs +84 -0
- package/tools/agents/providers/rule-delivery.mjs +1270 -0
- package/tools/agents/providers/warp.mjs +20 -26
- package/tools/cli/decision-offload-report.mjs +40 -0
- package/tools/cli/workspace-status.mjs +862 -0
- package/tools/plugin/package-plugins.mjs +186 -8
- package/tools/plugin/plugin-links.mjs +114 -0
- package/tools/providers/antigravity-transport.mjs +3 -1
- package/tools/providers/deepseek-harness-transport.mjs +360 -0
- package/tools/providers/omp-transport.mjs +194 -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/consecutive-failure-circuit-breaker.mjs +1748 -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/launcher-recovery-evidence.mjs +55 -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 +329 -0
- package/tools/ralph-external/lib/provider-adapter.mjs +748 -0
- package/tools/ralph-external/lib/recovery-probe.mjs +72 -0
- package/tools/ralph-external/lib/session-environment.mjs +28 -0
- package/tools/ralph-external/lib/systemd-client.mjs +49 -0
- package/tools/ralph-external/lib/worker-health.mjs +439 -0
- package/tools/ralph-external/lib/worker-isolation.mjs +717 -0
- package/tools/ralph-external/lib/worker-overflow.mjs +50 -0
- package/tools/ralph-external/process-monitor.mjs +1017 -0
- package/tools/ralph-external/session-launcher.mjs +5057 -0
- package/tools/scripts/resource-preflight.mjs +541 -0
- package/tools/skills/deploy-skills-codex.mjs +2 -1
- package/vscode-extension/schemas/aiwg.config.v1.json +2916 -0
|
@@ -1,26 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { boundedSpawnSync } from '../../process/bounded-child-process.mjs';
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { emptyConfig, FORCE_PUSH_POLICY_ALIAS_NOTE, normalizeForcePushPolicy as normalizeForcePushPolicyShared, getConfigPath, getProjectDir, readAiwgConfig, resolveRemoteProvider, VALID_PROVIDERS, writeAiwgConfig, } from '../../config/aiwg-config.js';
|
|
4
4
|
import { AiwgError, EXIT_CODES } from '../errors.js';
|
|
5
|
-
import { askChoice, askString, askYesNo, createPromptInterface } from '../prompt-utils.js';
|
|
5
|
+
import { askChoice, askConsent, askString, askYesNo, createPromptInterface } from '../prompt-utils.js';
|
|
6
6
|
import * as ui from '../ui.js';
|
|
7
7
|
import { projectAiwgPath } from '../../config/project-artifacts.js';
|
|
8
8
|
import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
|
|
9
|
+
import { isInteractive } from '../env.js';
|
|
10
|
+
import { requireFlagValue as strictFlagValue, MissingFlagValueError } from '../flag-parsing.js';
|
|
11
|
+
import { detectInstalledWorkerClis, evaluateWorkerDispatchOffer, workerDispatchOfferHintWithArg, workerDispatchOfferQuestion, WORKER_DISPATCH_ARG_VALUES, } from '../../models/worker-dispatch-offer.js';
|
|
9
12
|
const DELIVERY_MODES = ['pr-required', 'feature-branch', 'direct'];
|
|
10
13
|
const FORCE_PUSH_POLICIES = ['never', 'own-branch-only', 'allowed'];
|
|
11
14
|
const ISSUE_PROVIDERS = ['gitea', 'github', 'local'];
|
|
12
15
|
const SIGNING_FORMATS = ['openpgp', 'ssh', 'x509'];
|
|
13
16
|
const TRACKER_VIA = ['tea', 'gh', 'mcp', 'api'];
|
|
17
|
+
/**
|
|
18
|
+
* A value-taking flag present without a usable value is a usage error, not
|
|
19
|
+
* "not given" (#3062 review item 11) — delegates to the shared strict
|
|
20
|
+
* parser, translating its `MissingFlagValueError` into this file's own
|
|
21
|
+
* `AiwgError`/`EXIT_CODES.USAGE` convention. `precedence: 'first'` matches
|
|
22
|
+
* this command's own pre-#3062 behavior (a hand-rolled loop that returned
|
|
23
|
+
* on the first match) — unchanged by the shared parser's second-round fix
|
|
24
|
+
* (#3062 second review, finding 4).
|
|
25
|
+
*/
|
|
14
26
|
function flagValue(args, ...names) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
try {
|
|
28
|
+
return strictFlagValue(args, {}, ...names);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (err instanceof MissingFlagValueError) {
|
|
32
|
+
throw new AiwgError({
|
|
33
|
+
code: 'ERR_USAGE_MISSING_FLAG_VALUE',
|
|
34
|
+
message: `${err.message}.`,
|
|
35
|
+
exitCode: EXIT_CODES.USAGE,
|
|
36
|
+
});
|
|
21
37
|
}
|
|
38
|
+
throw err;
|
|
22
39
|
}
|
|
23
|
-
return undefined;
|
|
24
40
|
}
|
|
25
41
|
function boolFlag(args, name) {
|
|
26
42
|
return args.includes(name);
|
|
@@ -92,6 +108,10 @@ export function parseSetupProjectOptions(ctx) {
|
|
|
92
108
|
trackerActorVia: parseEnum(flagValue(args, '--tracker-actor-via'), TRACKER_VIA, '--tracker-actor-via'),
|
|
93
109
|
customerTrackerActorLogin: flagValue(args, '--customer-tracker-actor-login'),
|
|
94
110
|
customerTrackerActorVia: parseEnum(flagValue(args, '--customer-tracker-actor-via'), TRACKER_VIA, '--customer-tracker-actor-via'),
|
|
111
|
+
// #3062: answers the worker-dispatch question directly, with or without
|
|
112
|
+
// a terminal, and suppresses the interactive question below (see
|
|
113
|
+
// `SetupProjectOptions.workerDispatchChoice`'s doc comment).
|
|
114
|
+
workerDispatchChoice: parseEnum(flagValue(args, '--worker-dispatch'), WORKER_DISPATCH_ARG_VALUES, '--worker-dispatch'),
|
|
95
115
|
providers: (() => {
|
|
96
116
|
const providers = parseStringList(flagValue(args, '--providers'));
|
|
97
117
|
return providers ? normalizeProviders(providers) : undefined;
|
|
@@ -99,7 +119,7 @@ export function parseSetupProjectOptions(ctx) {
|
|
|
99
119
|
};
|
|
100
120
|
}
|
|
101
121
|
export function detectGitRemotes(projectDir) {
|
|
102
|
-
const result =
|
|
122
|
+
const result = boundedSpawnSync('git', ['-C', projectDir, 'remote', '-v'], 'quick', {
|
|
103
123
|
encoding: 'utf-8',
|
|
104
124
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
105
125
|
});
|
|
@@ -122,21 +142,21 @@ export function detectGitRemotes(projectDir) {
|
|
|
122
142
|
return [...byName.values()];
|
|
123
143
|
}
|
|
124
144
|
function detectDefaultBranch(projectDir) {
|
|
125
|
-
const symbolic =
|
|
145
|
+
const symbolic = boundedSpawnSync('git', ['-C', projectDir, 'symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD'], 'quick', {
|
|
126
146
|
encoding: 'utf-8',
|
|
127
147
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
128
148
|
});
|
|
129
149
|
const fromOrigin = symbolic.stdout.trim().replace(/^origin\//, '');
|
|
130
150
|
if (symbolic.status === 0 && fromOrigin)
|
|
131
151
|
return fromOrigin;
|
|
132
|
-
const branch =
|
|
152
|
+
const branch = boundedSpawnSync('git', ['-C', projectDir, 'branch', '--show-current'], 'quick', {
|
|
133
153
|
encoding: 'utf-8',
|
|
134
154
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
135
155
|
});
|
|
136
156
|
return branch.stdout.trim() || 'main';
|
|
137
157
|
}
|
|
138
158
|
function gitConfig(projectDir, key) {
|
|
139
|
-
const result =
|
|
159
|
+
const result = boundedSpawnSync('git', ['-C', projectDir, 'config', '--get', key], 'quick', {
|
|
140
160
|
encoding: 'utf-8',
|
|
141
161
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
142
162
|
});
|
|
@@ -321,6 +341,19 @@ export async function buildSetupProjectPlan(options) {
|
|
|
321
341
|
}
|
|
322
342
|
base.remotes = remotesConfig;
|
|
323
343
|
base.delivery = delivery;
|
|
344
|
+
// #3050: apply an already-made worker-dispatch opt-in choice (from the
|
|
345
|
+
// interactive wizard), then recompute whether any surface should still
|
|
346
|
+
// offer/hint it — a choice just applied here always clears the offer.
|
|
347
|
+
// The decline is a setup/onboarding preference, not worker policy, so it
|
|
348
|
+
// lives in `setup`, not in the frozen `parallelism` contract fragment
|
|
349
|
+
// (B-OG-29).
|
|
350
|
+
if (options.workerDispatchChoice === 'enable') {
|
|
351
|
+
base.parallelism = { ...base.parallelism, worker_dispatch: true };
|
|
352
|
+
}
|
|
353
|
+
else if (options.workerDispatchChoice === 'decline') {
|
|
354
|
+
base.setup = { ...base.setup, worker_dispatch_offer: 'declined' };
|
|
355
|
+
}
|
|
356
|
+
const workerDispatchOffer = evaluateWorkerDispatchOffer(base.parallelism, base.setup, detectInstalledWorkerClis());
|
|
324
357
|
if (primaryRemote?.provider === 'unknown' && issueProvider !== 'local') {
|
|
325
358
|
warnings.push(`Remote '${primary}' is self-hosted or unknown; provider '${issueProvider}' was selected explicitly/defaulted.`);
|
|
326
359
|
}
|
|
@@ -347,9 +380,10 @@ export async function buildSetupProjectPlan(options) {
|
|
|
347
380
|
issueProvider,
|
|
348
381
|
warnings,
|
|
349
382
|
diff: formatPreviewDiff(existing, base),
|
|
383
|
+
workerDispatchOffer,
|
|
350
384
|
};
|
|
351
385
|
}
|
|
352
|
-
async function applyInteractivePrompts(plan, rl, signal) {
|
|
386
|
+
export async function applyInteractivePrompts(plan, rl, signal, supplied = {}) {
|
|
353
387
|
const remoteNames = plan.remotes.map(r => r.name);
|
|
354
388
|
const current = plan.next;
|
|
355
389
|
console.log('');
|
|
@@ -360,28 +394,59 @@ async function applyInteractivePrompts(plan, rl, signal) {
|
|
|
360
394
|
}
|
|
361
395
|
if (plan.remotes.length === 0)
|
|
362
396
|
console.log(' (none)');
|
|
363
|
-
|
|
397
|
+
// #3062 review item 10: a value already supplied by flag is never
|
|
398
|
+
// re-asked — only the fields `supplied` leaves `undefined` prompt here.
|
|
399
|
+
// `??`'s right-hand side is only evaluated when the left is nullish, so
|
|
400
|
+
// a supplied value skips the corresponding `ask*` call entirely.
|
|
401
|
+
const primary = supplied.primary ?? (remoteNames.length > 0
|
|
364
402
|
? await askChoice(rl, `Primary remote [${current.remotes?.primary}]: `, remoteNames, current.remotes?.primary, signal)
|
|
365
|
-
: await askString(rl, `Primary remote [${current.remotes?.primary}]: `, current.remotes?.primary ?? 'origin', signal);
|
|
366
|
-
const issueProvider =
|
|
403
|
+
: await askString(rl, `Primary remote [${current.remotes?.primary}]: `, current.remotes?.primary ?? 'origin', signal));
|
|
404
|
+
const issueProvider = supplied.issueProvider
|
|
405
|
+
?? await askChoice(rl, `Issue provider (${ISSUE_PROVIDERS.join('/')}): `, ISSUE_PROVIDERS, plan.issueProvider, signal);
|
|
367
406
|
const issueTracker = issueProvider === 'local'
|
|
368
407
|
? 'local'
|
|
369
|
-
: remoteNames.length > 0
|
|
408
|
+
: supplied.issueTracker ?? (remoteNames.length > 0
|
|
370
409
|
? await askChoice(rl, `Issue tracker remote [${current.remotes?.issue_tracker}]: `, remoteNames, current.remotes?.issue_tracker, signal)
|
|
371
|
-
: await askString(rl, `Issue tracker remote [${current.remotes?.issue_tracker}]: `, current.remotes?.issue_tracker ?? primary, signal);
|
|
372
|
-
const ci = remoteNames.length > 0
|
|
410
|
+
: await askString(rl, `Issue tracker remote [${current.remotes?.issue_tracker}]: `, current.remotes?.issue_tracker ?? primary, signal));
|
|
411
|
+
const ci = supplied.ci ?? (remoteNames.length > 0
|
|
373
412
|
? await askChoice(rl, `CI remote [${current.remotes?.ci}]: `, remoteNames, current.remotes?.ci, signal)
|
|
374
|
-
: await askString(rl, `CI remote [${current.remotes?.ci}]: `, current.remotes?.ci ?? primary, signal);
|
|
375
|
-
const deliveryMode =
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
const
|
|
413
|
+
: await askString(rl, `CI remote [${current.remotes?.ci}]: `, current.remotes?.ci ?? primary, signal));
|
|
414
|
+
const deliveryMode = supplied.deliveryMode
|
|
415
|
+
?? await askChoice(rl, `Delivery mode (${DELIVERY_MODES.join('/')}): `, DELIVERY_MODES, current.delivery?.mode, signal);
|
|
416
|
+
const defaultBranch = supplied.defaultBranch
|
|
417
|
+
?? await askString(rl, `Default branch [${current.delivery?.default_branch}]: `, current.delivery?.default_branch ?? 'main', signal);
|
|
418
|
+
const requireCiGreen = supplied.requireCiGreen
|
|
419
|
+
?? await askYesNo(rl, 'Require CI green before done? [Y/n]: ', current.delivery?.require_ci_green ?? true, signal);
|
|
420
|
+
const autoCloseIssues = supplied.autoCloseIssues
|
|
421
|
+
?? await askYesNo(rl, 'Auto-close linked issues from delivery? [Y/n]: ', current.delivery?.auto_close_issues ?? true, signal);
|
|
422
|
+
const forcePushPolicy = supplied.forcePushPolicy
|
|
423
|
+
?? await askChoice(rl, `Force-push policy (${FORCE_PUSH_POLICIES.join('/')}): `, FORCE_PUSH_POLICIES, current.delivery?.force_push_policy, signal);
|
|
424
|
+
const requireSignedCommits = supplied.requireSignedCommits
|
|
425
|
+
?? await askYesNo(rl, 'Require signed delivery commits? [y/N]: ', current.delivery?.require_signed_commits ?? false, signal);
|
|
426
|
+
const providers = supplied.providers
|
|
427
|
+
?? parseProviders(await askString(rl, `Providers [${current.providers.join(',')}]: `, current.providers.join(','), signal), current.providers);
|
|
428
|
+
// #3050: offer direct worker dispatch, only when there is something to
|
|
429
|
+
// offer (two or more worker CLIs detected, dispatch not already on or
|
|
430
|
+
// declined), and only in a context where the answer could actually be
|
|
431
|
+
// acted on: CI and dry-run never prompt (review item 5) — an unattended
|
|
432
|
+
// CI run could otherwise stall on a prompt timeout, and a dry-run would
|
|
433
|
+
// ask a question whose answer is never written. Both cases fall back to
|
|
434
|
+
// the informational hint at the end of `execute()` instead (via
|
|
435
|
+
// `plan.workerDispatchOffer.shouldOffer` staying true on the rebuilt plan).
|
|
436
|
+
// Strict/distinguishable consent (review items 2 and 4): only an actually
|
|
437
|
+
// answered "no" is recorded as a persistent decline. An explicit
|
|
438
|
+
// `--worker-dispatch` already answers this directly (#3062) — skip the
|
|
439
|
+
// question the same way as every other supplied field.
|
|
440
|
+
let workerDispatchChoice = supplied.workerDispatchChoice;
|
|
441
|
+
if (!workerDispatchChoice && plan.workerDispatchOffer.shouldOffer && process.env.CI !== 'true' && !supplied.dryRun) {
|
|
442
|
+
console.log('');
|
|
443
|
+
const outcome = await askConsent(rl, workerDispatchOfferQuestion(plan.workerDispatchOffer.detected), undefined, signal);
|
|
444
|
+
if (outcome.kind === 'answered')
|
|
445
|
+
workerDispatchChoice = outcome.value ? 'enable' : 'decline';
|
|
446
|
+
}
|
|
382
447
|
return {
|
|
383
448
|
projectDir: plan.projectDir,
|
|
384
|
-
providers
|
|
449
|
+
providers,
|
|
385
450
|
primary,
|
|
386
451
|
issueProvider,
|
|
387
452
|
issueTracker,
|
|
@@ -392,6 +457,7 @@ async function applyInteractivePrompts(plan, rl, signal) {
|
|
|
392
457
|
autoCloseIssues,
|
|
393
458
|
forcePushPolicy,
|
|
394
459
|
requireSignedCommits,
|
|
460
|
+
...(workerDispatchChoice ? { workerDispatchChoice } : {}),
|
|
395
461
|
};
|
|
396
462
|
}
|
|
397
463
|
function printPlan(plan) {
|
|
@@ -410,6 +476,45 @@ export const setupHandler = {
|
|
|
410
476
|
description: 'CLI helper for agent-led repository policy and tracker setup',
|
|
411
477
|
category: 'project',
|
|
412
478
|
aliases: [],
|
|
479
|
+
async help() {
|
|
480
|
+
return {
|
|
481
|
+
exitCode: 0,
|
|
482
|
+
rawOutput: true,
|
|
483
|
+
message: `Usage: aiwg setup project [options]
|
|
484
|
+
|
|
485
|
+
Options:
|
|
486
|
+
--target <dir> Project directory
|
|
487
|
+
--yes Confirm writes without prompting
|
|
488
|
+
--dry-run Preview the setup plan
|
|
489
|
+
--non-interactive Disable prompts
|
|
490
|
+
--json Emit the plan as JSON
|
|
491
|
+
--primary <remote> Primary repository remote
|
|
492
|
+
--issue-tracker <remote> Internal issue tracker remote
|
|
493
|
+
--customer-issue-tracker <remote> Customer issue tracker remote
|
|
494
|
+
--ci <remote> CI remote
|
|
495
|
+
--issue-provider <provider> Internal tracker provider
|
|
496
|
+
--customer-issue-provider <provider> Customer tracker provider
|
|
497
|
+
--delivery-mode <mode> Delivery policy
|
|
498
|
+
--default-branch <branch> Default branch
|
|
499
|
+
--require-ci-green <boolean> Require passing CI
|
|
500
|
+
--auto-close-issues <boolean> Close delivered issues
|
|
501
|
+
--issue-comment-on-cycle <boolean> Report issue cycles
|
|
502
|
+
--force-push-policy <policy> Force-push policy
|
|
503
|
+
--require-signed-commits <boolean> Require signed commits
|
|
504
|
+
--committer-name <name> Committer identity
|
|
505
|
+
--committer-email <email> Committer email
|
|
506
|
+
--signing-format <format> Signing format
|
|
507
|
+
--signing-key <key> Signing key
|
|
508
|
+
--signing-enforce <commits|tags|all> Signing enforcement
|
|
509
|
+
--tracker-actor-login <login> Internal tracker actor
|
|
510
|
+
--tracker-actor-via <via> Internal tracker access method
|
|
511
|
+
--customer-tracker-actor-login <login> Customer tracker actor
|
|
512
|
+
--customer-tracker-actor-via <via> Customer tracker access method
|
|
513
|
+
--worker-dispatch <choice> Worker dispatch policy
|
|
514
|
+
--providers <ids> Comma-separated provider IDs
|
|
515
|
+
`,
|
|
516
|
+
};
|
|
517
|
+
},
|
|
413
518
|
async execute(ctx) {
|
|
414
519
|
const [subcommand] = ctx.args;
|
|
415
520
|
if (subcommand && subcommand !== 'project' && !subcommand.startsWith('--')) {
|
|
@@ -420,12 +525,32 @@ export const setupHandler = {
|
|
|
420
525
|
}
|
|
421
526
|
const args = subcommand === 'project' ? ctx.args.slice(1) : ctx.args;
|
|
422
527
|
const options = parseSetupProjectOptions({ ...ctx, args });
|
|
528
|
+
// #3062 review item 12: the one shared interactive decision (TTY, TERM,
|
|
529
|
+
// CI, DEBIAN_FRONTEND) — this used to check only `process.stdin.isTTY &&
|
|
530
|
+
// process.stdout.isTTY`, so a CI job with a pseudo-terminal could still
|
|
531
|
+
// reach these prompts.
|
|
532
|
+
const canPrompt = isInteractive(options.nonInteractive);
|
|
533
|
+
// #3062 second review, finding 6: refuse before any child process runs
|
|
534
|
+
// — `buildSetupProjectPlan()` below makes four `git` calls on its own,
|
|
535
|
+
// and this exact refusal used to happen only after building (and
|
|
536
|
+
// printing) the full plan. A write that can never be confirmed (no
|
|
537
|
+
// `--yes`, no terminal, not a dry run) is known from `options` alone.
|
|
538
|
+
if (!options.dryRun && !options.yes && !canPrompt) {
|
|
539
|
+
throw new AiwgError({
|
|
540
|
+
code: 'ERR_NON_INTERACTIVE_CONFIRMATION_REQUIRED',
|
|
541
|
+
message: 'Refusing to write project setup in a non-interactive context without --yes.',
|
|
542
|
+
hint: 'Re-run with `aiwg setup project --yes` or use `--dry-run` to preview only.',
|
|
543
|
+
exitCode: EXIT_CODES.USAGE,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
423
546
|
let plan = await buildSetupProjectPlan(options);
|
|
424
|
-
const canPrompt = !options.nonInteractive && process.stdin.isTTY && process.stdout.isTTY;
|
|
425
547
|
if (!options.yes && canPrompt) {
|
|
426
548
|
const rl = createPromptInterface();
|
|
427
549
|
try {
|
|
428
|
-
|
|
550
|
+
// #3062 review item 10: every field already supplied by flag is
|
|
551
|
+
// passed straight through so it is never re-asked — only genuinely
|
|
552
|
+
// missing ones prompt.
|
|
553
|
+
const prompted = await applyInteractivePrompts(plan, rl, ctx.signal, options);
|
|
429
554
|
plan = await buildSetupProjectPlan({ ...options, ...prompted });
|
|
430
555
|
}
|
|
431
556
|
finally {
|
|
@@ -445,6 +570,19 @@ export const setupHandler = {
|
|
|
445
570
|
exitCode: EXIT_CODES.CONFIG,
|
|
446
571
|
});
|
|
447
572
|
}
|
|
573
|
+
// #3050: non-interactive/--yes/CI/dry-run runs never prompt — the
|
|
574
|
+
// question above already applied a choice when it was asked (which
|
|
575
|
+
// clears `shouldOffer` on the rebuilt plan), so `shouldOffer` is only
|
|
576
|
+
// ever still true here when nothing asked. In `--json` mode the offer
|
|
577
|
+
// is structured data on the JSON object, never a separate
|
|
578
|
+
// human-readable line — a stray print after the JSON would make
|
|
579
|
+
// `setup project --json` unparseable (review item 6).
|
|
580
|
+
// #3062: an explicit `--worker-dispatch` argument clears `shouldOffer`
|
|
581
|
+
// the same way an answered prompt does, so `applied_choice` (alongside
|
|
582
|
+
// the top-level `dry_run` flag) is how `--json --dry-run` reports what
|
|
583
|
+
// the argument would have written — `previewBlocks()` deliberately
|
|
584
|
+
// excludes `parallelism`/`setup` (an unrelated, pre-existing contract),
|
|
585
|
+
// so this field carries that information instead of widening it.
|
|
448
586
|
if (options.json) {
|
|
449
587
|
console.log(JSON.stringify({
|
|
450
588
|
project_dir: plan.projectDir,
|
|
@@ -453,21 +591,24 @@ export const setupHandler = {
|
|
|
453
591
|
issue_provider: plan.issueProvider,
|
|
454
592
|
warnings: plan.warnings,
|
|
455
593
|
config: previewBlocks(plan.next),
|
|
594
|
+
worker_dispatch_offer: plan.workerDispatchOffer.shouldOffer
|
|
595
|
+
? { should_offer: true, detected: plan.workerDispatchOffer.detected,
|
|
596
|
+
hint: workerDispatchOfferHintWithArg(plan.workerDispatchOffer.detected) }
|
|
597
|
+
: { should_offer: false, ...(options.workerDispatchChoice ? { applied_choice: options.workerDispatchChoice } : {}) },
|
|
456
598
|
}, null, 2));
|
|
457
599
|
}
|
|
458
600
|
else {
|
|
459
601
|
printPlan(plan);
|
|
602
|
+
if (options.workerDispatchChoice === 'enable')
|
|
603
|
+
ui.info('Next: aiwg doctor --probe-workers --qualify.');
|
|
604
|
+
if (plan.workerDispatchOffer.shouldOffer) {
|
|
605
|
+
ui.info(workerDispatchOfferHintWithArg(plan.workerDispatchOffer.detected));
|
|
606
|
+
}
|
|
460
607
|
}
|
|
461
608
|
if (options.dryRun)
|
|
462
609
|
return { exitCode: 0 };
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
code: 'ERR_NON_INTERACTIVE_CONFIRMATION_REQUIRED',
|
|
466
|
-
message: 'Refusing to write project setup in a non-interactive context without --yes.',
|
|
467
|
-
hint: 'Re-run with `aiwg setup project --yes` or use `--dry-run` to preview only.',
|
|
468
|
-
exitCode: EXIT_CODES.USAGE,
|
|
469
|
-
});
|
|
470
|
-
}
|
|
610
|
+
// The `!options.yes && !canPrompt` refusal above (review finding 6)
|
|
611
|
+
// already covers this exact condition before any git call ran.
|
|
471
612
|
if (!options.yes && canPrompt) {
|
|
472
613
|
const rl = createPromptInterface();
|
|
473
614
|
try {
|
|
@@ -204,6 +204,7 @@ async function handleSteward(args, ctx) {
|
|
|
204
204
|
aiwg steward — Provider capability awareness and command routing
|
|
205
205
|
|
|
206
206
|
Usage:
|
|
207
|
+
aiwg steward decision-offload [--json] Offline advisory readiness and adoption report
|
|
207
208
|
aiwg steward capabilities --provider <name> Capabilities for a specific provider
|
|
208
209
|
aiwg steward capabilities --feature <name> Provider support matrix for a feature
|
|
209
210
|
aiwg steward capabilities --all Full matrix (all providers x features)
|
|
@@ -231,6 +232,16 @@ async function handleSteward(args, ctx) {
|
|
|
231
232
|
`);
|
|
232
233
|
return;
|
|
233
234
|
}
|
|
235
|
+
if (subcommand === 'decision-offload') {
|
|
236
|
+
const unknown = args.slice(1).filter(arg => arg !== '--json');
|
|
237
|
+
if (unknown.length)
|
|
238
|
+
throw new AiwgError({ code: 'ERR_USAGE_UNKNOWN_ARGUMENT',
|
|
239
|
+
message: `Unknown decision-offload argument: ${unknown[0]}`, exitCode: EXIT_CODES.USAGE });
|
|
240
|
+
const { buildDecisionOffloadSnapshot } = await import('../../decision/offload.js');
|
|
241
|
+
const decisionOffload = await buildDecisionOffloadSnapshot({ projectRoot: ctx?.cwd ?? process.cwd(), frameworkRoot: ctx?.frameworkRoot });
|
|
242
|
+
console.log(JSON.stringify(args.includes('--json') ? { decisionOffload } : decisionOffload, null, 2));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
234
245
|
if (subcommand === 'permissions') {
|
|
235
246
|
const operation = args[1];
|
|
236
247
|
// `<namespace> --help` must reach the same usage block bare invocation prints (#2533).
|
|
@@ -21,6 +21,8 @@ import { sessionHandler } from "./session.js";
|
|
|
21
21
|
import { feedbackHandler } from "./feedback.js";
|
|
22
22
|
import { handlerResultFromError } from "../errors.js";
|
|
23
23
|
import { getProjectDir } from "../../config/aiwg-config.js";
|
|
24
|
+
import { deployedSkillRoots } from "../../providers/deployed-skill-roots.js";
|
|
25
|
+
import { releaseSkillOwnership } from "../../providers/skill-ownership.mjs";
|
|
24
26
|
import { formatDeployedWorkspaceSignalPlan, readWorkspaceSignalPlan } from "../workspace-signals.js";
|
|
25
27
|
import * as path from "node:path";
|
|
26
28
|
import * as fsSync from "node:fs";
|
|
@@ -32,6 +34,9 @@ export const quickrefHandler = {
|
|
|
32
34
|
description: 'Generate and deploy an always-visible project quickref',
|
|
33
35
|
category: 'project',
|
|
34
36
|
aliases: [],
|
|
37
|
+
async help() {
|
|
38
|
+
return { exitCode: 0, message: 'Usage: aiwg quickref generate|deploy --project [--provider <id>] [--dry-run]', rawOutput: true };
|
|
39
|
+
},
|
|
35
40
|
async execute(ctx) {
|
|
36
41
|
const action = ctx.args.find(arg => !arg.startsWith('-')) ?? 'generate';
|
|
37
42
|
if (!ctx.args.includes('--project')) {
|
|
@@ -147,6 +152,11 @@ export const mcpHandler = {
|
|
|
147
152
|
description: "AIWG MCP server commands (serve, install, add, remove, update, list, inject, info)",
|
|
148
153
|
category: "mcp",
|
|
149
154
|
aliases: ["mcp", "aiwg-mcp"],
|
|
155
|
+
async help() {
|
|
156
|
+
const { main } = await import("../../mcp/cli.mjs");
|
|
157
|
+
await main(["--help"]);
|
|
158
|
+
return { exitCode: 0 };
|
|
159
|
+
},
|
|
150
160
|
async execute(ctx) {
|
|
151
161
|
try {
|
|
152
162
|
// Dynamic import to avoid loading MCP dependencies unless needed
|
|
@@ -647,7 +657,15 @@ async function removeUserScopeDeploy(args) {
|
|
|
647
657
|
continue;
|
|
648
658
|
}
|
|
649
659
|
try {
|
|
650
|
-
|
|
660
|
+
if (type === 'skills') {
|
|
661
|
+
const { resolveFrameworkDir } = await import('./use.js');
|
|
662
|
+
const released = releaseSkillOwnership(target, { frameworkSlug: resolveFrameworkDir(positional) ?? positional });
|
|
663
|
+
if (released === null)
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
await fs.rm(target, { recursive: true, force: true });
|
|
668
|
+
}
|
|
651
669
|
deletedHere++;
|
|
652
670
|
totalDeleted++;
|
|
653
671
|
}
|
|
@@ -699,7 +717,9 @@ export const removeHandler = {
|
|
|
699
717
|
// adapter validates receipt hashes and preserves operator modifications.
|
|
700
718
|
const nativeRemovalProvider = parseRemoveProvider(ctx.args);
|
|
701
719
|
if (firstRemovePositional(ctx.args) === 'omp' && nativeRemovalProvider.provider === 'omp') {
|
|
702
|
-
|
|
720
|
+
// Loaded from the package root, not by a path relative to this file: the
|
|
721
|
+
// compiled handler sits one directory deeper than its source.
|
|
722
|
+
const { uninstall } = (await import(pathToFileURL(path.join(await getFrameworkRoot(), 'tools/agents/providers/omp.mjs')).href));
|
|
703
723
|
const { getProjectDir } = await import('../../config/aiwg-config.js');
|
|
704
724
|
const dryRun = ctx.args.includes('--dry-run');
|
|
705
725
|
const scope = ctx.args.includes('--user') || isScopeUser(ctx.args) ? 'user' : 'project';
|
|
@@ -768,6 +788,33 @@ export const removeHandler = {
|
|
|
768
788
|
const projectDir = getProjectDir({ cwd: ctx.cwd }, ctx.args);
|
|
769
789
|
const config = await readAiwgConfig(projectDir);
|
|
770
790
|
const entry = config?.installed?.[positionalArg];
|
|
791
|
+
if (config && entry && entry.source !== 'project-local') {
|
|
792
|
+
const fs = await import('node:fs/promises');
|
|
793
|
+
const { resolveFrameworkDir } = await import('./use.js');
|
|
794
|
+
const frameworkSlug = resolveFrameworkDir(positionalArg) ?? positionalArg;
|
|
795
|
+
const dryRun = ctx.args.includes('--dry-run');
|
|
796
|
+
const providers = Object.keys(entry.deployedTo).filter(p => !providerParse.provider || p === providerParse.provider);
|
|
797
|
+
if (providerParse.provider && providers.length === 0) {
|
|
798
|
+
return { exitCode: 1, message: `Error: '${positionalArg}' is not deployed for provider '${providerParse.provider}'.` };
|
|
799
|
+
}
|
|
800
|
+
let released = 0;
|
|
801
|
+
for (const provider of providers) {
|
|
802
|
+
for (const root of deployedSkillRoots(projectDir, provider)) {
|
|
803
|
+
for (const name of await fs.readdir(root).catch(() => [])) {
|
|
804
|
+
if (releaseSkillOwnership(path.join(root, name), { frameworkSlug }, { dryRun }) !== null)
|
|
805
|
+
released++;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
if (!dryRun && !ctx.args.includes('--keep-registry'))
|
|
809
|
+
delete entry.deployedTo[provider];
|
|
810
|
+
}
|
|
811
|
+
if (!dryRun && !ctx.args.includes('--keep-registry')) {
|
|
812
|
+
if (Object.keys(entry.deployedTo).length === 0)
|
|
813
|
+
delete config.installed[positionalArg];
|
|
814
|
+
await writeAiwgConfig(projectDir, config);
|
|
815
|
+
}
|
|
816
|
+
return { exitCode: 0, message: `${dryRun ? 'Would release' : 'Released'} ${released} skill ownership receipt(s); operator files preserved.` };
|
|
817
|
+
}
|
|
771
818
|
if (config && entry?.source === 'project-local') {
|
|
772
819
|
const force = ctx.args.includes('--force');
|
|
773
820
|
const dryRun = ctx.args.includes('--dry-run');
|
|
@@ -1300,12 +1347,17 @@ export const indexHandler = {
|
|
|
1300
1347
|
description: "Artifact index commands (build, query, deps, stats)",
|
|
1301
1348
|
category: "index",
|
|
1302
1349
|
aliases: [],
|
|
1350
|
+
async help() {
|
|
1351
|
+
const { printIndexUsage } = await import("../../artifacts/cli.js");
|
|
1352
|
+
printIndexUsage();
|
|
1353
|
+
return { exitCode: 0 };
|
|
1354
|
+
},
|
|
1303
1355
|
async execute(ctx) {
|
|
1304
1356
|
try {
|
|
1305
1357
|
const { main } = await import("../../artifacts/cli.js");
|
|
1306
1358
|
await main(ctx.args);
|
|
1307
1359
|
return {
|
|
1308
|
-
exitCode: 0,
|
|
1360
|
+
exitCode: Number(process.exitCode ?? 0),
|
|
1309
1361
|
};
|
|
1310
1362
|
}
|
|
1311
1363
|
catch (error) {
|
|
@@ -1324,6 +1376,11 @@ export const corpusHandler = {
|
|
|
1324
1376
|
description: "Research-corpus tools (radar-init, radar-status, radar-report)",
|
|
1325
1377
|
category: "index",
|
|
1326
1378
|
aliases: [],
|
|
1379
|
+
async help() {
|
|
1380
|
+
const { corpusMain } = await import("../../artifacts/corpus-tools/cli.js");
|
|
1381
|
+
await corpusMain(["--help"]);
|
|
1382
|
+
return { exitCode: 0 };
|
|
1383
|
+
},
|
|
1327
1384
|
async execute(ctx) {
|
|
1328
1385
|
try {
|
|
1329
1386
|
const { corpusMain } = await import("../../artifacts/corpus-tools/cli.js");
|
|
@@ -16,15 +16,25 @@ import { join, basename, resolve } from 'node:path';
|
|
|
16
16
|
import { pathToFileURL } from 'node:url';
|
|
17
17
|
import { projectAiwgPath } from '../../config/project-artifacts.js';
|
|
18
18
|
import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
|
|
19
|
+
import { isSessionProviderResolution, resolveActiveProvider } from '../provider-resolution.js';
|
|
19
20
|
// ── Provider Detection ───────────────────────────────────────
|
|
20
|
-
function detectProvider(args) {
|
|
21
|
+
async function detectProvider(args, cwd) {
|
|
21
22
|
const providerFlag = parseFlag(args, '--provider');
|
|
22
23
|
if (providerFlag)
|
|
23
24
|
return normalizeProviderDefinitionId(providerFlag) ?? providerFlag;
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
// Resolved through the same shared provider-resolution path `runtime-info`
|
|
26
|
+
// and `steward capabilities` use (`resolveActiveProvider` -> the `claude`
|
|
27
|
+
// provider's `detection.env` markers in provider-definitions.ts) so none
|
|
28
|
+
// of them disagree about which provider the current session is running
|
|
29
|
+
// under (#2623, #2627, #3054). The ad-hoc `CLAUDE_CODE_VERSION`/
|
|
30
|
+
// `ANTHROPIC_API_KEY` check this replaced was stale (neither is set by
|
|
31
|
+
// current Claude Code) and `ANTHROPIC_API_KEY` was a false positive for
|
|
32
|
+
// any non-Claude session with that key set.
|
|
33
|
+
// Only a session signal counts. Native team dispatch needs the command to
|
|
34
|
+
// be running inside that harness; project configuration alone does not
|
|
35
|
+
// establish that.
|
|
36
|
+
const resolution = await resolveActiveProvider({ cwd });
|
|
37
|
+
return isSessionProviderResolution(resolution) ? (resolution.provider ?? 'unknown') : 'unknown';
|
|
28
38
|
}
|
|
29
39
|
function isNativeTeamsProvider(provider) {
|
|
30
40
|
// Only Claude Code has native agent team support
|
|
@@ -154,7 +164,7 @@ async function teamRunOmp(ctx) {
|
|
|
154
164
|
}
|
|
155
165
|
}
|
|
156
166
|
async function teamRun(ctx) {
|
|
157
|
-
if (['omp', 'oh-my-pi'].includes(detectProvider(ctx.args)))
|
|
167
|
+
if (['omp', 'oh-my-pi'].includes(await detectProvider(ctx.args, ctx.cwd)))
|
|
158
168
|
return teamRunOmp(ctx);
|
|
159
169
|
const positional = getPositionalArgs(ctx.args);
|
|
160
170
|
const slug = positional[0];
|
|
@@ -162,7 +172,7 @@ async function teamRun(ctx) {
|
|
|
162
172
|
ui.error('Usage: aiwg team run <name> [--provider <p>] [--objective "<text>"]');
|
|
163
173
|
return { exitCode: 1 };
|
|
164
174
|
}
|
|
165
|
-
const provider = detectProvider(ctx.args);
|
|
175
|
+
const provider = await detectProvider(ctx.args, ctx.cwd);
|
|
166
176
|
const objective = parseFlag(ctx.args, '--objective') || `Execute ${slug} team workflow`;
|
|
167
177
|
const team = await loadTeam(slug, ctx.frameworkRoot, ctx.cwd);
|
|
168
178
|
if (!team) {
|
|
@@ -221,7 +231,7 @@ async function teamRun(ctx) {
|
|
|
221
231
|
// ── Subcommand: list ─────────────────────────────────────────
|
|
222
232
|
async function teamList(ctx) {
|
|
223
233
|
const json = hasFlag(ctx.args, '--json');
|
|
224
|
-
const provider = detectProvider(ctx.args);
|
|
234
|
+
const provider = await detectProvider(ctx.args, ctx.cwd);
|
|
225
235
|
const teams = await listAllTeams(ctx.frameworkRoot, ctx.cwd);
|
|
226
236
|
if (json) {
|
|
227
237
|
console.log(JSON.stringify(teams.map(t => ({
|
|
@@ -76,6 +76,9 @@ export const uhpHandler = {
|
|
|
76
76
|
description: 'Inspect and smoke-test an explicitly selected experimental UHP endpoint profile',
|
|
77
77
|
category: 'toolsmith',
|
|
78
78
|
aliases: [],
|
|
79
|
+
async help() {
|
|
80
|
+
return { exitCode: 0, message: usage(), rawOutput: true };
|
|
81
|
+
},
|
|
79
82
|
async execute(ctx) {
|
|
80
83
|
try {
|
|
81
84
|
return await executeUhp(ctx);
|