@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.
- package/README.md +33 -0
- package/agentic/code/providers/capability-matrix.yaml +511 -0
- package/agentic/code/providers/model-capabilities.v1.json +120 -0
- package/agentic/code/providers/model-catalog.v1.json +96 -0
- package/agentic/code/providers/model-policy-evaluations.v1.json +50 -0
- package/agentic/code/providers/premium-model-allowlist.v1.json +36 -0
- package/bin/aiwg.mjs +14 -10
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/artifacts/cli.js +2 -0
- package/dist/src/artifacts/types.js +4 -0
- package/dist/src/auth/client.js +209 -0
- package/dist/src/auth/config.js +38 -0
- package/dist/src/auth/credential-store.js +141 -0
- package/dist/src/auth/resource-credentials.js +25 -0
- package/dist/src/auth/types.js +2 -0
- package/dist/src/channel/manager.mjs +5 -5
- package/dist/src/cli/handlers/auth.js +125 -0
- package/dist/src/cli/handlers/help.js +1 -0
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/install.js +42 -4
- package/dist/src/cli/handlers/marketplace.js +375 -122
- package/dist/src/cli/handlers/resource-versions.js +2 -0
- package/dist/src/cli/handlers/sessions.js +23 -5
- package/dist/src/cli/handlers/subcommands.js +10 -1
- package/dist/src/cli/handlers/use.js +342 -43
- package/dist/src/config/gitignore.js +1 -0
- package/dist/src/extensions/commands/definitions.js +19 -0
- package/dist/src/marketplace/exchange.js +602 -0
- package/dist/src/marketplace/provenance-types.js +19 -0
- package/dist/src/marketplace/provenance.js +834 -0
- package/dist/src/memory/canonical-context.js +342 -0
- package/dist/src/memory/context-pack.js +282 -0
- package/dist/src/memory/index.js +4 -0
- package/dist/src/memory/intake.js +118 -0
- package/dist/src/packages/adapters/git.js +79 -29
- package/dist/src/packages/package-discovery.js +81 -0
- package/dist/src/packages/package-registry.js +2 -0
- package/dist/src/packages/registry.js +119 -20
- package/dist/src/resources/resolver.js +1 -0
- package/dist/src/resources/web-release.d.ts +3 -1
- package/dist/src/resources/web-release.js +14 -6
- package/dist/src/serve/agentic-sandbox-fleet-client.js +213 -0
- package/dist/src/serve/fleet-mission-conductor.js +293 -0
- package/dist/src/sessions/index.js +1 -0
- package/dist/src/sessions/output-registration.js +338 -0
- package/dist/src/sessions/promotion.js +73 -2
- package/dist/src/sessions/repository.js +2 -1
- package/dist/src/update/notifier.mjs +13 -2
- package/package.json +8 -1
- package/tools/_resolve-impl.mjs +74 -0
- package/tools/agents/deploy-agents.mjs +962 -0
- package/tools/agents/providers/base.mjs +2954 -0
- package/tools/agents/providers/claude.mjs +711 -0
- package/tools/agents/providers/codex.mjs +699 -0
- package/tools/agents/providers/copilot.mjs +659 -0
- package/tools/agents/providers/cursor.mjs +714 -0
- package/tools/agents/providers/factory.mjs +1130 -0
- package/tools/agents/providers/hermes.mjs +663 -0
- package/tools/agents/providers/hook-capabilities.mjs +85 -0
- package/tools/agents/providers/model-role.mjs +56 -0
- package/tools/agents/providers/openclaw-translator.mjs +348 -0
- package/tools/agents/providers/openclaw.mjs +680 -0
- package/tools/agents/providers/opencode.mjs +675 -0
- package/tools/agents/providers/openhuman.mjs +292 -0
- package/tools/agents/providers/warp.mjs +413 -0
- package/tools/agents/providers/windsurf.mjs +748 -0
- package/tools/commands/deploy-prompts-codex.mjs +336 -0
- package/tools/plugin/package-plugins.mjs +1013 -0
- package/tools/skills/deploy-skills-codex.mjs +571 -0
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Copilot Provider
|
|
3
|
+
*
|
|
4
|
+
* Deploys agents in GitHub Copilot .agent.md format (Markdown with YAML frontmatter).
|
|
5
|
+
* Commands deploy as prompt files (.prompt.md) in .github/prompts/.
|
|
6
|
+
* Rules deploy as path-scoped instructions (.instructions.md) in .github/instructions/.
|
|
7
|
+
*
|
|
8
|
+
* Deployment paths:
|
|
9
|
+
* - Agents: .github/agents/ (.agent.md)
|
|
10
|
+
* - Commands: .github/prompts/ (.prompt.md)
|
|
11
|
+
* - Skills: .github/skills/
|
|
12
|
+
* - Rules: .github/instructions/ (.instructions.md)
|
|
13
|
+
*
|
|
14
|
+
* Special features:
|
|
15
|
+
* - .agent.md format with YAML frontmatter + markdown body
|
|
16
|
+
* - .prompt.md format for commands (invocable as /command in Copilot Chat)
|
|
17
|
+
* - .instructions.md format with applyTo globs for path-scoped rules
|
|
18
|
+
* - Tool mapping to Copilot built-in tools
|
|
19
|
+
* - Creates copilot-instructions.md
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import realFs from 'fs';
|
|
23
|
+
import { createRequire } from 'module';
|
|
24
|
+
const _require = createRequire(import.meta.url);
|
|
25
|
+
const staticModelCatalog = _require('../../../agentic/code/providers/model-catalog.v1.json');
|
|
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 {
|
|
30
|
+
ensureDir,
|
|
31
|
+
listMdFiles,
|
|
32
|
+
listMdFilesRecursive,
|
|
33
|
+
deployFiles,
|
|
34
|
+
inferAgentCategory,
|
|
35
|
+
toKebabCase,
|
|
36
|
+
initializeFrameworkWorkspace,
|
|
37
|
+
getAddonAgentFiles,
|
|
38
|
+
getAddonCommandFiles,
|
|
39
|
+
getAddonRuleFiles,
|
|
40
|
+
getAddonSkillDirs,
|
|
41
|
+
listSkillDirs,
|
|
42
|
+
deploySkillDir,
|
|
43
|
+
deploySkillsWithKernelRouting,
|
|
44
|
+
isKernelSkill,
|
|
45
|
+
pruneStaleAiwgSkills,
|
|
46
|
+
computeAllKernelNames,
|
|
47
|
+
normalizeDeploymentMode,
|
|
48
|
+
collectFrameworkArtifacts,
|
|
49
|
+
listOnDemandRuleFiles,
|
|
50
|
+
writeOnDemandRuleIndex,
|
|
51
|
+
cleanupOldRuleFiles,
|
|
52
|
+
filterCommandsAgainstSkills,
|
|
53
|
+
deploySoulCompanions,
|
|
54
|
+
loadRuntimeModelCatalog
|
|
55
|
+
} from './base.mjs';
|
|
56
|
+
const modelCatalog = loadRuntimeModelCatalog(staticModelCatalog);
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Provider Configuration
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
export const name = 'copilot';
|
|
63
|
+
export const aliases = [];
|
|
64
|
+
|
|
65
|
+
export const paths = {
|
|
66
|
+
agents: '.github/agents/',
|
|
67
|
+
commands: '.github/prompts/',
|
|
68
|
+
// Skills sequestered under .github/.aiwg/skills/ — index-driven discovery (#1212).
|
|
69
|
+
skills: '.github/.aiwg/skills/',
|
|
70
|
+
rules: '.github/instructions/'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Kernel skills (always-loaded) deploy to the platform-native dir.
|
|
74
|
+
export const kernelSkillsPath = '.github/skills/';
|
|
75
|
+
|
|
76
|
+
export const support = {
|
|
77
|
+
agents: 'native',
|
|
78
|
+
commands: 'native',
|
|
79
|
+
skills: 'conventional',
|
|
80
|
+
rules: 'native'
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const capabilities = {
|
|
84
|
+
skills: true,
|
|
85
|
+
rules: true,
|
|
86
|
+
aggregatedOutput: false,
|
|
87
|
+
yamlFormat: false
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Model Mapping
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Map model shorthand to GitHub Copilot format.
|
|
96
|
+
* Resolve semantic AIWG roles through the current provider catalog.
|
|
97
|
+
*/
|
|
98
|
+
export function mapModel(originalModel, modelCfg, modelsConfig) {
|
|
99
|
+
const copilotModels = {
|
|
100
|
+
'opus': modelCatalog.providers.copilot.roles.reasoning.id,
|
|
101
|
+
'sonnet': modelCatalog.providers.copilot.roles.coding.id,
|
|
102
|
+
'haiku': modelCatalog.providers.copilot.roles.efficiency.id
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Handle override models first
|
|
106
|
+
if (modelCfg.reasoningModel || modelCfg.codingModel || modelCfg.efficiencyModel) {
|
|
107
|
+
const clean = (originalModel || 'sonnet').toLowerCase().replace(/['"]/g, '');
|
|
108
|
+
if (/opus/i.test(clean)) return modelCfg.reasoningModel || copilotModels.opus;
|
|
109
|
+
if (/haiku/i.test(clean)) return modelCfg.efficiencyModel || copilotModels.haiku;
|
|
110
|
+
return modelCfg.codingModel || copilotModels.sonnet;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const clean = (originalModel || 'sonnet').toLowerCase().replace(/['"]/g, '');
|
|
114
|
+
|
|
115
|
+
for (const [key, value] of Object.entries(copilotModels)) {
|
|
116
|
+
if (clean.includes(key)) return value;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return copilotModels.sonnet; // default
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// Tool Mapping
|
|
124
|
+
// ============================================================================
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get Copilot tools based on category and original tools.
|
|
128
|
+
* Uses Copilot's built-in tool names (search/codebase, edit, web/fetch, agent, terminal).
|
|
129
|
+
*/
|
|
130
|
+
export function getTools(category, toolsString) {
|
|
131
|
+
// Map AIWG tools to GitHub Copilot built-in tools
|
|
132
|
+
const toolMap = {
|
|
133
|
+
'Read': 'search/codebase',
|
|
134
|
+
'Write': 'edit',
|
|
135
|
+
'MultiEdit': 'edit',
|
|
136
|
+
'Edit': 'edit',
|
|
137
|
+
'Bash': 'terminal',
|
|
138
|
+
'WebFetch': 'web/fetch',
|
|
139
|
+
'Glob': 'search/codebase',
|
|
140
|
+
'Grep': 'search/codebase',
|
|
141
|
+
'Task': 'agent',
|
|
142
|
+
'Agent': 'agent'
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Default tools by category
|
|
146
|
+
const categoryDefaults = {
|
|
147
|
+
analysis: ['search/codebase', 'web/fetch'],
|
|
148
|
+
documentation: ['search/codebase', 'edit', 'web/fetch'],
|
|
149
|
+
planning: ['search/codebase', 'web/fetch'],
|
|
150
|
+
implementation: ['search/codebase', 'edit', 'terminal', 'web/fetch', 'agent']
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// If tools specified, map them
|
|
154
|
+
if (toolsString) {
|
|
155
|
+
let originalTools = [];
|
|
156
|
+
if (toolsString.startsWith('[')) {
|
|
157
|
+
try {
|
|
158
|
+
originalTools = JSON.parse(toolsString);
|
|
159
|
+
} catch (e) {
|
|
160
|
+
originalTools = toolsString.replace(/[\[\]"']/g, '').split(/[,\s]+/).filter(Boolean);
|
|
161
|
+
}
|
|
162
|
+
} else {
|
|
163
|
+
originalTools = toolsString.split(/[,\s]+/).filter(Boolean);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const mappedTools = new Set();
|
|
167
|
+
for (const tool of originalTools) {
|
|
168
|
+
const cleanTool = tool.replace(/\(.*\)/, '').trim();
|
|
169
|
+
const mapped = toolMap[cleanTool];
|
|
170
|
+
if (mapped) mappedTools.add(mapped);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (mappedTools.size > 0) {
|
|
174
|
+
return Array.from(mappedTools);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Fall back to category defaults
|
|
179
|
+
return categoryDefaults[category] || categoryDefaults.implementation;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// Content Transformation
|
|
184
|
+
// ============================================================================
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Transform AIWG agent to GitHub Copilot .agent.md format.
|
|
188
|
+
* Output: YAML frontmatter with name, description, tools, model + markdown body (system prompt).
|
|
189
|
+
*/
|
|
190
|
+
export function transformAgent(srcPath, content, opts) {
|
|
191
|
+
const { modelsConfig = {} } = opts;
|
|
192
|
+
|
|
193
|
+
// Parse existing frontmatter
|
|
194
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
195
|
+
if (!fmMatch) return content;
|
|
196
|
+
|
|
197
|
+
const [, frontmatter, body] = fmMatch;
|
|
198
|
+
|
|
199
|
+
// Extract metadata
|
|
200
|
+
const name = frontmatter.match(/name:\s*(.+)/)?.[1]?.trim();
|
|
201
|
+
const description = frontmatter.match(/description:\s*(.+)/)?.[1]?.trim();
|
|
202
|
+
const modelMatch = frontmatter.match(/model:\s*(.+)/)?.[1]?.trim();
|
|
203
|
+
const toolsMatch = frontmatter.match(/tools:\s*(.+)/)?.[1]?.trim();
|
|
204
|
+
const categoryMatch = frontmatter.match(/category:\s*(.+)/)?.[1]?.trim();
|
|
205
|
+
|
|
206
|
+
// Map model to Copilot format
|
|
207
|
+
const copilotModel = mapModel(modelMatch, opts, modelsConfig);
|
|
208
|
+
|
|
209
|
+
// Determine agent category
|
|
210
|
+
const category = categoryMatch || inferAgentCategory(name, body);
|
|
211
|
+
|
|
212
|
+
// Get Copilot-specific tools
|
|
213
|
+
const copilotTools = getTools(category, toolsMatch);
|
|
214
|
+
|
|
215
|
+
// Build YAML frontmatter
|
|
216
|
+
const fmLines = [
|
|
217
|
+
'---',
|
|
218
|
+
`name: ${name || 'aiwg-agent'}`,
|
|
219
|
+
`description: ${description || 'AIWG SDLC agent'}`
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
if (copilotTools.length > 0) {
|
|
223
|
+
fmLines.push(`tools: [${copilotTools.map(t => `'${t}'`).join(', ')}]`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
fmLines.push(`model: ${copilotModel}`);
|
|
227
|
+
fmLines.push('---');
|
|
228
|
+
|
|
229
|
+
// Body is the system prompt (markdown)
|
|
230
|
+
const cleanBody = body.trim();
|
|
231
|
+
return fmLines.join('\n') + '\n\n' + cleanBody + '\n';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Transform AIWG command to GitHub Copilot .prompt.md format.
|
|
236
|
+
* Output: YAML frontmatter with name, description, model, tools + markdown body.
|
|
237
|
+
* Users invoke via /command-name in Copilot Chat.
|
|
238
|
+
*/
|
|
239
|
+
export function transformCommand(srcPath, content, opts) {
|
|
240
|
+
const { modelsConfig = {} } = opts;
|
|
241
|
+
|
|
242
|
+
// Parse existing frontmatter
|
|
243
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
244
|
+
if (!fmMatch) {
|
|
245
|
+
// No frontmatter, create simple prompt format
|
|
246
|
+
const firstLine = content.split('\n')[0];
|
|
247
|
+
const description = firstLine.replace(/^#\s*/, '').trim() || 'AIWG command';
|
|
248
|
+
const cmdName = toKebabCase(description);
|
|
249
|
+
|
|
250
|
+
return `---\nname: ${cmdName}\ndescription: ${description}\nmodel: gpt-4o\n---\n\n${content.trim()}\n`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const [, frontmatter, body] = fmMatch;
|
|
254
|
+
|
|
255
|
+
// Extract metadata
|
|
256
|
+
const description = frontmatter.match(/description:\s*(.+)/)?.[1]?.trim();
|
|
257
|
+
const argumentHint = frontmatter.match(/argument-hint:\s*(.+)/)?.[1]?.trim()?.replace(/^["']|["']$/g, '');
|
|
258
|
+
const modelMatch = frontmatter.match(/model:\s*(.+)/)?.[1]?.trim();
|
|
259
|
+
const toolsMatch = frontmatter.match(/(?:allowed-tools|tools):\s*(.+)/)?.[1]?.trim();
|
|
260
|
+
const cmdName = toKebabCase(description || 'aiwg-command');
|
|
261
|
+
|
|
262
|
+
// Map model
|
|
263
|
+
const copilotModel = mapModel(modelMatch, opts, modelsConfig);
|
|
264
|
+
|
|
265
|
+
// Map tools from allowed-tools
|
|
266
|
+
const copilotTools = getTools('implementation', toolsMatch);
|
|
267
|
+
|
|
268
|
+
// Build YAML frontmatter
|
|
269
|
+
const fmLines = [
|
|
270
|
+
'---',
|
|
271
|
+
`name: ${cmdName}`,
|
|
272
|
+
`description: ${description || 'AIWG command'}`
|
|
273
|
+
];
|
|
274
|
+
|
|
275
|
+
if (copilotTools.length > 0) {
|
|
276
|
+
fmLines.push(`tools: [${copilotTools.map(t => `'${t}'`).join(', ')}]`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
fmLines.push(`model: ${copilotModel}`);
|
|
280
|
+
|
|
281
|
+
if (argumentHint) {
|
|
282
|
+
fmLines.push(`argument-hint: "${argumentHint}"`);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
fmLines.push('---');
|
|
286
|
+
|
|
287
|
+
const cleanBody = body.trim();
|
|
288
|
+
return fmLines.join('\n') + '\n\n' + cleanBody + '\n';
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Transform AIWG rule to GitHub Copilot .instructions.md format.
|
|
293
|
+
* Output: YAML frontmatter with name, description, applyTo + rule body.
|
|
294
|
+
*/
|
|
295
|
+
export function transformRule(srcPath, content, opts) {
|
|
296
|
+
// Rules may have frontmatter or be plain markdown
|
|
297
|
+
let frontmatter = '';
|
|
298
|
+
let body = content;
|
|
299
|
+
|
|
300
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
301
|
+
if (fmMatch) {
|
|
302
|
+
frontmatter = fmMatch[1];
|
|
303
|
+
body = fmMatch[2];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Extract name from frontmatter or first heading
|
|
307
|
+
let name = frontmatter && frontmatter.match(/name:\s*(.+)/)?.[1]?.trim();
|
|
308
|
+
if (!name) {
|
|
309
|
+
const headingMatch = body.match(/^#\s+(.+)/m);
|
|
310
|
+
name = headingMatch ? headingMatch[1].trim() : path.basename(srcPath, '.md');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Extract description from frontmatter or first bold line
|
|
314
|
+
let description = frontmatter && frontmatter.match(/description:\s*(.+)/)?.[1]?.trim();
|
|
315
|
+
if (!description) {
|
|
316
|
+
const scopeMatch = body.match(/\*\*(?:Scope|Summary)\*\*:\s*(.+)/);
|
|
317
|
+
description = scopeMatch ? scopeMatch[1].trim() : name;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Derive applyTo from rule content or filename
|
|
321
|
+
const applyTo = deriveApplyTo(srcPath, body);
|
|
322
|
+
|
|
323
|
+
// Build instructions format
|
|
324
|
+
const fmLines = [
|
|
325
|
+
'---',
|
|
326
|
+
`name: ${name}`,
|
|
327
|
+
`description: ${description}`
|
|
328
|
+
];
|
|
329
|
+
|
|
330
|
+
if (applyTo) {
|
|
331
|
+
fmLines.push(`applyTo: '${applyTo}'`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
fmLines.push('---');
|
|
335
|
+
|
|
336
|
+
const cleanBody = body.trim();
|
|
337
|
+
return fmLines.join('\n') + '\n\n' + cleanBody + '\n';
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Derive applyTo glob patterns from rule content and filename.
|
|
342
|
+
*/
|
|
343
|
+
function deriveApplyTo(srcPath, body) {
|
|
344
|
+
const filename = path.basename(srcPath).toLowerCase();
|
|
345
|
+
const content = body.toLowerCase();
|
|
346
|
+
|
|
347
|
+
// Security rules apply to code files
|
|
348
|
+
if (filename.includes('security') || filename.includes('token') ||
|
|
349
|
+
content.includes('vulnerability') || content.includes('owasp')) {
|
|
350
|
+
return '**/*.{ts,js,mjs,cjs,py,go,java,rs}';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Documentation rules apply to markdown
|
|
354
|
+
if (filename.includes('diagram') || filename.includes('documentation') ||
|
|
355
|
+
filename.includes('doc-') || content.includes('documentation artifact')) {
|
|
356
|
+
return '**/*.md';
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Agent/deployment rules apply to agent definitions
|
|
360
|
+
if (filename.includes('agent-deployment') || filename.includes('agent-')) {
|
|
361
|
+
return '**/*.{md,yaml,yml}';
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Code style/implementation rules
|
|
365
|
+
if (filename.includes('code') || filename.includes('implementation') ||
|
|
366
|
+
filename.includes('test') || filename.includes('lint')) {
|
|
367
|
+
return '**/*.{ts,js,mjs,cjs}';
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Default: apply to all files
|
|
371
|
+
return '**/*';
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ============================================================================
|
|
375
|
+
// Deployment Functions
|
|
376
|
+
// ============================================================================
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Deploy agents to .github/agents/ as .agent.md files
|
|
380
|
+
*/
|
|
381
|
+
export function deployAgents(agentFiles, targetDir, opts) {
|
|
382
|
+
const destDir = path.join(targetDir, paths.agents);
|
|
383
|
+
ensureDir(destDir, opts.dryRun);
|
|
384
|
+
return deployFiles(agentFiles, destDir, { ...opts, fileExtension: '.agent.md', injectPlatform: true }, transformAgent);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Deploy commands to .github/prompts/ as .prompt.md files
|
|
389
|
+
*/
|
|
390
|
+
export function deployCommands(commandFiles, targetDir, opts) {
|
|
391
|
+
const destDir = path.join(targetDir, paths.commands);
|
|
392
|
+
ensureDir(destDir, opts.dryRun);
|
|
393
|
+
return deployFiles(commandFiles, destDir, { ...opts, fileExtension: '.prompt.md' }, transformCommand);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Deploy skills with kernel-vs-standard routing (#1212/#1216) plus
|
|
398
|
+
* .agents/skills/ cross-agent compatibility (PUW-012 #1113).
|
|
399
|
+
* - kernel skills → .github/skills/ (platform-native, always-loaded)
|
|
400
|
+
* - standard → .github/.aiwg/skills/ (index-discoverable)
|
|
401
|
+
* - cross-agent compatibility mirror is preserved at .agents/skills/.
|
|
402
|
+
*/
|
|
403
|
+
export function deploySkills(skillDirs, targetDir, opts) {
|
|
404
|
+
const standardDestDir = path.join(targetDir, paths.skills);
|
|
405
|
+
const kernelDestDir = path.join(targetDir, kernelSkillsPath);
|
|
406
|
+
deploySkillsWithKernelRouting(skillDirs, standardDestDir, kernelDestDir, opts);
|
|
407
|
+
|
|
408
|
+
// Cross-agent compatibility: .agents/skills/ — honors #1217 no-copy
|
|
409
|
+
// default. Filter to kernel-only unless operator opts in via env var.
|
|
410
|
+
const copyStandardSkills = opts?.copyStandardSkills === true;
|
|
411
|
+
const crossAgentSkills = copyStandardSkills
|
|
412
|
+
? skillDirs
|
|
413
|
+
: skillDirs.filter(d => isKernelSkill(d));
|
|
414
|
+
if (crossAgentSkills.length > 0) {
|
|
415
|
+
const crossAgentDir = path.join(targetDir, '.agents', 'skills');
|
|
416
|
+
ensureDir(crossAgentDir, opts.dryRun);
|
|
417
|
+
if (!opts.dryRun) {
|
|
418
|
+
console.log(`Deploying cross-agent skills to ${path.relative(process.cwd(), crossAgentDir)}...`);
|
|
419
|
+
} else {
|
|
420
|
+
console.log(`[dry-run] Would deploy cross-agent skills to .agents/skills/`);
|
|
421
|
+
}
|
|
422
|
+
for (const skillDir of crossAgentSkills) {
|
|
423
|
+
deploySkillDir(skillDir, crossAgentDir, opts);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Deploy rules to .github/instructions/ as .instructions.md files
|
|
430
|
+
*/
|
|
431
|
+
export function deployRules(ruleFiles, targetDir, opts) {
|
|
432
|
+
const destDir = path.join(targetDir, paths.rules);
|
|
433
|
+
ensureDir(destDir, opts.dryRun);
|
|
434
|
+
cleanupOldRuleFiles(destDir, opts);
|
|
435
|
+
return deployFiles(ruleFiles, destDir, { ...opts, fileExtension: '.instructions.md' }, transformRule);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// ============================================================================
|
|
439
|
+
// copilot-instructions.md
|
|
440
|
+
// ============================================================================
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Create copilot-instructions.md from template
|
|
444
|
+
*/
|
|
445
|
+
export function createCopilotInstructions(target, srcRoot, dryRun) {
|
|
446
|
+
const templatePath = path.join(srcRoot, 'agentic', 'code', 'frameworks', 'sdlc-complete', 'templates', 'copilot', 'copilot-instructions.md.aiwg-template');
|
|
447
|
+
const githubDir = path.join(target, '.github');
|
|
448
|
+
const destPath = path.join(githubDir, 'copilot-instructions.md');
|
|
449
|
+
|
|
450
|
+
if (!fs.existsSync(templatePath)) {
|
|
451
|
+
console.warn(`Copilot instructions template not found at ${templatePath}`);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
const template = fs.readFileSync(templatePath, 'utf8');
|
|
456
|
+
|
|
457
|
+
// Ensure .github directory exists
|
|
458
|
+
if (!dryRun && !fs.existsSync(githubDir)) {
|
|
459
|
+
fs.mkdirSync(githubDir, { recursive: true });
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (fs.existsSync(destPath)) {
|
|
463
|
+
const existing = fs.readFileSync(destPath, 'utf8');
|
|
464
|
+
|
|
465
|
+
if (existing.includes('<!-- AIWG SDLC Framework Integration -->') ||
|
|
466
|
+
existing.includes('## AIWG SDLC Framework')) {
|
|
467
|
+
console.log('copilot-instructions.md already contains AIWG section, skipping');
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const markerIndex = template.indexOf('<!-- AIWG SDLC Framework Integration -->');
|
|
472
|
+
const aiwgSection = markerIndex !== -1 ? template.slice(markerIndex) : template;
|
|
473
|
+
const combined = existing.trimEnd() + '\n\n---\n\n' + aiwgSection.trim() + '\n';
|
|
474
|
+
|
|
475
|
+
if (dryRun) {
|
|
476
|
+
console.log(`[dry-run] Would update existing copilot-instructions.md with AIWG section`);
|
|
477
|
+
} else {
|
|
478
|
+
fs.writeFileSync(destPath, combined, 'utf8');
|
|
479
|
+
console.log('Updated copilot-instructions.md with AIWG SDLC framework section');
|
|
480
|
+
}
|
|
481
|
+
} else {
|
|
482
|
+
if (dryRun) {
|
|
483
|
+
console.log(`[dry-run] Would create copilot-instructions.md from template`);
|
|
484
|
+
} else {
|
|
485
|
+
fs.writeFileSync(destPath, template, 'utf8');
|
|
486
|
+
console.log('Created copilot-instructions.md from template');
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// ============================================================================
|
|
492
|
+
// Post-Deployment
|
|
493
|
+
// ============================================================================
|
|
494
|
+
|
|
495
|
+
export async function postDeploy(targetDir, opts) {
|
|
496
|
+
initializeFrameworkWorkspace(targetDir, opts.mode, opts.dryRun, opts.srcRoot);
|
|
497
|
+
|
|
498
|
+
// Create copilot-instructions.md
|
|
499
|
+
createCopilotInstructions(targetDir, opts.srcRoot, opts.dryRun);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// ============================================================================
|
|
503
|
+
// File Extension
|
|
504
|
+
// ============================================================================
|
|
505
|
+
|
|
506
|
+
export function getFileExtension(type) {
|
|
507
|
+
switch (type) {
|
|
508
|
+
case 'agent': return '.agent.md';
|
|
509
|
+
case 'command': return '.prompt.md';
|
|
510
|
+
case 'rule': return '.instructions.md';
|
|
511
|
+
default: return '.md';
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// ============================================================================
|
|
516
|
+
// Main Deploy Function
|
|
517
|
+
// ============================================================================
|
|
518
|
+
|
|
519
|
+
export async function deploy(opts) {
|
|
520
|
+
const {
|
|
521
|
+
srcRoot,
|
|
522
|
+
target,
|
|
523
|
+
mode,
|
|
524
|
+
deployCommands: shouldDeployCommands,
|
|
525
|
+
deploySkills: shouldDeploySkills,
|
|
526
|
+
deployRules: shouldDeployRules,
|
|
527
|
+
commandsOnly,
|
|
528
|
+
skillsOnly,
|
|
529
|
+
rulesOnly,
|
|
530
|
+
dryRun
|
|
531
|
+
} = opts;
|
|
532
|
+
|
|
533
|
+
console.log(`\n=== GitHub Copilot Provider ===`);
|
|
534
|
+
console.log(`Target: ${target}`);
|
|
535
|
+
console.log(`Mode: ${mode}`);
|
|
536
|
+
|
|
537
|
+
const agentFiles = [];
|
|
538
|
+
const commandFiles = [];
|
|
539
|
+
const skillDirs = [];
|
|
540
|
+
const ruleFiles = [];
|
|
541
|
+
const normalizedMode = normalizeDeploymentMode(mode);
|
|
542
|
+
|
|
543
|
+
// All addons (dynamically discovered)
|
|
544
|
+
if (normalizedMode === 'general' || normalizedMode === 'sdlc' || normalizedMode === 'both' || normalizedMode === 'all') {
|
|
545
|
+
agentFiles.push(...getAddonAgentFiles(srcRoot));
|
|
546
|
+
|
|
547
|
+
if (shouldDeployCommands || commandsOnly) {
|
|
548
|
+
commandFiles.push(...getAddonCommandFiles(srcRoot));
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (shouldDeploySkills || skillsOnly) {
|
|
552
|
+
skillDirs.push(...getAddonSkillDirs(srcRoot));
|
|
553
|
+
|
|
554
|
+
// Holistic post-deploy cleanup of stale AIWG-managed kernel
|
|
555
|
+
// skills (renamed/removed sources). Uses the global kernel set
|
|
556
|
+
// (computeAllKernelNames walks all source frameworks/addons),
|
|
557
|
+
// not just this-call's skillDirs, because aiwg use invokes
|
|
558
|
+
// deploy-agents.mjs multiple times.
|
|
559
|
+
{
|
|
560
|
+
const _kernelDestDir = path.isAbsolute(kernelSkillsPath)
|
|
561
|
+
? kernelSkillsPath
|
|
562
|
+
: path.join(target, kernelSkillsPath);
|
|
563
|
+
pruneStaleAiwgSkills(_kernelDestDir, computeAllKernelNames(srcRoot), opts);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (shouldDeployRules || rulesOnly) {
|
|
568
|
+
ruleFiles.push(...getAddonRuleFiles(srcRoot));
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
const frameworkArtifacts = collectFrameworkArtifacts(srcRoot, normalizedMode, {
|
|
573
|
+
includeAgents: true,
|
|
574
|
+
includeCommands: shouldDeployCommands || commandsOnly,
|
|
575
|
+
includeSkills: shouldDeploySkills || skillsOnly,
|
|
576
|
+
includeRules: shouldDeployRules || rulesOnly,
|
|
577
|
+
recursiveCommands: true,
|
|
578
|
+
consolidatedSdlcRules: true
|
|
579
|
+
});
|
|
580
|
+
agentFiles.push(...frameworkArtifacts.agents);
|
|
581
|
+
const soulFiles = [...(frameworkArtifacts.souls || [])];
|
|
582
|
+
commandFiles.push(...frameworkArtifacts.commands);
|
|
583
|
+
skillDirs.push(...frameworkArtifacts.skills);
|
|
584
|
+
ruleFiles.push(...frameworkArtifacts.rules);
|
|
585
|
+
|
|
586
|
+
// Deploy
|
|
587
|
+
if (!commandsOnly && !skillsOnly && !rulesOnly) {
|
|
588
|
+
console.log(`\nDeploying ${agentFiles.length} agents (.agent.md format)...`);
|
|
589
|
+
deployAgents(agentFiles, target, opts);
|
|
590
|
+
|
|
591
|
+
// Deploy soul companion files alongside agents
|
|
592
|
+
if (soulFiles.length > 0) {
|
|
593
|
+
const destDir = path.join(target, paths.agents);
|
|
594
|
+
console.log(`\nDeploying ${soulFiles.length} soul files...`);
|
|
595
|
+
deploySoulCompanions(soulFiles, destDir, opts);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// Filter commands that collide with skills (skills take precedence)
|
|
600
|
+
const filteredCommands = (shouldDeploySkills || skillsOnly)
|
|
601
|
+
? filterCommandsAgainstSkills(commandFiles, skillDirs)
|
|
602
|
+
: commandFiles;
|
|
603
|
+
|
|
604
|
+
if (shouldDeployCommands || commandsOnly) {
|
|
605
|
+
console.log(`\nDeploying ${filteredCommands.length} commands (.prompt.md format)...`);
|
|
606
|
+
deployCommands(filteredCommands, target, opts);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (shouldDeploySkills || skillsOnly) {
|
|
610
|
+
console.log(`\nDeploying ${skillDirs.length} skills...`);
|
|
611
|
+
deploySkills(skillDirs, target, opts);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
if (shouldDeployRules || rulesOnly) {
|
|
615
|
+
console.log(`\nDeploying ${ruleFiles.length} rules...`);
|
|
616
|
+
deployRules(ruleFiles, target, opts);
|
|
617
|
+
|
|
618
|
+
// On-demand index (#1675): list the MEDIUM/LOW rules tier-gated out of the
|
|
619
|
+
// always-on set so agents can fetch them via `aiwg show rule`.
|
|
620
|
+
const onDemandCount = writeOnDemandRuleIndex(
|
|
621
|
+
path.join(target, paths.rules),
|
|
622
|
+
listOnDemandRuleFiles(srcRoot),
|
|
623
|
+
opts,
|
|
624
|
+
);
|
|
625
|
+
if (onDemandCount > 0) {
|
|
626
|
+
console.log(` On-demand rules (not inlined): ${onDemandCount} → RULES-ONDEMAND.md`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
await postDeploy(target, opts);
|
|
631
|
+
|
|
632
|
+
console.log('\n=== Copilot deployment complete ===\n');
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// ============================================================================
|
|
636
|
+
// Default Export
|
|
637
|
+
// ============================================================================
|
|
638
|
+
|
|
639
|
+
export default {
|
|
640
|
+
name,
|
|
641
|
+
aliases,
|
|
642
|
+
paths,
|
|
643
|
+
kernelSkillsPath,
|
|
644
|
+
support,
|
|
645
|
+
capabilities,
|
|
646
|
+
transformAgent,
|
|
647
|
+
transformCommand,
|
|
648
|
+
transformRule,
|
|
649
|
+
mapModel,
|
|
650
|
+
getTools,
|
|
651
|
+
deployAgents,
|
|
652
|
+
deployCommands,
|
|
653
|
+
deploySkills,
|
|
654
|
+
deployRules,
|
|
655
|
+
createCopilotInstructions,
|
|
656
|
+
postDeploy,
|
|
657
|
+
getFileExtension,
|
|
658
|
+
deploy
|
|
659
|
+
};
|