@aiwg/cli 2026.8.0 → 2026.8.2

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.
Files changed (70) hide show
  1. package/README.md +33 -0
  2. package/agentic/code/providers/capability-matrix.yaml +511 -0
  3. package/agentic/code/providers/model-capabilities.v1.json +120 -0
  4. package/agentic/code/providers/model-catalog.v1.json +96 -0
  5. package/agentic/code/providers/model-policy-evaluations.v1.json +50 -0
  6. package/agentic/code/providers/premium-model-allowlist.v1.json +36 -0
  7. package/bin/aiwg.mjs +14 -10
  8. package/dist/src/api/index.d.ts +1 -0
  9. package/dist/src/api/index.js +1 -0
  10. package/dist/src/artifacts/cli.js +2 -0
  11. package/dist/src/artifacts/types.js +4 -0
  12. package/dist/src/auth/client.js +209 -0
  13. package/dist/src/auth/config.js +38 -0
  14. package/dist/src/auth/credential-store.js +141 -0
  15. package/dist/src/auth/resource-credentials.js +25 -0
  16. package/dist/src/auth/types.js +2 -0
  17. package/dist/src/channel/manager.mjs +5 -5
  18. package/dist/src/cli/handlers/auth.js +125 -0
  19. package/dist/src/cli/handlers/help.js +1 -0
  20. package/dist/src/cli/handlers/index.js +3 -1
  21. package/dist/src/cli/handlers/install.js +42 -4
  22. package/dist/src/cli/handlers/marketplace.js +375 -122
  23. package/dist/src/cli/handlers/resource-versions.js +2 -0
  24. package/dist/src/cli/handlers/sessions.js +23 -5
  25. package/dist/src/cli/handlers/subcommands.js +10 -1
  26. package/dist/src/cli/handlers/use.js +342 -43
  27. package/dist/src/config/gitignore.js +1 -0
  28. package/dist/src/extensions/commands/definitions.js +19 -0
  29. package/dist/src/marketplace/exchange.js +602 -0
  30. package/dist/src/marketplace/provenance-types.js +19 -0
  31. package/dist/src/marketplace/provenance.js +834 -0
  32. package/dist/src/memory/canonical-context.js +342 -0
  33. package/dist/src/memory/context-pack.js +282 -0
  34. package/dist/src/memory/index.js +4 -0
  35. package/dist/src/memory/intake.js +118 -0
  36. package/dist/src/packages/adapters/git.js +79 -29
  37. package/dist/src/packages/package-discovery.js +81 -0
  38. package/dist/src/packages/package-registry.js +2 -0
  39. package/dist/src/packages/registry.js +119 -20
  40. package/dist/src/resources/resolver.js +1 -0
  41. package/dist/src/resources/web-release.d.ts +3 -1
  42. package/dist/src/resources/web-release.js +14 -6
  43. package/dist/src/serve/agentic-sandbox-fleet-client.js +213 -0
  44. package/dist/src/serve/fleet-mission-conductor.js +293 -0
  45. package/dist/src/sessions/index.js +1 -0
  46. package/dist/src/sessions/output-registration.js +338 -0
  47. package/dist/src/sessions/promotion.js +73 -2
  48. package/dist/src/sessions/repository.js +2 -1
  49. package/dist/src/update/notifier.mjs +13 -2
  50. package/package.json +8 -1
  51. package/tools/_resolve-impl.mjs +74 -0
  52. package/tools/agents/deploy-agents.mjs +962 -0
  53. package/tools/agents/providers/base.mjs +2954 -0
  54. package/tools/agents/providers/claude.mjs +711 -0
  55. package/tools/agents/providers/codex.mjs +699 -0
  56. package/tools/agents/providers/copilot.mjs +659 -0
  57. package/tools/agents/providers/cursor.mjs +714 -0
  58. package/tools/agents/providers/factory.mjs +1130 -0
  59. package/tools/agents/providers/hermes.mjs +663 -0
  60. package/tools/agents/providers/hook-capabilities.mjs +85 -0
  61. package/tools/agents/providers/model-role.mjs +56 -0
  62. package/tools/agents/providers/openclaw-translator.mjs +348 -0
  63. package/tools/agents/providers/openclaw.mjs +680 -0
  64. package/tools/agents/providers/opencode.mjs +675 -0
  65. package/tools/agents/providers/openhuman.mjs +292 -0
  66. package/tools/agents/providers/warp.mjs +413 -0
  67. package/tools/agents/providers/windsurf.mjs +748 -0
  68. package/tools/commands/deploy-prompts-codex.mjs +336 -0
  69. package/tools/plugin/package-plugins.mjs +1013 -0
  70. package/tools/skills/deploy-skills-codex.mjs +571 -0
@@ -0,0 +1,292 @@
1
+ /**
2
+ * OpenHuman provider (tinyhumansai/openhuman) — Tier-1 deployment.
3
+ *
4
+ * OpenHuman is an OSS personal-AI runtime (Rust core + React/Tauri shell).
5
+ * This module wires AIWG into OpenHuman's user-global app roots:
6
+ *
7
+ * - agents -> no markdown persona deploy; OpenHuman native custom agents
8
+ * are TOML-only under ~/.openhuman/agents (Tier-2, #1559)
9
+ * - skills -> kernel: ~/.openhuman/skills/ (native user-scope scan root;
10
+ * visible in the OpenHuman Skills UI)
11
+ * standard: AIWG index/discovery only
12
+ * - commands -> no native command directory; command-skills deploy as skills
13
+ * - rules -> full bodies under ~/.openhuman/.aiwg/rules/ for `aiwg show`
14
+ *
15
+ * Decisions: ADR `.aiwg/architecture/adr-openhuman-agent-target.md`.
16
+ * Epic #1552 · this module: #1555.
17
+ */
18
+
19
+ import path from 'path';
20
+ import os from 'os';
21
+ import {
22
+ ensureDir,
23
+ deployFiles,
24
+ deploySkillsWithKernelRouting,
25
+ createAgentsMdFromTemplate,
26
+ getAddonAgentFiles,
27
+ getAddonCommandFiles,
28
+ getAddonSkillDirs,
29
+ getAddonRuleFiles,
30
+ collectFrameworkArtifacts,
31
+ normalizeDeploymentMode,
32
+ cleanupOldRuleFiles,
33
+ filterCommandsAgainstSkills,
34
+ resolveAiwgRoot,
35
+ } from './base.mjs';
36
+
37
+ // ============================================================================
38
+ // Provider Configuration
39
+ // ============================================================================
40
+
41
+ export const name = 'openhuman';
42
+ export const aliases = [];
43
+
44
+ export const paths = {
45
+ // OpenHuman's native custom-agent surface is TOML-only under
46
+ // ~/.openhuman/agents. Markdown personas are not a project-level OpenHuman
47
+ // install target.
48
+ agents: '',
49
+ // OpenHuman has no native command surface. Empty path => no discrete command
50
+ // files; command-skills are reachable only through the kernel skill copy or
51
+ // AIWG index/discovery.
52
+ commands: '',
53
+ // Standard (non-kernel) skills are not copied by default. `--copy-all`
54
+ // explicitly opts into this user-scoped mirror for offline/discovery use.
55
+ skills: path.join(os.homedir(), '.openhuman', '.aiwg', 'skills'),
56
+ // Full rule bodies for `aiwg show rule`.
57
+ rules: path.join(os.homedir(), '.openhuman', '.aiwg', 'rules'),
58
+ };
59
+
60
+ // OpenHuman's native user-scope scan root for kernel skills.
61
+ export const kernelSkillsPath = path.join(os.homedir(), '.openhuman', 'skills');
62
+
63
+ export const support = {
64
+ agents: 'none', // Native TOML harness agents are emitted by the CLI
65
+ commands: 'none',
66
+ skills: 'native', // .openhuman/skills/ natively scanned
67
+ rules: 'indexed', // `aiwg show rule`
68
+ };
69
+
70
+ export const capabilities = {
71
+ skills: true,
72
+ rules: true,
73
+ aggregatedOutput: false,
74
+ yamlFormat: false,
75
+ homeDirectoryDeploy: true,
76
+ };
77
+
78
+ // ============================================================================
79
+ // Model Mapping
80
+ // ============================================================================
81
+
82
+ /**
83
+ * OpenHuman uses its own model namespace (neocortex-*, router hints
84
+ * reasoning/coding/agentic/local). AIWG `sonnet/opus/haiku` do not map cleanly.
85
+ * Markdown personas are not deployed for OpenHuman; native harness agents
86
+ * inherit the parent model (ModelSpec::Inherit) when `[model]` is omitted.
87
+ * See ADR adr-openhuman-agent-target.
88
+ */
89
+ export function mapModel(originalModel) {
90
+ return originalModel;
91
+ }
92
+
93
+ // ============================================================================
94
+ // Content Transformation
95
+ // ============================================================================
96
+
97
+ /** Markdown personas are not a supported OpenHuman install target. */
98
+ export function transformAgent(srcPath, content) {
99
+ return content;
100
+ }
101
+
102
+ export function transformCommand(srcPath, content) {
103
+ return content;
104
+ }
105
+
106
+ export function transformSkillFrontmatter(content) {
107
+ if (!content.startsWith('---\n')) return content;
108
+ const end = content.indexOf('\n---', 4);
109
+ if (end < 0) return content;
110
+
111
+ let fm = content.slice(4, end);
112
+ const body = content.slice(end);
113
+
114
+ // OpenHuman currently classifies any SKILL.md with non-empty `platforms` as
115
+ // Hermes format. AIWG deploys directly into OpenHuman's user-global scan root,
116
+ // so the platform hint is not needed in the deployed copy and would mislabel
117
+ // the UI badge.
118
+ fm = fm
119
+ .replace(/^platforms:\s*\[[^\]]*\]\n?/m, '')
120
+ .replace(/^platforms:\s*\n(?:[ \t]+-[ \t]+\S[^\n]*\n?)*/m, '');
121
+
122
+ return `---\n${fm.trimEnd()}\n${body}`;
123
+ }
124
+
125
+ // ============================================================================
126
+ // Deployment
127
+ // ============================================================================
128
+
129
+ export function deployAgents(agentFiles, targetDir, opts) {
130
+ return 0;
131
+ }
132
+
133
+ export function deployCommands(commandFiles, targetDir, opts) {
134
+ return 0;
135
+ }
136
+
137
+ /**
138
+ * Kernel-vs-standard skill routing (#1212/#1216):
139
+ * - kernel → ~/.openhuman/skills/ (native UI scan root)
140
+ * - standard → not copied by default (AIWG index/discovery)
141
+ * → ~/.openhuman/.aiwg/skills/ with explicit --copy-all
142
+ */
143
+ export function deploySkills(skillDirs, targetDir, opts) {
144
+ const standardDestDir = path.isAbsolute(paths.skills)
145
+ ? paths.skills
146
+ : path.join(targetDir, paths.skills);
147
+ const kernelDestDir = path.isAbsolute(kernelSkillsPath)
148
+ ? kernelSkillsPath
149
+ : path.join(targetDir, kernelSkillsPath);
150
+ return deploySkillsWithKernelRouting(skillDirs, standardDestDir, kernelDestDir, {
151
+ ...opts,
152
+ copyStandardSkills: opts.copyStandardSkills === true,
153
+ transformSkillMd: transformSkillFrontmatter,
154
+ });
155
+ }
156
+
157
+ export function deployRules(ruleFiles, targetDir, opts) {
158
+ const destDir = path.isAbsolute(paths.rules)
159
+ ? paths.rules
160
+ : path.join(targetDir, paths.rules);
161
+ ensureDir(destDir, opts.dryRun);
162
+ cleanupOldRuleFiles(destDir, opts);
163
+ return deployFiles(ruleFiles, destDir, opts, transformAgent);
164
+ }
165
+
166
+ export function createAgentsMd(target, srcRoot, dryRun) {
167
+ const aiwgRoot = resolveAiwgRoot(srcRoot) || srcRoot;
168
+ createAgentsMdFromTemplate(target, aiwgRoot, 'openhuman/AGENTS.md.aiwg-template', dryRun);
169
+ }
170
+
171
+ export async function postDeploy(targetDir, opts) {
172
+ if (
173
+ opts.createAgentsMd ||
174
+ (!opts.commandsOnly && !opts.skillsOnly && !opts.rulesOnly)
175
+ ) {
176
+ createAgentsMd(targetDir, opts.srcRoot, opts.dryRun);
177
+ }
178
+ }
179
+
180
+ export function getFileExtension() {
181
+ return '.md';
182
+ }
183
+
184
+ // ============================================================================
185
+ // Main Deploy Function
186
+ // ============================================================================
187
+
188
+ export async function deploy(opts) {
189
+ const {
190
+ srcRoot,
191
+ target,
192
+ mode,
193
+ deployCommands: shouldDeployCommands,
194
+ deploySkills: shouldDeploySkills,
195
+ deployRules: shouldDeployRules,
196
+ commandsOnly,
197
+ skillsOnly,
198
+ rulesOnly,
199
+ } = opts;
200
+
201
+ console.log(`\n=== OpenHuman Provider ===`);
202
+ console.log(`Target: ${target}`);
203
+ console.log(`Mode: ${mode}`);
204
+
205
+ const agentFiles = [];
206
+ const commandFiles = [];
207
+ const ruleFiles = [];
208
+ const skillDirs = [];
209
+ const normalizedMode = normalizeDeploymentMode(mode);
210
+
211
+ // Addon artifacts (dynamically discovered)
212
+ if (['general', 'sdlc', 'both', 'all'].includes(normalizedMode)) {
213
+ agentFiles.push(...getAddonAgentFiles(srcRoot));
214
+ if (shouldDeployCommands || commandsOnly) commandFiles.push(...getAddonCommandFiles(srcRoot));
215
+ if (shouldDeployRules || rulesOnly) ruleFiles.push(...getAddonRuleFiles(srcRoot));
216
+ if (shouldDeploySkills || skillsOnly) skillDirs.push(...getAddonSkillDirs(srcRoot));
217
+ }
218
+
219
+ // Framework artifacts
220
+ const fw = collectFrameworkArtifacts(srcRoot, normalizedMode, {
221
+ includeAgents: true,
222
+ includeCommands: shouldDeployCommands || commandsOnly,
223
+ includeSkills: shouldDeploySkills || skillsOnly,
224
+ includeRules: shouldDeployRules || rulesOnly,
225
+ recursiveCommands: true,
226
+ consolidatedSdlcRules: true,
227
+ });
228
+ agentFiles.push(...fw.agents);
229
+ commandFiles.push(...fw.commands);
230
+ skillDirs.push(...fw.skills);
231
+ ruleFiles.push(...fw.rules);
232
+
233
+ if (!commandsOnly && !skillsOnly && !rulesOnly) {
234
+ console.log(`\nSkipping markdown agents: OpenHuman native agents are TOML-only under ~/.openhuman/agents.`);
235
+ }
236
+
237
+ // Commands take a back seat to skills where they collide.
238
+ const filteredCommands = (shouldDeploySkills || skillsOnly)
239
+ ? filterCommandsAgainstSkills(commandFiles, skillDirs)
240
+ : commandFiles;
241
+
242
+ // No native command directory. Command-skills reach OpenHuman only when they
243
+ // are kernel skills copied to ~/.openhuman/skills; otherwise AIWG discovery
244
+ // finds them on demand.
245
+ if ((shouldDeployCommands || commandsOnly) && paths.commands) {
246
+ console.log(`\nDeploying ${filteredCommands.length} commands...`);
247
+ deployCommands(filteredCommands, target, opts);
248
+ }
249
+
250
+ if (shouldDeploySkills || skillsOnly) {
251
+ console.log(
252
+ `\nDeploying ${skillDirs.length} skills (kernel → ~/.openhuman/skills, standard → ${
253
+ opts.copyStandardSkills ? '~/.openhuman/.aiwg/skills via --copy-all' : 'index/discovery'
254
+ })...`,
255
+ );
256
+ deploySkills(skillDirs, target, opts);
257
+ }
258
+
259
+ if (shouldDeployRules || rulesOnly) {
260
+ console.log(`\nDeploying ${ruleFiles.length} rules for AIWG discovery...`);
261
+ deployRules(ruleFiles, target, opts);
262
+ }
263
+
264
+ await postDeploy(target, opts);
265
+
266
+ console.log('\n=== OpenHuman deployment complete ===\n');
267
+ }
268
+
269
+ // ============================================================================
270
+ // Default Export
271
+ // ============================================================================
272
+
273
+ export default {
274
+ name,
275
+ aliases,
276
+ paths,
277
+ kernelSkillsPath,
278
+ support,
279
+ capabilities,
280
+ transformAgent,
281
+ transformCommand,
282
+ mapModel,
283
+ deployAgents,
284
+ deployCommands,
285
+ deploySkills,
286
+ deployRules,
287
+ createAgentsMd,
288
+ transformSkillFrontmatter,
289
+ postDeploy,
290
+ getFileExtension,
291
+ deploy,
292
+ };
@@ -0,0 +1,413 @@
1
+ /**
2
+ * Warp Terminal Provider
3
+ *
4
+ * Supports both aggregated (WARP.md) and discrete file deployment.
5
+ * Aggregates agents and commands into WARP.md via external script,
6
+ * while also deploying discrete files for all 4 artifact types.
7
+ *
8
+ * Deployment paths:
9
+ * - Agents: WARP.md (aggregated only — Warp does not discover .warp/agents/)
10
+ * - Commands: WARP.md (aggregated only — Warp does not discover .warp/commands/)
11
+ * - Skills: .warp/skills/ (discrete — natively discovered by Warp)
12
+ * - Skills: .agents/skills/ (cross-agent compatibility path)
13
+ * - Rules: WARP.md (aggregated only — Warp does not discover .warp/rules/)
14
+ *
15
+ * Special features:
16
+ * - Aggregated WARP.md for agents, commands, and rules
17
+ * - Discrete .warp/skills/ for natively discovered skills
18
+ * - Section preservation (user vs AIWG managed sections in WARP.md)
19
+ * - Backup creation with timestamp
20
+ * - CLAUDE.md symlink support
21
+ */
22
+
23
+ import realFs from 'fs';
24
+ import { createRequire } from 'module';
25
+ const _require = createRequire(import.meta.url);
26
+ let fs;
27
+ try { const gfs = _require('graceful-fs'); gfs.gracefulify(realFs); fs = realFs; } catch { fs = realFs; }
28
+ import path from 'path';
29
+ import { spawn } from 'child_process';
30
+ import { classifyModelRole, modelForRole } from './model-role.mjs';
31
+ import {
32
+ ensureDir,
33
+ listMdFiles,
34
+ listSkillDirs,
35
+ deploySkillDir,
36
+ deploySkillsWithKernelRouting,
37
+ isKernelSkill,
38
+ pruneStaleAiwgSkills,
39
+ computeAllKernelNames,
40
+ initializeFrameworkWorkspace,
41
+ getAddonAgentFiles,
42
+ getAddonCommandFiles,
43
+ getAddonSkillDirs,
44
+ getAddonRuleFiles,
45
+ normalizeDeploymentMode,
46
+ collectFrameworkArtifacts
47
+ } from './base.mjs';
48
+
49
+ // ============================================================================
50
+ // Provider Configuration
51
+ // ============================================================================
52
+
53
+ export const name = 'warp';
54
+ export const aliases = [];
55
+
56
+ export const paths = {
57
+ agents: '.warp/agents/',
58
+ commands: '.warp/commands/',
59
+ // Skills sequestered under .warp/.aiwg/skills/ — index-driven discovery (#1212).
60
+ skills: '.warp/.aiwg/skills/',
61
+ crossAgentSkills: '.agents/skills/', // Cross-agent compatibility path (#771)
62
+ rules: '.warp/rules/',
63
+ };
64
+
65
+ // Kernel skills (always-loaded) deploy to the platform-native dir.
66
+ export const kernelSkillsPath = '.warp/skills/';
67
+
68
+ export const support = {
69
+ agents: 'aggregated', // WARP.md primary; files mirrored for portability
70
+ commands: 'conventional', // .warp/commands/ mirror for slash-command parity
71
+ skills: 'native', // .warp/skills/ — natively discovered by Warp
72
+ rules: 'aggregated' // WARP.md primary; rule files mirrored for portability
73
+ };
74
+
75
+ export const capabilities = {
76
+ skills: true,
77
+ rules: true,
78
+ aggregatedOutput: true, // All content in single WARP.md file
79
+ yamlFormat: false
80
+ };
81
+
82
+ // ============================================================================
83
+ // Model Handling
84
+ // ============================================================================
85
+
86
+ /**
87
+ * Replace model in frontmatter based on role classification
88
+ * opus -> reasoning, sonnet -> coding, haiku -> efficiency
89
+ */
90
+ export function replaceModelFrontmatter(content, models) {
91
+ const fmStart = content.indexOf('---');
92
+ if (fmStart !== 0) return content;
93
+ const fmEnd = content.indexOf('\n---', 3);
94
+ if (fmEnd === -1) return content;
95
+
96
+ const header = content.slice(0, fmEnd + 4);
97
+ const body = content.slice(fmEnd + 4);
98
+
99
+ const modelMatch = header.match(/^model:\s*([^\n]+)$/m);
100
+ let newModel = null;
101
+
102
+ if (modelMatch) {
103
+ const orig = modelMatch[1].trim();
104
+ const role = classifyModelRole(orig);
105
+
106
+ if (role === 'reasoning') newModel = models.reasoning;
107
+ else if (role === 'efficiency') newModel = models.efficiency;
108
+ else if (role === 'coding') newModel = models.coding;
109
+ }
110
+
111
+ if (!newModel) return content;
112
+ const updatedHeader = header.replace(/^model:\s*[^\n]+$/m, `model: ${newModel}`);
113
+ return updatedHeader + body;
114
+ }
115
+
116
+ /**
117
+ * Map model shorthand to Warp format
118
+ */
119
+ export function mapModel(shorthand, modelCfg, modelsConfig) {
120
+ // If overrides specified, use them
121
+ if (modelCfg.reasoningModel || modelCfg.codingModel || modelCfg.efficiencyModel) {
122
+ return modelForRole(shorthand, {
123
+ reasoning: modelCfg.reasoningModel || 'opus',
124
+ coding: modelCfg.codingModel || 'sonnet',
125
+ efficiency: modelCfg.efficiencyModel || 'haiku',
126
+ }, { defaultRole: 'coding' }) ?? shorthand;
127
+ }
128
+
129
+ return shorthand || 'sonnet';
130
+ }
131
+
132
+ // ============================================================================
133
+ // Content Transformation
134
+ // ============================================================================
135
+
136
+ /**
137
+ * Transform agent content for Warp
138
+ */
139
+ export function transformAgent(srcPath, content, opts) {
140
+ const { reasoningModel, codingModel, efficiencyModel } = opts;
141
+
142
+ // Only transform if model overrides specified
143
+ if (reasoningModel || codingModel || efficiencyModel) {
144
+ const models = {
145
+ reasoning: reasoningModel || 'opus',
146
+ coding: codingModel || 'sonnet',
147
+ efficiency: efficiencyModel || 'haiku'
148
+ };
149
+ return replaceModelFrontmatter(content, models);
150
+ }
151
+
152
+ return content;
153
+ }
154
+
155
+ /**
156
+ * Transform command content for Warp
157
+ */
158
+ export function transformCommand(srcPath, content, opts) {
159
+ return transformAgent(srcPath, content, opts);
160
+ }
161
+
162
+ // ============================================================================
163
+ // Deployment Functions
164
+ // ============================================================================
165
+
166
+ // Warp does not discover .warp/agents/, .warp/commands/, or .warp/rules/.
167
+ // Agents, commands, and rules are delivered exclusively via aggregated WARP.md.
168
+ // Only skills (.warp/skills/) are natively discovered.
169
+
170
+ /**
171
+ * Deploy skills to .warp/skills/ (primary) and .agents/skills/ (cross-agent compatibility).
172
+ * The .agents/skills/ path is an interop convention for projects using multiple AI coding tools.
173
+ */
174
+ export function deploySkills(skillDirs, targetDir, opts) {
175
+ // Primary: kernel-vs-standard routing (#1212/#1216)
176
+ // - kernel skills → .warp/skills/ (platform-native, always-loaded)
177
+ // - standard → .warp/.aiwg/skills/ (index-discoverable)
178
+ const standardDestDir = path.join(targetDir, paths.skills);
179
+ const kernelDestDir = path.join(targetDir, kernelSkillsPath);
180
+ deploySkillsWithKernelRouting(skillDirs, standardDestDir, kernelDestDir, opts);
181
+
182
+ // Cross-agent compatibility: .agents/skills/
183
+ const crossAgentDir = path.join(targetDir, paths.crossAgentSkills);
184
+ ensureDir(crossAgentDir, opts.dryRun);
185
+ if (!opts.dryRun) {
186
+ console.log(`Deploying cross-agent skills to ${path.relative(process.cwd(), crossAgentDir)}...`);
187
+ } else {
188
+ console.log(`[dry-run] Would deploy cross-agent skills to .agents/skills/`);
189
+ }
190
+ for (const skillDir of skillDirs) {
191
+ deploySkillDir(skillDir, crossAgentDir, opts);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Deploy via external setup-warp.mjs script
197
+ * This generates the aggregated WARP.md file
198
+ */
199
+ export async function deployWarp(targetDir, srcRoot, opts) {
200
+ const scriptPath = path.join(srcRoot, 'tools', 'warp', 'setup-warp.mjs');
201
+
202
+ if (!fs.existsSync(scriptPath)) {
203
+ console.warn(`Warp setup script not found at ${scriptPath}`);
204
+ return;
205
+ }
206
+
207
+ console.log('\nGenerating aggregated WARP.md...');
208
+
209
+ return new Promise((resolve, reject) => {
210
+ const args = ['--target', targetDir, '--source', srcRoot];
211
+ if (opts.dryRun) args.push('--dry-run');
212
+ if (opts.force) args.push('--force');
213
+ if (opts.mode) args.push('--mode', opts.mode);
214
+
215
+ const child = spawn('node', [scriptPath, ...args], {
216
+ stdio: 'inherit',
217
+ cwd: srcRoot
218
+ });
219
+
220
+ child.on('close', (code) => {
221
+ if (code === 0) resolve();
222
+ else reject(new Error(`setup-warp.mjs exited with code ${code}`));
223
+ });
224
+
225
+ child.on('error', reject);
226
+ });
227
+ }
228
+
229
+ // ============================================================================
230
+ // AGENTS.md (not used for Warp - content goes in WARP.md)
231
+ // ============================================================================
232
+
233
+ export function createAgentsMd(target, srcRoot, dryRun) {
234
+ console.log('Warp uses WARP.md instead of AGENTS.md');
235
+ }
236
+
237
+ // ============================================================================
238
+ // Post-Deployment
239
+ // ============================================================================
240
+
241
+ export async function postDeploy(targetDir, opts) {
242
+ initializeFrameworkWorkspace(targetDir, opts.mode, opts.dryRun, opts.srcRoot);
243
+ }
244
+
245
+ // ============================================================================
246
+ // File Extension
247
+ // ============================================================================
248
+
249
+ export function getFileExtension(type) {
250
+ return '.md';
251
+ }
252
+
253
+ // ============================================================================
254
+ // Main Deploy Function
255
+ // ============================================================================
256
+
257
+ /**
258
+ * Main deployment function for Warp provider
259
+ * Deploys discrete files for all artifact types, then generates aggregated WARP.md
260
+ */
261
+ export async function deploy(opts) {
262
+ const {
263
+ srcRoot,
264
+ target,
265
+ mode,
266
+ deployCommands: shouldDeployCommands,
267
+ deploySkills: shouldDeploySkills,
268
+ deployRules: shouldDeployRules,
269
+ commandsOnly,
270
+ skillsOnly,
271
+ rulesOnly,
272
+ dryRun
273
+ } = opts;
274
+
275
+ console.log(`\n=== Warp Terminal Provider ===`);
276
+ console.log(`Target: ${target}`);
277
+ console.log(`Mode: ${mode}`);
278
+
279
+ // Collect source files based on mode
280
+ const agentFiles = [];
281
+ const commandFiles = [];
282
+ const skillDirs = [];
283
+ const ruleFiles = [];
284
+
285
+ // Check for addon-style directory structure (direct agents/, commands/, skills/ subdirs)
286
+ // This handles deployment when --source points to an addon directory
287
+ const isAddonSource = fs.existsSync(path.join(srcRoot, 'agents')) ||
288
+ fs.existsSync(path.join(srcRoot, 'commands')) ||
289
+ fs.existsSync(path.join(srcRoot, 'skills'));
290
+
291
+ if (isAddonSource) {
292
+ // Deploy from addon-style directory structure
293
+ const addonAgentsDir = path.join(srcRoot, 'agents');
294
+ if (fs.existsSync(addonAgentsDir)) {
295
+ agentFiles.push(...listMdFiles(addonAgentsDir));
296
+ }
297
+
298
+ if (shouldDeployCommands || commandsOnly) {
299
+ const addonCommandsDir = path.join(srcRoot, 'commands');
300
+ if (fs.existsSync(addonCommandsDir)) {
301
+ commandFiles.push(...listMdFiles(addonCommandsDir));
302
+ }
303
+ }
304
+
305
+ if (shouldDeploySkills || skillsOnly) {
306
+ const addonSkillsDir = path.join(srcRoot, 'skills');
307
+ if (fs.existsSync(addonSkillsDir)) {
308
+ skillDirs.push(...listSkillDirs(addonSkillsDir));
309
+
310
+ // Holistic post-deploy cleanup of stale AIWG-managed kernel
311
+ // skills (renamed/removed sources). Uses the global kernel set
312
+ // (computeAllKernelNames walks all source frameworks/addons),
313
+ // not just this-call's skillDirs, because aiwg use invokes
314
+ // deploy-agents.mjs multiple times.
315
+ {
316
+ const _kernelDestDir = path.isAbsolute(kernelSkillsPath)
317
+ ? kernelSkillsPath
318
+ : path.join(target, kernelSkillsPath);
319
+ pruneStaleAiwgSkills(_kernelDestDir, computeAllKernelNames(srcRoot), opts);
320
+ }
321
+ }
322
+ }
323
+
324
+ if (shouldDeployRules || rulesOnly) {
325
+ const addonRulesDir = path.join(srcRoot, 'rules');
326
+ if (fs.existsSync(addonRulesDir)) {
327
+ ruleFiles.push(...listMdFiles(addonRulesDir));
328
+ }
329
+ }
330
+ }
331
+
332
+ const normalizedMode = normalizeDeploymentMode(mode);
333
+
334
+ // All addons (dynamically discovered)
335
+ if (normalizedMode === 'general' || normalizedMode === 'sdlc' || normalizedMode === 'both' || normalizedMode === 'all') {
336
+ agentFiles.push(...getAddonAgentFiles(srcRoot));
337
+
338
+ if (shouldDeployCommands || commandsOnly) {
339
+ commandFiles.push(...getAddonCommandFiles(srcRoot));
340
+ }
341
+
342
+ if (shouldDeploySkills || skillsOnly) {
343
+ skillDirs.push(...getAddonSkillDirs(srcRoot));
344
+ }
345
+
346
+ if (shouldDeployRules || rulesOnly) {
347
+ ruleFiles.push(...getAddonRuleFiles(srcRoot));
348
+ }
349
+ }
350
+
351
+ const frameworkArtifacts = collectFrameworkArtifacts(srcRoot, normalizedMode, {
352
+ includeAgents: true,
353
+ includeCommands: shouldDeployCommands || commandsOnly,
354
+ includeSkills: shouldDeploySkills || skillsOnly,
355
+ includeRules: shouldDeployRules || rulesOnly,
356
+ recursiveCommands: true,
357
+ consolidatedSdlcRules: true
358
+ });
359
+ agentFiles.push(...frameworkArtifacts.agents);
360
+ commandFiles.push(...frameworkArtifacts.commands);
361
+ skillDirs.push(...frameworkArtifacts.skills);
362
+ ruleFiles.push(...frameworkArtifacts.rules);
363
+
364
+ // Warp only discovers .warp/skills/ natively.
365
+ // Agents, commands, and rules are delivered via aggregated WARP.md only.
366
+ console.log('\n--- Deploying discrete files (skills only) ---');
367
+
368
+ if (shouldDeploySkills || skillsOnly) {
369
+ console.log(`\nDeploying ${skillDirs.length} skills to .warp/skills/...`);
370
+ deploySkills(skillDirs, target, opts);
371
+ }
372
+
373
+ if (!commandsOnly && !skillsOnly && !rulesOnly) {
374
+ console.log(`\nSkipping discrete agent deployment (Warp uses WARP.md)`);
375
+ }
376
+ if (shouldDeployCommands || commandsOnly) {
377
+ console.log(`\nSkipping discrete command deployment (Warp uses WARP.md)`);
378
+ }
379
+ if (shouldDeployRules || rulesOnly) {
380
+ console.log(`\nSkipping discrete rule deployment (Warp uses WARP.md)`);
381
+ }
382
+
383
+ // Generate aggregated WARP.md (existing behavior)
384
+ console.log('\n--- Generating aggregated output ---');
385
+ await deployWarp(target, srcRoot, opts);
386
+
387
+ // Post-deployment
388
+ await postDeploy(target, opts);
389
+
390
+ console.log('\n=== Warp deployment complete ===\n');
391
+ }
392
+
393
+ // ============================================================================
394
+ // Default Export
395
+ // ============================================================================
396
+
397
+ export default {
398
+ name,
399
+ aliases,
400
+ paths,
401
+ kernelSkillsPath,
402
+ support,
403
+ capabilities,
404
+ transformAgent,
405
+ transformCommand,
406
+ mapModel,
407
+ deploySkills,
408
+ deployWarp,
409
+ createAgentsMd,
410
+ postDeploy,
411
+ getFileExtension,
412
+ deploy
413
+ };