@aiwg/cli 2026.8.8 → 2026.8.11
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/agents/packaged-agent-inventory.js +37 -1
- 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/fortemi-core-sync.js +23 -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 +63 -17
- 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 +272 -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 +61 -7
- 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
|
@@ -44,6 +44,48 @@ export function ensureDir(d, dryRun = false) {
|
|
|
44
44
|
if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true });
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
const PROJECT_ARTIFACT_ENV_KEYS = [
|
|
48
|
+
'AIWG_ARTIFACTS_PATH',
|
|
49
|
+
'AIWG_PROJECT_ARTIFACTS_PATH',
|
|
50
|
+
'AIWG_PROJECT_AIWG_DIR',
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
function expandProjectArtifactPath(value, projectDir) {
|
|
54
|
+
const trimmed = value.trim();
|
|
55
|
+
if (trimmed === '~') return os.homedir();
|
|
56
|
+
if (trimmed.startsWith('~/')) return path.resolve(os.homedir(), trimmed.slice(2));
|
|
57
|
+
return path.isAbsolute(trimmed) ? trimmed : path.resolve(projectDir, trimmed);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function parseProjectArtifactLocation(contents) {
|
|
61
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
62
|
+
let line = rawLine.trim();
|
|
63
|
+
if (!line || line.startsWith('#')) continue;
|
|
64
|
+
if (line.startsWith('export ')) line = line.slice('export '.length).trim();
|
|
65
|
+
const assignment = line.match(/^AIWG_ARTIFACTS_PATH\s*=\s*(.+)$/);
|
|
66
|
+
if (assignment) line = assignment[1].trim();
|
|
67
|
+
if ((line.startsWith('"') && line.endsWith('"')) || (line.startsWith("'") && line.endsWith("'"))) {
|
|
68
|
+
line = line.slice(1, -1);
|
|
69
|
+
}
|
|
70
|
+
return line || null;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Resolve the artifact corpus root used for framework-generated workspace data. */
|
|
76
|
+
export function resolveFrameworkWorkspaceRoot(projectDir, env = process.env) {
|
|
77
|
+
for (const key of PROJECT_ARTIFACT_ENV_KEYS) {
|
|
78
|
+
const value = env[key];
|
|
79
|
+
if (typeof value === 'string' && value.trim()) return expandProjectArtifactPath(value, projectDir);
|
|
80
|
+
}
|
|
81
|
+
const pointer = path.join(projectDir, '.aiwg-location');
|
|
82
|
+
if (fs.existsSync(pointer)) {
|
|
83
|
+
const configured = parseProjectArtifactLocation(fs.readFileSync(pointer, 'utf8'));
|
|
84
|
+
if (configured) return expandProjectArtifactPath(configured, projectDir);
|
|
85
|
+
}
|
|
86
|
+
return path.join(projectDir, '.aiwg');
|
|
87
|
+
}
|
|
88
|
+
|
|
47
89
|
/**
|
|
48
90
|
* List markdown files in a directory (non-recursive)
|
|
49
91
|
*/
|
|
@@ -138,8 +180,11 @@ const MANIFEST_FILENAME = '.aiwg-manifest.json';
|
|
|
138
180
|
*
|
|
139
181
|
* Idempotent — skips if either form of the marker is already present.
|
|
140
182
|
*/
|
|
141
|
-
export function addManagedMarker(content, version, source) {
|
|
183
|
+
export function addManagedMarker(content, version, source, style = 'markdown') {
|
|
142
184
|
if (MANAGED_MARKER_RE.test(content)) return content;
|
|
185
|
+
if (style === 'line-comment') {
|
|
186
|
+
return `# aiwg:managed v${version} ${source}\n${content}`;
|
|
187
|
+
}
|
|
143
188
|
// Frontmatter present → inject as YAML comment after the opening `---\n`.
|
|
144
189
|
if (content.startsWith('---\n')) {
|
|
145
190
|
return content.replace(
|
|
@@ -638,9 +683,18 @@ export function deployFiles(files, destDir, opts, transformFn) {
|
|
|
638
683
|
transformedContent = injectPlatformInContent(transformedContent, platformName);
|
|
639
684
|
}
|
|
640
685
|
|
|
641
|
-
// Add managed marker for
|
|
686
|
+
// Add managed marker for provider artifacts (#749). TOML accepts `#`
|
|
687
|
+
// comments, which lets doctor attribute transformed Codex agents even
|
|
688
|
+
// though their YAML frontmatter is removed during serialization.
|
|
642
689
|
if (base.endsWith('.md') || base.endsWith('.mdc')) {
|
|
643
690
|
transformedContent = addManagedMarker(transformedContent, deployVersion, deploySource);
|
|
691
|
+
} else if (base.endsWith('.toml')) {
|
|
692
|
+
transformedContent = addManagedMarker(
|
|
693
|
+
transformedContent,
|
|
694
|
+
deployVersion,
|
|
695
|
+
deploySource,
|
|
696
|
+
'line-comment',
|
|
697
|
+
);
|
|
644
698
|
}
|
|
645
699
|
|
|
646
700
|
// Compute content hash for sidecar comparison
|
|
@@ -1441,7 +1495,7 @@ export function deploySkillDir(skillDir, destDir, opts) {
|
|
|
1441
1495
|
* Creates .aiwg/frameworks/{framework-id}/ directories
|
|
1442
1496
|
*/
|
|
1443
1497
|
export function initializeFrameworkWorkspace(target, mode, dryRun, srcRoot = null) {
|
|
1444
|
-
const aiwgBase =
|
|
1498
|
+
const aiwgBase = resolveFrameworkWorkspaceRoot(target);
|
|
1445
1499
|
const frameworksDir = path.join(aiwgBase, 'frameworks');
|
|
1446
1500
|
const sharedDir = path.join(aiwgBase, 'shared');
|
|
1447
1501
|
|
|
@@ -1498,7 +1552,7 @@ export function initializeFrameworkWorkspace(target, mode, dryRun, srcRoot = nul
|
|
|
1498
1552
|
}
|
|
1499
1553
|
for (const entry of fw.memoryCreates || []) {
|
|
1500
1554
|
if (entry && typeof entry.path === 'string') {
|
|
1501
|
-
console.log(`[dry-run] ${path.join(
|
|
1555
|
+
console.log(`[dry-run] ${path.join(aiwgBase, entry.path.slice('.aiwg/'.length))}${entry.path.endsWith('/') ? '/' : ''}`);
|
|
1502
1556
|
}
|
|
1503
1557
|
}
|
|
1504
1558
|
}
|
|
@@ -1515,7 +1569,7 @@ export function initializeFrameworkWorkspace(target, mode, dryRun, srcRoot = nul
|
|
|
1515
1569
|
for (const subdir of fw.subdirs) {
|
|
1516
1570
|
ensureDir(path.join(fwBase, subdir));
|
|
1517
1571
|
}
|
|
1518
|
-
initializeMemoryCreates(
|
|
1572
|
+
initializeMemoryCreates(aiwgBase, fw.path, fw.memoryCreates);
|
|
1519
1573
|
}
|
|
1520
1574
|
|
|
1521
1575
|
// Initialize registry.json if it doesn't exist
|
|
@@ -1536,12 +1590,12 @@ export function initializeFrameworkWorkspace(target, mode, dryRun, srcRoot = nul
|
|
|
1536
1590
|
}
|
|
1537
1591
|
|
|
1538
1592
|
|
|
1539
|
-
function initializeMemoryCreates(
|
|
1593
|
+
function initializeMemoryCreates(aiwgBase, frameworkPath, creates) {
|
|
1540
1594
|
for (const entry of creates || []) {
|
|
1541
1595
|
if (!entry || typeof entry.path !== 'string') continue;
|
|
1542
1596
|
if (!entry.path.startsWith('.aiwg/')) continue;
|
|
1543
1597
|
|
|
1544
|
-
const targetPath = path.join(
|
|
1598
|
+
const targetPath = path.join(aiwgBase, entry.path.slice('.aiwg/'.length));
|
|
1545
1599
|
const isDirectory = entry.path.endsWith('/') || path.extname(entry.path) === '';
|
|
1546
1600
|
if (isDirectory) {
|
|
1547
1601
|
ensureDir(targetPath);
|
|
@@ -209,10 +209,13 @@ function deploySkills(skillDirs, opts) {
|
|
|
209
209
|
? skillDirs
|
|
210
210
|
: skillDirs.filter(d => isKernelSkill(d));
|
|
211
211
|
if (crossAgentSkills.length > 0) {
|
|
212
|
-
|
|
212
|
+
// Honor the deployment target selected by `aiwg use --target`. Provider
|
|
213
|
+
// subprocesses execute from AIWG_ROOT so process.cwd() would otherwise
|
|
214
|
+
// mutate the framework checkout during isolated/project-targeted deploys.
|
|
215
|
+
const crossAgentDir = path.join(opts.target || process.cwd(), '.agents', 'skills');
|
|
213
216
|
ensureDir(crossAgentDir, opts.dryRun);
|
|
214
217
|
if (!opts.dryRun) {
|
|
215
|
-
console.log(`Deploying cross-agent skills to ${path.relative(process.cwd(), crossAgentDir)}...`);
|
|
218
|
+
console.log(`Deploying cross-agent skills to ${path.relative(opts.target || process.cwd(), crossAgentDir)}...`);
|
|
216
219
|
} else {
|
|
217
220
|
console.log(`[dry-run] Would deploy cross-agent skills to .agents/skills/`);
|
|
218
221
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Devin Desktop Provider (Windsurf compatibility adapter)
|
|
3
3
|
*
|
|
4
|
-
* Deploys agents to
|
|
4
|
+
* Deploys agents to the Devin Desktop/Windsurf compatibility surface with
|
|
5
|
+
* aggregated AGENTS.md and trigger-frontmatter rules. The provider id and
|
|
6
|
+
* generated `.windsurf/` paths remain stable for backward compatibility.
|
|
5
7
|
*
|
|
6
8
|
* Deployment paths:
|
|
7
9
|
* - Output: AGENTS.md (aggregated agents)
|
|
@@ -18,7 +20,7 @@
|
|
|
18
20
|
* - Capabilities tags for tools
|
|
19
21
|
* - Workflow format for commands
|
|
20
22
|
* - Conventional skills and rules deployment
|
|
21
|
-
* -
|
|
23
|
+
* - Devin Desktop selectors resolve to the stable `windsurf` provider id
|
|
22
24
|
*/
|
|
23
25
|
|
|
24
26
|
import realFs from 'fs';
|
|
@@ -57,7 +59,7 @@ import {
|
|
|
57
59
|
// ============================================================================
|
|
58
60
|
|
|
59
61
|
export const name = 'windsurf';
|
|
60
|
-
export const aliases = [];
|
|
62
|
+
export const aliases = ['devin', 'devin-desktop', 'devin-local', 'cascade'];
|
|
61
63
|
|
|
62
64
|
export const paths = {
|
|
63
65
|
agents: '.windsurf/agents/', // Discrete mirrors alongside AGENTS.md
|
|
@@ -85,17 +87,6 @@ export const capabilities = {
|
|
|
85
87
|
yamlFormat: false
|
|
86
88
|
};
|
|
87
89
|
|
|
88
|
-
// ============================================================================
|
|
89
|
-
// Warning Display
|
|
90
|
-
// ============================================================================
|
|
91
|
-
|
|
92
|
-
function displayWarning() {
|
|
93
|
-
console.log('\n' + '='.repeat(70));
|
|
94
|
-
console.log('[EXPERIMENTAL] Windsurf provider support is experimental and untested.');
|
|
95
|
-
console.log('Please report issues: https://github.com/jmagly/aiwg/issues');
|
|
96
|
-
console.log('='.repeat(70) + '\n');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
90
|
// ============================================================================
|
|
100
91
|
// Content Transformation
|
|
101
92
|
// ============================================================================
|
|
@@ -253,12 +244,12 @@ export function generateAgentsMd(files, destPath, opts) {
|
|
|
253
244
|
// refuses to replace the legacy 2MB+ aggregate writer's output.
|
|
254
245
|
lines.push('<!-- aiwg-managed -->');
|
|
255
246
|
lines.push('');
|
|
256
|
-
lines.push('> AIWG Agent Directory for
|
|
247
|
+
lines.push('> AIWG Agent Directory for Devin Desktop');
|
|
257
248
|
lines.push('');
|
|
258
249
|
lines.push('<!--');
|
|
259
|
-
lines.push('
|
|
260
|
-
lines.push('
|
|
261
|
-
lines.push(' See: https://docs.
|
|
250
|
+
lines.push(' Generated by AIWG for Devin Desktop using the Windsurf compatibility adapter.');
|
|
251
|
+
lines.push(' Devin Desktop reads this file for directory-scoped AI instructions.');
|
|
252
|
+
lines.push(' See: https://docs.devin.ai/onboard-devin/agents-md');
|
|
262
253
|
lines.push('-->');
|
|
263
254
|
lines.push('');
|
|
264
255
|
lines.push('## Table of Contents');
|
|
@@ -316,10 +307,10 @@ export function generateWindsurfRules(srcRoot, target, opts) {
|
|
|
316
307
|
lines.push('trigger: always_on');
|
|
317
308
|
lines.push('---');
|
|
318
309
|
lines.push('');
|
|
319
|
-
lines.push('# AIWG Orchestration for
|
|
310
|
+
lines.push('# AIWG Orchestration for Devin Desktop');
|
|
320
311
|
lines.push('');
|
|
321
312
|
lines.push('<!--');
|
|
322
|
-
lines.push('
|
|
313
|
+
lines.push(' Generated by AIWG for Devin Desktop using the Windsurf compatibility adapter.');
|
|
323
314
|
lines.push(' This file provides orchestration context for AIWG SDLC workflows.');
|
|
324
315
|
lines.push(' trigger: always_on — included in system prompt on every message.');
|
|
325
316
|
lines.push('-->');
|
|
@@ -556,9 +547,7 @@ export async function deploy(opts) {
|
|
|
556
547
|
dryRun
|
|
557
548
|
} = opts;
|
|
558
549
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
console.log(`\n=== Windsurf Provider (EXPERIMENTAL) ===`);
|
|
550
|
+
console.log(`\n=== Devin Desktop Provider (windsurf compatibility adapter) ===`);
|
|
562
551
|
console.log(`Target: ${target}`);
|
|
563
552
|
console.log(`Mode: ${mode}`);
|
|
564
553
|
const normalizedMode = normalizeDeploymentMode(mode);
|
|
@@ -417,6 +417,17 @@ function isFullAiwgSourceRoot(srcRoot) {
|
|
|
417
417
|
const repoRoot = path.resolve(scriptDir, '..', '..');
|
|
418
418
|
const srcRoot = source || repoRoot;
|
|
419
419
|
const fullAiwgSourceRoot = isFullAiwgSourceRoot(srcRoot);
|
|
420
|
+
const copyStandardSkills = cfg.copyStandardSkills === true;
|
|
421
|
+
// Component-scoped deploys (the way `aiwg use all` installs selected
|
|
422
|
+
// frameworks/addons) still need a complete inventory for stale-skill
|
|
423
|
+
// reconciliation. AIWG_ROOT is supplied by the orchestrator for exactly
|
|
424
|
+
// this purpose; fall back to the script checkout for standalone use.
|
|
425
|
+
const configuredAiwgRoot = process.env.AIWG_ROOT
|
|
426
|
+
? path.resolve(process.env.AIWG_ROOT)
|
|
427
|
+
: repoRoot;
|
|
428
|
+
const inventoryRoot = fullAiwgSourceRoot
|
|
429
|
+
? srcRoot
|
|
430
|
+
: (!copyStandardSkills && isFullAiwgSourceRoot(configuredAiwgRoot) ? configuredAiwgRoot : null);
|
|
420
431
|
|
|
421
432
|
console.log(`Deploying skills to Codex`);
|
|
422
433
|
console.log(` Source: ${srcRoot}`);
|
|
@@ -440,8 +451,6 @@ function isFullAiwgSourceRoot(srcRoot) {
|
|
|
440
451
|
// Codex normally deploys to the project `.agents/skills/` target, so the
|
|
441
452
|
// kernel/standard split is enforced at filter time rather than via separate
|
|
442
453
|
// destination directories. The standalone legacy default remains supported.
|
|
443
|
-
const copyStandardSkills = cfg.copyStandardSkills === true;
|
|
444
|
-
|
|
445
454
|
// Track every AIWG-managed source skill name so we can scope post-deploy
|
|
446
455
|
// cleanup to skills AIWG ships — never delete user-authored or
|
|
447
456
|
// third-party skills sitting alongside.
|
|
@@ -457,10 +466,13 @@ function isFullAiwgSourceRoot(srcRoot) {
|
|
|
457
466
|
// so full-root cleanup can remove stale AIWG skills. Component-scoped
|
|
458
467
|
// cleanup is limited below to names owned by that component, preserving
|
|
459
468
|
// user-authored skills alongside the generated set.
|
|
460
|
-
for (const { dir } of getSkillDirectories(srcRoot, 'all')) {
|
|
469
|
+
for (const { dir } of getSkillDirectories(inventoryRoot || srcRoot, 'all')) {
|
|
461
470
|
const allSkills = findSkillDirs(dir);
|
|
462
471
|
for (const s of allSkills) {
|
|
463
472
|
allManagedNames.add(path.basename(s));
|
|
473
|
+
if (!copyStandardSkills && isKernelSkill(s)) {
|
|
474
|
+
desiredNames.add(path.basename(s));
|
|
475
|
+
}
|
|
464
476
|
// Also record the frontmatter `name:` since Codex uses that as the
|
|
465
477
|
// target dir. Best-effort — ignore parse errors.
|
|
466
478
|
try {
|
|
@@ -469,7 +481,11 @@ function isFullAiwgSourceRoot(srcRoot) {
|
|
|
469
481
|
if (fmMatch) {
|
|
470
482
|
const nameMatch = fmMatch[1].match(/^\s*name:\s*(.+?)\s*$/m);
|
|
471
483
|
if (nameMatch) {
|
|
472
|
-
|
|
484
|
+
const deployedName = stripWrappingQuotes(nameMatch[1]);
|
|
485
|
+
allManagedNames.add(deployedName);
|
|
486
|
+
if (!copyStandardSkills && isKernelSkill(s)) {
|
|
487
|
+
desiredNames.add(deployedName);
|
|
488
|
+
}
|
|
473
489
|
}
|
|
474
490
|
}
|
|
475
491
|
} catch { /* ignore */ }
|
|
@@ -528,7 +544,7 @@ function isFullAiwgSourceRoot(srcRoot) {
|
|
|
528
544
|
// the .aiwg-managed marker. Treat only the exact historical names as
|
|
529
545
|
// managed so malformed legacy frontmatter cannot survive an upgrade.
|
|
530
546
|
let isAiwgManaged = allManagedNames.has(name) || LEGACY_RENAMED_SKILLS.has(name);
|
|
531
|
-
if (!isAiwgManaged && fullAiwgSourceRoot) {
|
|
547
|
+
if (!isAiwgManaged && (fullAiwgSourceRoot || inventoryRoot)) {
|
|
532
548
|
// Check for the .aiwg-managed marker file (preferred — survives
|
|
533
549
|
// frontmatter transforms) or fall back to namespace check.
|
|
534
550
|
const markerFile = path.join(target, name, '.aiwg-managed');
|