@aiwg/cli 2026.8.8 → 2026.8.10
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 +23 -8
- package/THIRD_PARTY_NOTICES.md +35 -0
- package/agentic/code/providers/capability-matrix.yaml +3 -3
- package/bin/aiwg.mjs +125 -0
- package/dist/src/artifacts/backends/graphology-backend.js +4 -3
- package/dist/src/artifacts/backends/sqlite-backend.js +4 -5
- package/dist/src/artifacts/cli.js +2 -2
- package/dist/src/artifacts/corpus-tools/cli.js +27 -0
- package/dist/src/artifacts/corpus-tools/profile-embed.js +3 -2
- package/dist/src/artifacts/corpus-tools/retrieval-lab.js +356 -0
- package/dist/src/artifacts/discover-facets.js +2 -2
- package/dist/src/artifacts/embedding-index.js +9 -8
- package/dist/src/artifacts/graph-backend.js +2 -2
- package/dist/src/artifacts/query-engine.js +21 -7
- package/dist/src/artifacts/repair.js +47 -0
- package/dist/src/artifacts/types.js +3 -3
- package/dist/src/cli/command-log.js +2 -2
- package/dist/src/cli/handlers/artifacts.js +50 -1
- package/dist/src/cli/handlers/cost-report.js +71 -0
- package/dist/src/cli/handlers/evidence.js +78 -0
- package/dist/src/cli/handlers/help.js +9 -0
- package/dist/src/cli/handlers/index.js +8 -3
- package/dist/src/cli/handlers/local-executor.js +4 -3
- package/dist/src/cli/handlers/refresh.js +20 -8
- package/dist/src/cli/handlers/regenerate.js +3 -3
- package/dist/src/cli/handlers/serve.js +15 -36
- package/dist/src/cli/handlers/setup-manifest.js +8 -1
- package/dist/src/cli/handlers/use.js +256 -70
- package/dist/src/cli/handlers/utilities.js +149 -0
- package/dist/src/cli/handlers/workspace.js +10 -0
- package/dist/src/cli/help-generator.js +2 -1
- package/dist/src/cli/router.js +4 -1
- package/dist/src/cli/services/deployment-verification.js +596 -0
- package/dist/src/cli/skill-usage.js +2 -2
- package/dist/src/cli/workflow-orchestrator.js +1 -1
- package/dist/src/cli/workspace-signals.js +2 -2
- package/dist/src/config/aiwg-config.js +54 -27
- package/dist/src/config/cli.js +3 -3
- package/dist/src/config/project-artifacts-health.js +2 -0
- package/dist/src/config/project-artifacts-health.mjs +123 -0
- package/dist/src/config/project-artifacts-runtime.mjs +16 -0
- package/dist/src/config/project-artifacts.js +2 -1
- package/dist/src/cost/fleet-report.js +329 -0
- package/dist/src/evidence/bundle.js +256 -0
- package/dist/src/extensions/commands/definitions.js +77 -25
- package/dist/src/extensions/deployment-registration.js +6 -4
- package/dist/src/features/catalog.js +26 -0
- package/dist/src/features/cli.js +1 -3
- package/dist/src/features/runtime.js +17 -1
- package/dist/src/issues/cli.js +91 -7
- package/dist/src/mcp/server.mjs +1 -1
- package/dist/src/ops/registry.js +2 -2
- package/dist/src/policy/authorization.js +2 -2
- package/dist/src/providers/capability-matrix.yaml +3 -3
- package/dist/src/providers/provider-definitions.js +7 -5
- package/dist/src/providers/provider-definitions.mjs +1 -1
- package/dist/src/serve/pty-bridge.js +2 -8
- package/dist/src/serve/screen-reader.js +3 -6
- package/dist/src/smiths/context-pipeline/aiwg-md.js +2 -2
- package/dist/src/smiths/context-pipeline/finalization.js +18 -5
- package/dist/src/smiths/context-pipeline/generator.js +2 -2
- package/dist/src/smiths/context-pipeline/workspace-context.js +16 -17
- package/package.json +2 -1
- package/tools/agents/deploy-agents.mjs +10 -11
- package/tools/agents/providers/base.mjs +47 -5
- package/tools/agents/providers/openclaw.mjs +5 -2
- package/tools/agents/providers/windsurf.mjs +13 -24
- package/tools/skills/deploy-skills-codex.mjs +21 -5
|
@@ -36,16 +36,22 @@ import { installAiwgHooks } from '../../extensions/claude-hooks-installer.js';
|
|
|
36
36
|
import { detectScope, mirrorToUserScope, rejectOpenClawProjectScope, USER_SCOPE_PATHS, } from '../scope-resolver.js';
|
|
37
37
|
import { maybeWarnProjectIsolation } from '../project-isolation/index.js';
|
|
38
38
|
import { formatWorkspaceSignalPlan, includedBundleIds, resolveWorkspaceSignalPlan, writeWorkspaceSignalPlan, } from '../workspace-signals.js';
|
|
39
|
-
import { getProviderArtifactPathStrings, getProviderKernelSkillPath, normalizeProviderDefinitionId, } from '../../providers/provider-definitions.js';
|
|
39
|
+
import { getProviderArtifactPathStrings, getProviderDefinition, getProviderKernelSkillPath, normalizeProviderDefinitionId, } from '../../providers/provider-definitions.js';
|
|
40
40
|
// Module-level guard so the iteration loops further down (which re-enter
|
|
41
41
|
// execute() per framework/provider) don't re-emit the warning each pass.
|
|
42
42
|
// Reset is not needed: a single CLI process is one user invocation.
|
|
43
43
|
let projectIsolationChecked = false;
|
|
44
|
+
// Non-zero only while the outer `aiwg use --json` orchestration wrapper is
|
|
45
|
+
// collecting child-process output. The CLI is single-command-per-process;
|
|
46
|
+
// recursive provider expansion shares this guard intentionally.
|
|
47
|
+
let machineReadableUseDepth = 0;
|
|
44
48
|
// Context-pipeline: emits WORKSPACE.md + AIWG.md + provider adapters last.
|
|
45
49
|
// for non-Claude providers per ADR-1 (.aiwg/architecture/adr-agents-md-aggregation.md).
|
|
46
50
|
// Distinct from agentsmith (which creates subagent personas).
|
|
47
51
|
import { generate as generateContextFiles, discoverDeployedArtifacts, } from '../../smiths/context-pipeline/index.js';
|
|
48
52
|
import { verifyModelWrapperDeployment } from '../../models/wrapper-deployment.js';
|
|
53
|
+
import { loadGraphIndexFile } from '../../artifacts/index-reader.js';
|
|
54
|
+
import { aggregateUseDeploymentResult, buildDryRunUseResult, renderUseDeploymentResult, verifyProviderDeployment, } from '../services/deployment-verification.js';
|
|
49
55
|
/**
|
|
50
56
|
* Valid framework identifiers
|
|
51
57
|
*/
|
|
@@ -517,11 +523,13 @@ async function runPreDeployCollisionCheck(opts) {
|
|
|
517
523
|
sourceSkillsDir,
|
|
518
524
|
});
|
|
519
525
|
const report = formatCollisionReport(results, { verbose });
|
|
520
|
-
if (report) {
|
|
526
|
+
if (report && machineReadableUseDepth === 0) {
|
|
521
527
|
process.stderr.write(report + '\n');
|
|
522
528
|
}
|
|
523
529
|
if (hasBlockingCollisions(results) && !force) {
|
|
524
|
-
|
|
530
|
+
if (machineReadableUseDepth === 0) {
|
|
531
|
+
process.stderr.write('\nDeployment blocked. Use --force to override.\n');
|
|
532
|
+
}
|
|
525
533
|
return false;
|
|
526
534
|
}
|
|
527
535
|
return true;
|
|
@@ -559,7 +567,7 @@ const NEXT_STEPS = {
|
|
|
559
567
|
'warp/sdlc': agenticNextSteps('Open Warp: Start a Warp session in this project root.'),
|
|
560
568
|
'copilot/sdlc': agenticNextSteps('Open VS Code: Open this workspace and use Copilot Chat.'),
|
|
561
569
|
'codex/sdlc': agenticNextSteps('Open Codex: Restart Codex in this project root.'),
|
|
562
|
-
'windsurf/sdlc': agenticNextSteps('Open
|
|
570
|
+
'windsurf/sdlc': agenticNextSteps('Open Devin Desktop: Open this project in Devin Desktop and ask Devin for AIWG status.'),
|
|
563
571
|
'openclaw/sdlc': agenticNextSteps('Start OpenClaw: Open OpenClaw with this project workspace.'),
|
|
564
572
|
'openclaw/marketing': agenticNextSteps('Start OpenClaw: Open OpenClaw with this project workspace.'),
|
|
565
573
|
'openclaw/all': agenticNextSteps('Start OpenClaw: Open OpenClaw with this project workspace.'),
|
|
@@ -575,9 +583,6 @@ export function nextStepsFor(framework, provider = 'claude') {
|
|
|
575
583
|
const steps = NEXT_STEPS[providerKey] ?? NEXT_STEPS[framework] ?? NEXT_STEPS.sdlc;
|
|
576
584
|
return steps.map((step) => step.replace('{{aiwg-regenerate}}', regenerateInvocation));
|
|
577
585
|
}
|
|
578
|
-
function printNextSteps(framework, provider = 'claude') {
|
|
579
|
-
ui.section('Next steps:', nextStepsFor(framework, provider));
|
|
580
|
-
}
|
|
581
586
|
/**
|
|
582
587
|
* Per-provider session-reload requirement after `aiwg use`.
|
|
583
588
|
*
|
|
@@ -613,8 +618,8 @@ const SESSION_RELOAD_NOTICE = {
|
|
|
613
618
|
rationale: 'Warp aggregates context from WARP.md when a new tab spawns; existing tabs keep the prior version.',
|
|
614
619
|
},
|
|
615
620
|
windsurf: {
|
|
616
|
-
action: 'Restart
|
|
617
|
-
rationale: '
|
|
621
|
+
action: 'Restart Devin Desktop or reload the workspace so the aggregated AGENTS.md is re-parsed.',
|
|
622
|
+
rationale: 'Devin Desktop reads the Windsurf-compatible AGENTS.md once per workspace session.',
|
|
618
623
|
},
|
|
619
624
|
factory: {
|
|
620
625
|
action: 'Restart your Factory droid runtime to pick up new entries in .factory/droids/.',
|
|
@@ -723,18 +728,6 @@ async function countDeployedArtifacts(target, paths, provider) {
|
|
|
723
728
|
behaviors: await countDirs(paths.behaviors),
|
|
724
729
|
};
|
|
725
730
|
}
|
|
726
|
-
async function countDiscoverableSkills(aiwgRoot) {
|
|
727
|
-
try {
|
|
728
|
-
const { loadGraphIndexFile } = await import('../../artifacts/index-reader.js');
|
|
729
|
-
const index = loadGraphIndexFile(aiwgRoot, 'metadata.json', 'framework');
|
|
730
|
-
if (!index?.entries)
|
|
731
|
-
return null;
|
|
732
|
-
return Object.values(index.entries).filter(entry => entry.type === 'skill').length;
|
|
733
|
-
}
|
|
734
|
-
catch {
|
|
735
|
-
return null;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
731
|
/**
|
|
739
732
|
* Detect forge targets from .git/config remote URLs.
|
|
740
733
|
* Returns a list of forge types found: 'github' | 'gitea'
|
|
@@ -1106,7 +1099,7 @@ async function deployProjectLocalBundles(opts) {
|
|
|
1106
1099
|
const upstream = await buildUpstreamRegistry({ frameworkRoot });
|
|
1107
1100
|
const shadowResult = await resolveShadows(targetBundles, upstream);
|
|
1108
1101
|
const report = formatShadowReport(shadowResult);
|
|
1109
|
-
if (report) {
|
|
1102
|
+
if (report && machineReadableUseDepth === 0) {
|
|
1110
1103
|
process.stderr.write(report + '\n');
|
|
1111
1104
|
}
|
|
1112
1105
|
// #1037/#1049 — Activity log per shadow resolution
|
|
@@ -1237,15 +1230,12 @@ function resolveBuiltInProviderForUse(provider) {
|
|
|
1237
1230
|
}
|
|
1238
1231
|
function unsupportedProviderMessage(provider) {
|
|
1239
1232
|
const normalized = provider.trim().toLowerCase();
|
|
1240
|
-
if (normalized === 'devin
|
|
1233
|
+
if (normalized === 'devin-cli') {
|
|
1241
1234
|
return [
|
|
1242
1235
|
`Unsupported provider: ${provider}`,
|
|
1243
1236
|
'',
|
|
1244
|
-
'Devin
|
|
1245
|
-
'
|
|
1246
|
-
' aiwg use sdlc --provider devin-desktop',
|
|
1247
|
-
'',
|
|
1248
|
-
'Devin CLI has distinct rules/skills surfaces and is recorded as future-provider metadata; AIWG does not emit .devin/ provider output yet.',
|
|
1237
|
+
'Devin CLI has distinct rules/skills surfaces and is not a deployable AIWG provider yet.',
|
|
1238
|
+
'Use --provider devin for Devin Desktop deployments.',
|
|
1249
1239
|
].join('\n');
|
|
1250
1240
|
}
|
|
1251
1241
|
return null;
|
|
@@ -1670,6 +1660,46 @@ async function generateGlobalProjectContext(opts) {
|
|
|
1670
1660
|
},
|
|
1671
1661
|
});
|
|
1672
1662
|
}
|
|
1663
|
+
async function ensurePostDeployPhases(opts) {
|
|
1664
|
+
const currentIndex = loadGraphIndexFile(opts.frameworkRoot, 'metadata.json', 'framework');
|
|
1665
|
+
const builtAt = currentIndex ? Date.parse(currentIndex.builtAt) : Number.NaN;
|
|
1666
|
+
const startedAt = Date.parse(opts.invocationStartedAt);
|
|
1667
|
+
if (!Number.isFinite(builtAt) || builtAt + 2_000 < startedAt) {
|
|
1668
|
+
try {
|
|
1669
|
+
const { buildIndex } = await import('../../artifacts/index-builder.js');
|
|
1670
|
+
await buildIndex(opts.frameworkRoot, { graph: 'framework', explicit: false });
|
|
1671
|
+
}
|
|
1672
|
+
catch {
|
|
1673
|
+
// The shared verifier reports the index failure with stable remediation.
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
if (opts.args.includes('--no-context-files'))
|
|
1677
|
+
return;
|
|
1678
|
+
const paths = getProviderPaths(opts.provider);
|
|
1679
|
+
const sections = await discoverDeployedArtifacts(opts.projectPath, {
|
|
1680
|
+
agents: paths.agents,
|
|
1681
|
+
rules: paths.rules,
|
|
1682
|
+
skills: paths.skills,
|
|
1683
|
+
behaviors: paths.behaviors,
|
|
1684
|
+
});
|
|
1685
|
+
try {
|
|
1686
|
+
await generateContextFiles({
|
|
1687
|
+
provider: opts.provider,
|
|
1688
|
+
projectPath: opts.projectPath,
|
|
1689
|
+
sections,
|
|
1690
|
+
detectExistingFiles: true,
|
|
1691
|
+
force: opts.args.includes('--force-context-files'),
|
|
1692
|
+
skip: {
|
|
1693
|
+
workspaceMd: opts.args.includes('--no-workspace-md'),
|
|
1694
|
+
aiwgMd: opts.args.includes('--no-aiwg-md'),
|
|
1695
|
+
agentsMd: opts.args.includes('--no-agents-md'),
|
|
1696
|
+
},
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
catch {
|
|
1700
|
+
// The shared verifier reports context or provider-wiring failures.
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1673
1703
|
async function deploySourceDirectory(opts) {
|
|
1674
1704
|
const args = [
|
|
1675
1705
|
'--source', opts.source,
|
|
@@ -1820,7 +1850,158 @@ export class UseHandler {
|
|
|
1820
1850
|
description = 'Deploy AIWG framework to project or user scope';
|
|
1821
1851
|
category = 'framework';
|
|
1822
1852
|
aliases = [];
|
|
1853
|
+
orchestrationDepth = 0;
|
|
1823
1854
|
async execute(ctx) {
|
|
1855
|
+
const requestedBundle = firstUsePositional(ctx.args)
|
|
1856
|
+
?? (ctx.args[0] === '--profile' ? 'all' : undefined);
|
|
1857
|
+
const bypassOrchestration = this.orchestrationDepth > 0
|
|
1858
|
+
|| !requestedBundle
|
|
1859
|
+
|| requestedBundle === 'cockpit'
|
|
1860
|
+
|| ctx.args.includes('--workspace-signals');
|
|
1861
|
+
if (bypassOrchestration)
|
|
1862
|
+
return this.executeCore(ctx);
|
|
1863
|
+
this.orchestrationDepth += 1;
|
|
1864
|
+
try {
|
|
1865
|
+
return await this.executeOrchestrated(ctx, requestedBundle);
|
|
1866
|
+
}
|
|
1867
|
+
finally {
|
|
1868
|
+
this.orchestrationDepth -= 1;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
async executeOrchestrated(ctx, requestedBundle) {
|
|
1872
|
+
const startedAt = new Date().toISOString();
|
|
1873
|
+
const json = ctx.args.includes('--json');
|
|
1874
|
+
const coreArgs = ctx.args.filter((arg) => arg !== '--json');
|
|
1875
|
+
const remainingArgs = removeFirstPositional(coreArgs);
|
|
1876
|
+
const projectDir = getProjectDir(ctx, remainingArgs);
|
|
1877
|
+
const frameworkRoot = ctx.frameworkRoot || await getFrameworkRoot();
|
|
1878
|
+
const config = await readAiwgConfig(projectDir);
|
|
1879
|
+
const requestedProviders = configuredGlobalProviders(remainingArgs, config);
|
|
1880
|
+
const providers = [];
|
|
1881
|
+
for (const requestedProvider of requestedProviders) {
|
|
1882
|
+
const local = await resolveProjectLocalProviderAdapter(projectDir, requestedProvider);
|
|
1883
|
+
const builtIn = local.requestedProvider
|
|
1884
|
+
? local.provider
|
|
1885
|
+
: resolveBuiltInProviderForUse(local.provider).provider;
|
|
1886
|
+
if (!providers.includes(builtIn))
|
|
1887
|
+
providers.push(builtIn);
|
|
1888
|
+
}
|
|
1889
|
+
const dryRun = remainingArgs.includes('--dry-run');
|
|
1890
|
+
const requestedScope = remainingArgs.includes('--global')
|
|
1891
|
+
? 'user'
|
|
1892
|
+
: detectScope(remainingArgs);
|
|
1893
|
+
const contextOptOut = [
|
|
1894
|
+
'--no-context-files',
|
|
1895
|
+
'--no-workspace-md',
|
|
1896
|
+
'--no-aiwg-md',
|
|
1897
|
+
'--no-agents-md',
|
|
1898
|
+
].some((flag) => remainingArgs.includes(flag));
|
|
1899
|
+
const originalConsole = {
|
|
1900
|
+
log: console.log,
|
|
1901
|
+
info: console.info,
|
|
1902
|
+
warn: console.warn,
|
|
1903
|
+
error: console.error,
|
|
1904
|
+
};
|
|
1905
|
+
if (json) {
|
|
1906
|
+
machineReadableUseDepth += 1;
|
|
1907
|
+
console.log = () => { };
|
|
1908
|
+
console.info = () => { };
|
|
1909
|
+
console.warn = () => { };
|
|
1910
|
+
console.error = () => { };
|
|
1911
|
+
}
|
|
1912
|
+
let coreResult;
|
|
1913
|
+
try {
|
|
1914
|
+
coreResult = await this.executeCore({ ...ctx, args: coreArgs });
|
|
1915
|
+
}
|
|
1916
|
+
finally {
|
|
1917
|
+
if (json) {
|
|
1918
|
+
machineReadableUseDepth -= 1;
|
|
1919
|
+
console.log = originalConsole.log;
|
|
1920
|
+
console.info = originalConsole.info;
|
|
1921
|
+
console.warn = originalConsole.warn;
|
|
1922
|
+
console.error = originalConsole.error;
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
let result;
|
|
1926
|
+
if (dryRun && coreResult.exitCode === 0) {
|
|
1927
|
+
result = buildDryRunUseResult({
|
|
1928
|
+
projectRoot: projectDir,
|
|
1929
|
+
frameworkRoot,
|
|
1930
|
+
providers,
|
|
1931
|
+
scope: requestedScope,
|
|
1932
|
+
requestedBundles: [requestedBundle],
|
|
1933
|
+
contextOptOut,
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
else {
|
|
1937
|
+
if (coreResult.exitCode === 0 && !dryRun && !VALID_FRAMEWORKS.includes(requestedBundle)) {
|
|
1938
|
+
for (const provider of providers) {
|
|
1939
|
+
await ensurePostDeployPhases({
|
|
1940
|
+
frameworkRoot,
|
|
1941
|
+
projectPath: projectDir,
|
|
1942
|
+
provider,
|
|
1943
|
+
args: remainingArgs,
|
|
1944
|
+
invocationStartedAt: startedAt,
|
|
1945
|
+
});
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
const providerResults = [];
|
|
1949
|
+
for (const provider of providers) {
|
|
1950
|
+
const effectiveScope = provider === 'openclaw' || provider === 'openhuman'
|
|
1951
|
+
? 'user'
|
|
1952
|
+
: requestedScope;
|
|
1953
|
+
providerResults.push(await verifyProviderDeployment({
|
|
1954
|
+
projectRoot: projectDir,
|
|
1955
|
+
frameworkRoot,
|
|
1956
|
+
provider,
|
|
1957
|
+
scope: effectiveScope,
|
|
1958
|
+
requestedBundles: [requestedBundle],
|
|
1959
|
+
contextOptOut,
|
|
1960
|
+
invocationStartedAt: dryRun ? undefined : startedAt,
|
|
1961
|
+
deploymentExitCode: coreResult.exitCode,
|
|
1962
|
+
deploymentMessage: coreResult.message,
|
|
1963
|
+
}));
|
|
1964
|
+
}
|
|
1965
|
+
result = aggregateUseDeploymentResult({
|
|
1966
|
+
projectRoot: projectDir,
|
|
1967
|
+
frameworkRoot,
|
|
1968
|
+
scope: requestedScope,
|
|
1969
|
+
requestedBundles: [requestedBundle],
|
|
1970
|
+
providers: providerResults,
|
|
1971
|
+
});
|
|
1972
|
+
if (dryRun) {
|
|
1973
|
+
result.dryRun = true;
|
|
1974
|
+
result.exitClassification = 'failure';
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
if (json) {
|
|
1978
|
+
return { exitCode: result.exitCode, message: JSON.stringify(result, null, 2), rawOutput: true };
|
|
1979
|
+
}
|
|
1980
|
+
const verbose = coreArgs.includes('--verbose') || coreArgs.includes('-v');
|
|
1981
|
+
const versionInfo = await getVersionInfo().catch(() => null);
|
|
1982
|
+
const widthFromEnvironment = Number(process.env.COLUMNS);
|
|
1983
|
+
const width = Number.isFinite(process.stdout.columns) && process.stdout.columns > 0
|
|
1984
|
+
? process.stdout.columns
|
|
1985
|
+
: Number.isFinite(widthFromEnvironment) && widthFromEnvironment > 0
|
|
1986
|
+
? widthFromEnvironment
|
|
1987
|
+
: 100;
|
|
1988
|
+
const canonicalProvider = result.providers[0]?.provider ?? 'claude';
|
|
1989
|
+
const rendered = renderUseDeploymentResult(result, {
|
|
1990
|
+
verbose,
|
|
1991
|
+
width,
|
|
1992
|
+
version: versionInfo
|
|
1993
|
+
? { version: versionInfo.version, repository: versionInfo.repoUrl || 'aiwg.io' }
|
|
1994
|
+
: undefined,
|
|
1995
|
+
nextSteps: verbose && result.outcome !== 'failed' && VALID_FRAMEWORKS.includes(requestedBundle)
|
|
1996
|
+
? nextStepsFor(requestedBundle, canonicalProvider)
|
|
1997
|
+
: undefined,
|
|
1998
|
+
});
|
|
1999
|
+
return {
|
|
2000
|
+
exitCode: result.exitCode,
|
|
2001
|
+
message: [coreResult.message, rendered].filter(Boolean).join('\n'),
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
async executeCore(ctx) {
|
|
1824
2005
|
const explicitTarget = firstUsePositional(ctx.args);
|
|
1825
2006
|
if (ctx.args.includes('--workspace-signals')) {
|
|
1826
2007
|
const signalArgs = ctx.args.filter((a) => a !== '--workspace-signals');
|
|
@@ -2062,7 +2243,7 @@ export class UseHandler {
|
|
|
2062
2243
|
const verbose = remainingArgs.includes('--verbose') || remainingArgs.includes('-v');
|
|
2063
2244
|
const force = remainingArgs.includes('--force');
|
|
2064
2245
|
const copyAll = remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills');
|
|
2065
|
-
const quiet = !verbose && !dryRun;
|
|
2246
|
+
const quiet = machineReadableUseDepth > 0 || (!verbose && !dryRun);
|
|
2066
2247
|
ui.blank();
|
|
2067
2248
|
ui.header(` Workspace-aware deployment (${plan.profile})`);
|
|
2068
2249
|
ui.dim(` Included frameworks: ${selectedFrameworks.join(', ') || '(none)'}`);
|
|
@@ -2135,7 +2316,7 @@ export class UseHandler {
|
|
|
2135
2316
|
target,
|
|
2136
2317
|
dryRun,
|
|
2137
2318
|
verbose,
|
|
2138
|
-
quiet: !verbose && !dryRun,
|
|
2319
|
+
quiet: machineReadableUseDepth > 0 || (!verbose && !dryRun),
|
|
2139
2320
|
modelArgs: modelDeployArgs,
|
|
2140
2321
|
});
|
|
2141
2322
|
if (plResult.failed > 0) {
|
|
@@ -2326,13 +2507,19 @@ export class UseHandler {
|
|
|
2326
2507
|
const dryRunAddon = remainingArgs.includes('--dry-run');
|
|
2327
2508
|
const runner = createScriptRunner(frameworkRoot);
|
|
2328
2509
|
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
2510
|
+
// An explicitly selected upstream addon must be self-contained in the
|
|
2511
|
+
// project. Unlike a full framework deploy, its standard skills cannot be
|
|
2512
|
+
// left index-only: the user asked to install this specific bundle and
|
|
2513
|
+
// its supporting scripts must travel with the skill directory.
|
|
2514
|
+
addonBaseArgs.push('--copy-all');
|
|
2329
2515
|
addonBaseArgs.push(...modelDeployArgs);
|
|
2330
2516
|
if (provider)
|
|
2331
2517
|
addonBaseArgs.push('--provider', provider);
|
|
2332
2518
|
if (target)
|
|
2333
2519
|
addonBaseArgs.push('--target', target);
|
|
2334
2520
|
// Forward --copy-all (#1219) so addon-only deploys also honor it.
|
|
2335
|
-
if (remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills'))
|
|
2521
|
+
if ((remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills'))
|
|
2522
|
+
&& !addonBaseArgs.includes('--copy-all')) {
|
|
2336
2523
|
addonBaseArgs.push('--copy-all');
|
|
2337
2524
|
}
|
|
2338
2525
|
if (dryRunAddon)
|
|
@@ -2424,6 +2611,30 @@ export class UseHandler {
|
|
|
2424
2611
|
message: `Failed to register CLI commands: ${error instanceof Error ? error.message : String(error)}`,
|
|
2425
2612
|
};
|
|
2426
2613
|
}
|
|
2614
|
+
// Persist the same lifecycle record frameworks and project-local bundles
|
|
2615
|
+
// receive so status, refresh, doctor, and remove can account for this
|
|
2616
|
+
// upstream addon and every provider artifact it actually deployed.
|
|
2617
|
+
if (!dryRunAddon && config) {
|
|
2618
|
+
try {
|
|
2619
|
+
const manifestPath = path.join(addonSource, 'manifest.json');
|
|
2620
|
+
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
2621
|
+
// Provider rule aggregation may rename many source rules into one
|
|
2622
|
+
// managed index. Record this addon's contributed artifact counts,
|
|
2623
|
+
// matching framework registry semantics, rather than trying to
|
|
2624
|
+
// attribute shared aggregate filenames after deployment.
|
|
2625
|
+
const counts = await countBundleSourceArtifacts(addonSource);
|
|
2626
|
+
const updated = updateInstalled(config, framework, provider, counts, {
|
|
2627
|
+
version: manifest.version ?? (await getVersionInfo()).version,
|
|
2628
|
+
source: 'bundled',
|
|
2629
|
+
manifestHash: await hashManifest(manifestPath),
|
|
2630
|
+
});
|
|
2631
|
+
await writeAiwgConfig(projectDir, updated);
|
|
2632
|
+
config = updated;
|
|
2633
|
+
}
|
|
2634
|
+
catch (error) {
|
|
2635
|
+
ui.warn(`Addon registry update failed for '${framework}': ${error instanceof Error ? error.message : String(error)}`);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2427
2638
|
// Profile picker for addons with memory topology and multiple templates
|
|
2428
2639
|
try {
|
|
2429
2640
|
const profileManifestPath = path.join(addonSource, 'manifest.json');
|
|
@@ -2542,8 +2753,9 @@ export class UseHandler {
|
|
|
2542
2753
|
const filteredArgs = deployArgs.filter(a => a !== '--no-utils' && a !== '--no-project-local' && a !== '--ci-hooks-enabled' && a !== '--force' && a !== '--skip-conflicts' && a !== '--no-harness-agents');
|
|
2543
2754
|
const deployFilteredArgs = removeFlagWithOptionalValue(filteredArgs, '--harness-agents');
|
|
2544
2755
|
// Pass --quiet to suppress deploy-agents.mjs header/footer in default mode (#460)
|
|
2545
|
-
//
|
|
2546
|
-
|
|
2756
|
+
// Human dry-run remains verbose; machine-readable dry-run captures the
|
|
2757
|
+
// preview so stdout stays a single JSON document.
|
|
2758
|
+
if (machineReadableUseDepth > 0 || (!verbose && !dryRun))
|
|
2547
2759
|
deployFilteredArgs.push('--quiet');
|
|
2548
2760
|
// Extract provider and target from remainingArgs to pass to addon deployments
|
|
2549
2761
|
// Config-first resolution (#621): explicit --provider overrides config, config overrides default 'claude'
|
|
@@ -2583,6 +2795,9 @@ export class UseHandler {
|
|
|
2583
2795
|
if (unsupportedMessage) {
|
|
2584
2796
|
return { exitCode: 1, message: unsupportedMessage };
|
|
2585
2797
|
}
|
|
2798
|
+
if (requestedProvider.trim().toLowerCase() === 'windsurf') {
|
|
2799
|
+
ui.warn("Provider id 'windsurf' is deprecated; use '--provider devin' for Devin Desktop. Existing .windsurf/ output paths remain supported.");
|
|
2800
|
+
}
|
|
2586
2801
|
const provider = builtInProviderResolution.provider;
|
|
2587
2802
|
const providerDeployArgs = builtInProviderResolution.requestedProvider
|
|
2588
2803
|
? withProviderOverride(deployFilteredArgs, provider)
|
|
@@ -2645,14 +2860,15 @@ export class UseHandler {
|
|
|
2645
2860
|
}
|
|
2646
2861
|
}
|
|
2647
2862
|
// Deploy main framework
|
|
2648
|
-
const quiet = !verbose && !dryRun;
|
|
2863
|
+
const quiet = machineReadableUseDepth > 0 || (!verbose && !dryRun);
|
|
2649
2864
|
const captureOpts = quiet ? { capture: true } : {};
|
|
2650
2865
|
if (quiet) {
|
|
2651
2866
|
const installLabel = framework === 'all'
|
|
2652
2867
|
? 'Installing complete AIWG surface'
|
|
2653
2868
|
: `Installing ${framework} framework`;
|
|
2869
|
+
const providerLabel = getProviderDefinition(provider)?.displayName ?? provider;
|
|
2654
2870
|
ui.blank();
|
|
2655
|
-
console.log(` ${ui.brandMark()} ${ui.bold(installLabel)} ${ui.dimText(`for ${
|
|
2871
|
+
console.log(` ${ui.brandMark()} ${ui.bold(installLabel)} ${ui.dimText(`for ${providerLabel}`)}`);
|
|
2656
2872
|
ui.blank();
|
|
2657
2873
|
}
|
|
2658
2874
|
const runner = createScriptRunner(ctx.frameworkRoot);
|
|
@@ -2886,6 +3102,7 @@ export class UseHandler {
|
|
|
2886
3102
|
behaviorsPath: paths.behaviors,
|
|
2887
3103
|
provider,
|
|
2888
3104
|
cwd: target,
|
|
3105
|
+
quiet: !verbose,
|
|
2889
3106
|
});
|
|
2890
3107
|
if (verbose)
|
|
2891
3108
|
console.log('Extension registration complete');
|
|
@@ -2905,7 +3122,6 @@ export class UseHandler {
|
|
|
2905
3122
|
// (e.g., test fixtures, deploy from npm install rather than the
|
|
2906
3123
|
// source repo). buildIndex() calls `process.exit(1)` on missing
|
|
2907
3124
|
// scan dirs which would short-circuit our catch.
|
|
2908
|
-
let discoverableSkillCount = null;
|
|
2909
3125
|
if (!dryRun) {
|
|
2910
3126
|
// Build the framework graph against $AIWG_ROOT, not the project's
|
|
2911
3127
|
// target dir (#1217). The framework source is user-global at
|
|
@@ -2937,9 +3153,8 @@ export class UseHandler {
|
|
|
2937
3153
|
// regardless of build cwd.
|
|
2938
3154
|
await buildIndex(aiwgRootForIndex, { graph: 'framework', explicit: false });
|
|
2939
3155
|
console.log = origLog;
|
|
2940
|
-
discoverableSkillCount = await countDiscoverableSkills(aiwgRootForIndex);
|
|
2941
3156
|
const indexElapsedSec = ((Date.now() - indexStart) / 1000).toFixed(1);
|
|
2942
|
-
ui.success(`Capability index ready (${indexElapsedSec}s)
|
|
3157
|
+
ui.success(`Capability index ready (${indexElapsedSec}s).`);
|
|
2943
3158
|
}
|
|
2944
3159
|
catch (error) {
|
|
2945
3160
|
console.log = origLog;
|
|
@@ -2951,42 +3166,13 @@ export class UseHandler {
|
|
|
2951
3166
|
console.log('Framework source not found; skipping capability index rebuild');
|
|
2952
3167
|
}
|
|
2953
3168
|
}
|
|
2954
|
-
//
|
|
3169
|
+
// Collect deployment counts for registry persistence and the final
|
|
3170
|
+
// orchestrated report. Presentation happens once, after verification, so
|
|
3171
|
+
// users do not see a second competing summary.
|
|
2955
3172
|
let counts = { agents: 0, commands: 0, skills: 0, rules: 0, behaviors: 0 };
|
|
2956
3173
|
if (quiet) {
|
|
2957
|
-
// Count deployed artifacts
|
|
2958
3174
|
const paths = getProviderPaths(provider);
|
|
2959
3175
|
counts = await countDeployedArtifacts(target, paths, provider);
|
|
2960
|
-
if (counts.agents > 0)
|
|
2961
|
-
ui.deployCount('Agents', counts.agents);
|
|
2962
|
-
if (counts.commands > 0)
|
|
2963
|
-
ui.deployCount('Commands', counts.commands);
|
|
2964
|
-
if (counts.skills > 0)
|
|
2965
|
-
ui.deployCount('Skills', counts.skills);
|
|
2966
|
-
if (discoverableSkillCount !== null)
|
|
2967
|
-
ui.deployCount('Discoverable skills', discoverableSkillCount);
|
|
2968
|
-
if (counts.rules > 0)
|
|
2969
|
-
ui.deployCount('Rules', counts.rules);
|
|
2970
|
-
if (counts.behaviors > 0)
|
|
2971
|
-
ui.deployCount('Behaviors', counts.behaviors);
|
|
2972
|
-
ui.blank();
|
|
2973
|
-
printNextSteps(framework, provider);
|
|
2974
|
-
// #1240: warn the operator that the running session can't see the newly
|
|
2975
|
-
// deployed agents until reloaded. Skipping this notice is what produced
|
|
2976
|
-
// the "Agent type 'software-implementer' not found" symptom on a stale
|
|
2977
|
-
// Claude Code session.
|
|
2978
|
-
ui.blank();
|
|
2979
|
-
printSessionReloadNotice(provider);
|
|
2980
|
-
// Append version confirmation line (#719)
|
|
2981
|
-
try {
|
|
2982
|
-
const versionInfo = await getVersionInfo();
|
|
2983
|
-
ui.blank();
|
|
2984
|
-
const repoStamp = versionInfo.repoUrl || 'aiwg.io';
|
|
2985
|
-
ui.dim(` AIWG v${versionInfo.version} — ${repoStamp}`);
|
|
2986
|
-
}
|
|
2987
|
-
catch {
|
|
2988
|
-
// Graceful fallback: omit version line if versionInfo unavailable
|
|
2989
|
-
}
|
|
2990
3176
|
}
|
|
2991
3177
|
// Deploy CI workflow files when --ci-hooks-enabled is set (#661)
|
|
2992
3178
|
if (ciHooksEnabled) {
|