specweave 0.3.13 â 0.4.1
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/CLAUDE.md +506 -17
- package/README.md +100 -58
- package/bin/install-all.sh +9 -2
- package/bin/install-hooks.sh +57 -0
- package/bin/specweave.js +16 -0
- package/dist/adapters/adapter-base.d.ts +21 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -1
- package/dist/adapters/adapter-base.js +28 -0
- package/dist/adapters/adapter-base.js.map +1 -1
- package/dist/adapters/adapter-interface.d.ts +41 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.d.ts +36 -0
- package/dist/adapters/claude/adapter.d.ts.map +1 -1
- package/dist/adapters/claude/adapter.js +135 -0
- package/dist/adapters/claude/adapter.js.map +1 -1
- package/dist/adapters/copilot/adapter.d.ts +25 -0
- package/dist/adapters/copilot/adapter.d.ts.map +1 -1
- package/dist/adapters/copilot/adapter.js +112 -0
- package/dist/adapters/copilot/adapter.js.map +1 -1
- package/dist/adapters/cursor/adapter.d.ts +36 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -1
- package/dist/adapters/cursor/adapter.js +140 -0
- package/dist/adapters/cursor/adapter.js.map +1 -1
- package/dist/adapters/generic/adapter.d.ts +25 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -1
- package/dist/adapters/generic/adapter.js +111 -0
- package/dist/adapters/generic/adapter.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +103 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/plugin.d.ts +37 -0
- package/dist/cli/commands/plugin.d.ts.map +1 -0
- package/dist/cli/commands/plugin.js +296 -0
- package/dist/cli/commands/plugin.js.map +1 -0
- package/dist/core/agent-model-manager.d.ts +52 -0
- package/dist/core/agent-model-manager.d.ts.map +1 -0
- package/dist/core/agent-model-manager.js +120 -0
- package/dist/core/agent-model-manager.js.map +1 -0
- package/dist/core/cost-tracker.d.ts +108 -0
- package/dist/core/cost-tracker.d.ts.map +1 -0
- package/dist/core/cost-tracker.js +281 -0
- package/dist/core/cost-tracker.js.map +1 -0
- package/dist/core/model-selector.d.ts +57 -0
- package/dist/core/model-selector.d.ts.map +1 -0
- package/dist/core/model-selector.js +115 -0
- package/dist/core/model-selector.js.map +1 -0
- package/dist/core/phase-detector.d.ts +62 -0
- package/dist/core/phase-detector.d.ts.map +1 -0
- package/dist/core/phase-detector.js +229 -0
- package/dist/core/phase-detector.js.map +1 -0
- package/dist/core/plugin-detector.d.ts +96 -0
- package/dist/core/plugin-detector.d.ts.map +1 -0
- package/dist/core/plugin-detector.js +349 -0
- package/dist/core/plugin-detector.js.map +1 -0
- package/dist/core/plugin-loader.d.ts +111 -0
- package/dist/core/plugin-loader.d.ts.map +1 -0
- package/dist/core/plugin-loader.js +319 -0
- package/dist/core/plugin-loader.js.map +1 -0
- package/dist/core/plugin-manager.d.ts +144 -0
- package/dist/core/plugin-manager.d.ts.map +1 -0
- package/dist/core/plugin-manager.js +393 -0
- package/dist/core/plugin-manager.js.map +1 -0
- package/dist/core/schemas/plugin-manifest.schema.json +253 -0
- package/dist/core/types/plugin.d.ts +252 -0
- package/dist/core/types/plugin.d.ts.map +1 -0
- package/dist/core/types/plugin.js +48 -0
- package/dist/core/types/plugin.js.map +1 -0
- package/dist/integrations/jira/jira-mapper.d.ts +2 -2
- package/dist/integrations/jira/jira-mapper.js +2 -2
- package/dist/types/cost-tracking.d.ts +43 -0
- package/dist/types/cost-tracking.d.ts.map +1 -0
- package/dist/types/cost-tracking.js +8 -0
- package/dist/types/cost-tracking.js.map +1 -0
- package/dist/types/model-selection.d.ts +53 -0
- package/dist/types/model-selection.d.ts.map +1 -0
- package/dist/types/model-selection.js +12 -0
- package/dist/types/model-selection.js.map +1 -0
- package/dist/utils/cost-reporter.d.ts +58 -0
- package/dist/utils/cost-reporter.d.ts.map +1 -0
- package/dist/utils/cost-reporter.js +224 -0
- package/dist/utils/cost-reporter.js.map +1 -0
- package/dist/utils/pricing-constants.d.ts +70 -0
- package/dist/utils/pricing-constants.d.ts.map +1 -0
- package/dist/utils/pricing-constants.js +71 -0
- package/dist/utils/pricing-constants.js.map +1 -0
- package/package.json +13 -9
- package/src/adapters/adapter-base.ts +33 -0
- package/src/adapters/adapter-interface.ts +46 -0
- package/src/adapters/claude/adapter.ts +164 -0
- package/src/adapters/copilot/adapter.ts +138 -0
- package/src/adapters/cursor/adapter.ts +170 -0
- package/src/adapters/generic/adapter.ts +137 -0
- package/src/agents/architect/AGENT.md +3 -0
- package/src/agents/code-reviewer.md +156 -0
- package/src/agents/data-scientist/AGENT.md +181 -0
- package/src/agents/database-optimizer/AGENT.md +147 -0
- package/src/agents/devops/AGENT.md +3 -0
- package/src/agents/diagrams-architect/AGENT.md +3 -0
- package/src/agents/docs-writer/AGENT.md +3 -0
- package/src/agents/kubernetes-architect/AGENT.md +142 -0
- package/src/agents/ml-engineer/AGENT.md +150 -0
- package/src/agents/mlops-engineer/AGENT.md +201 -0
- package/src/agents/network-engineer/AGENT.md +149 -0
- package/src/agents/observability-engineer/AGENT.md +213 -0
- package/src/agents/payment-integration/AGENT.md +35 -0
- package/src/agents/performance/AGENT.md +3 -0
- package/src/agents/performance-engineer/AGENT.md +153 -0
- package/src/agents/pm/AGENT.md +3 -0
- package/src/agents/qa-lead/AGENT.md +3 -0
- package/src/agents/security/AGENT.md +3 -0
- package/src/agents/sre/AGENT.md +3 -0
- package/src/agents/tdd-orchestrator/AGENT.md +169 -0
- package/src/agents/tech-lead/AGENT.md +3 -0
- package/src/commands/specweave.costs.md +261 -0
- package/src/commands/specweave.increment.md +48 -4
- package/src/commands/specweave.ml-pipeline.md +292 -0
- package/src/commands/specweave.monitor-setup.md +501 -0
- package/src/commands/specweave.slo-implement.md +1055 -0
- package/src/commands/specweave.sync-github.md +1 -1
- package/src/commands/specweave.tdd-cycle.md +199 -0
- package/src/commands/specweave.tdd-green.md +842 -0
- package/src/commands/specweave.tdd-red.md +135 -0
- package/src/commands/specweave.tdd-refactor.md +165 -0
- package/src/hooks/post-increment-plugin-detect.sh +142 -0
- package/src/hooks/post-task-completion.sh +53 -11
- package/src/hooks/pre-task-plugin-detect.sh +96 -0
- package/src/skills/SKILLS-INDEX.md +18 -10
- package/src/skills/billing-automation/SKILL.md +559 -0
- package/src/skills/distributed-tracing/SKILL.md +438 -0
- package/src/skills/e2e-playwright/README.md +1 -1
- package/src/skills/e2e-playwright/package.json +1 -1
- package/src/skills/gitops-workflow/SKILL.md +285 -0
- package/src/skills/gitops-workflow/references/argocd-setup.md +134 -0
- package/src/skills/gitops-workflow/references/sync-policies.md +131 -0
- package/src/skills/grafana-dashboards/SKILL.md +369 -0
- package/src/skills/helm-chart-scaffolding/SKILL.md +544 -0
- package/src/skills/helm-chart-scaffolding/assets/Chart.yaml.template +42 -0
- package/src/skills/helm-chart-scaffolding/assets/values.yaml.template +185 -0
- package/src/skills/helm-chart-scaffolding/references/chart-structure.md +500 -0
- package/src/skills/helm-chart-scaffolding/scripts/validate-chart.sh +244 -0
- package/src/skills/k8s-manifest-generator/SKILL.md +511 -0
- package/src/skills/k8s-manifest-generator/assets/configmap-template.yaml +296 -0
- package/src/skills/k8s-manifest-generator/assets/deployment-template.yaml +203 -0
- package/src/skills/k8s-manifest-generator/assets/service-template.yaml +171 -0
- package/src/skills/k8s-manifest-generator/references/deployment-spec.md +753 -0
- package/src/skills/k8s-manifest-generator/references/service-spec.md +724 -0
- package/src/skills/k8s-security-policies/SKILL.md +334 -0
- package/src/skills/k8s-security-policies/assets/network-policy-template.yaml +177 -0
- package/src/skills/k8s-security-policies/references/rbac-patterns.md +187 -0
- package/src/skills/ml-pipeline-workflow/SKILL.md +245 -0
- package/src/skills/paypal-integration/SKILL.md +467 -0
- package/src/skills/pci-compliance/SKILL.md +466 -0
- package/src/skills/prometheus-configuration/SKILL.md +392 -0
- package/src/skills/slo-implementation/SKILL.md +329 -0
- package/src/skills/stripe-integration/SKILL.md +442 -0
- package/src/skills/tdd-workflow/SKILL.md +378 -0
- package/src/templates/README.md.template +1 -1
- package/src/skills/bmad-method-expert/SKILL.md +0 -626
- package/src/skills/bmad-method-expert/scripts/analyze-project.js +0 -318
- package/src/skills/bmad-method-expert/scripts/check-setup.js +0 -208
- package/src/skills/bmad-method-expert/scripts/generate-template.js +0 -1149
- package/src/skills/bmad-method-expert/scripts/validate-documents.js +0 -340
- package/src/skills/context-optimizer/SKILL.md +0 -588
- package/src/skills/figma-designer/SKILL.md +0 -149
- package/src/skills/figma-implementer/SKILL.md +0 -148
- package/src/skills/figma-mcp-connector/SKILL.md +0 -136
- package/src/skills/figma-to-code/SKILL.md +0 -128
- package/src/skills/spec-kit-expert/SKILL.md +0 -1010
|
@@ -12,6 +12,7 @@ import * as path from 'path';
|
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import { AdapterBase } from '../adapter-base.js';
|
|
14
14
|
import { AdapterOptions, AdapterFile } from '../adapter-interface.js';
|
|
15
|
+
import type { Plugin } from '../../core/types/plugin.js';
|
|
15
16
|
|
|
16
17
|
export class ClaudeAdapter extends AdapterBase {
|
|
17
18
|
name = 'claude';
|
|
@@ -154,4 +155,167 @@ You're ready to build with SpecWeave on Claude Code!
|
|
|
154
155
|
For complete documentation, see: .claude/README.md
|
|
155
156
|
`;
|
|
156
157
|
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Check if Claude adapter supports plugins
|
|
161
|
+
*
|
|
162
|
+
* Claude Code has FULL plugin support via native .claude/ directory
|
|
163
|
+
*
|
|
164
|
+
* @returns boolean Always true
|
|
165
|
+
*/
|
|
166
|
+
supportsPlugins(): boolean {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Compile and install a plugin for Claude Code
|
|
172
|
+
*
|
|
173
|
+
* Claude uses native plugin installation:
|
|
174
|
+
* - Copy skills to .claude/skills/{plugin-name}/{skill-name}/
|
|
175
|
+
* - Copy agents to .claude/agents/{plugin-name}/{agent-name}/
|
|
176
|
+
* - Copy commands to .claude/commands/
|
|
177
|
+
*
|
|
178
|
+
* @param plugin Plugin to install
|
|
179
|
+
*/
|
|
180
|
+
async compilePlugin(plugin: Plugin): Promise<void> {
|
|
181
|
+
const projectPath = process.cwd();
|
|
182
|
+
const claudeDir = path.join(projectPath, '.claude');
|
|
183
|
+
|
|
184
|
+
console.log(`\nđĻ Installing plugin: ${plugin.manifest.name}`);
|
|
185
|
+
|
|
186
|
+
// Ensure base directories exist
|
|
187
|
+
await fs.ensureDir(path.join(claudeDir, 'skills'));
|
|
188
|
+
await fs.ensureDir(path.join(claudeDir, 'agents'));
|
|
189
|
+
await fs.ensureDir(path.join(claudeDir, 'commands'));
|
|
190
|
+
|
|
191
|
+
// Install skills
|
|
192
|
+
for (const skill of plugin.skills) {
|
|
193
|
+
const targetPath = path.join(claudeDir, 'skills', skill.name);
|
|
194
|
+
await fs.ensureDir(targetPath);
|
|
195
|
+
|
|
196
|
+
// Copy SKILL.md
|
|
197
|
+
const skillMdPath = path.join(skill.path, 'SKILL.md');
|
|
198
|
+
if (await fs.pathExists(skillMdPath)) {
|
|
199
|
+
await fs.copy(skillMdPath, path.join(targetPath, 'SKILL.md'));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Copy test cases if they exist
|
|
203
|
+
const testCasesDir = path.join(skill.path, 'test-cases');
|
|
204
|
+
if (await fs.pathExists(testCasesDir)) {
|
|
205
|
+
await fs.copy(testCasesDir, path.join(targetPath, 'test-cases'));
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
console.log(` â Skill: ${skill.name}`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Install agents
|
|
212
|
+
for (const agent of plugin.agents) {
|
|
213
|
+
const targetPath = path.join(claudeDir, 'agents', agent.name);
|
|
214
|
+
await fs.ensureDir(targetPath);
|
|
215
|
+
|
|
216
|
+
// Copy AGENT.md
|
|
217
|
+
const agentMdPath = path.join(agent.path, 'AGENT.md');
|
|
218
|
+
if (await fs.pathExists(agentMdPath)) {
|
|
219
|
+
await fs.copy(agentMdPath, path.join(targetPath, 'AGENT.md'));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
console.log(` â Agent: ${agent.name}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Install commands
|
|
226
|
+
for (const command of plugin.commands) {
|
|
227
|
+
// Commands use their full name as filename
|
|
228
|
+
const fileName = command.name.replace(/\./g, '-') + '.md';
|
|
229
|
+
const targetPath = path.join(claudeDir, 'commands', fileName);
|
|
230
|
+
|
|
231
|
+
if (await fs.pathExists(command.path)) {
|
|
232
|
+
await fs.copy(command.path, targetPath);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
console.log(` â Command: /${command.name}`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
console.log(`\nâ
Plugin ${plugin.manifest.name} installed!`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Unload a plugin from Claude Code
|
|
243
|
+
*
|
|
244
|
+
* Removes plugin files from .claude/ directory
|
|
245
|
+
*
|
|
246
|
+
* @param pluginName Name of plugin to unload
|
|
247
|
+
*/
|
|
248
|
+
async unloadPlugin(pluginName: string): Promise<void> {
|
|
249
|
+
const projectPath = process.cwd();
|
|
250
|
+
const claudeDir = path.join(projectPath, '.claude');
|
|
251
|
+
|
|
252
|
+
console.log(`\nđī¸ Unloading plugin: ${pluginName}`);
|
|
253
|
+
|
|
254
|
+
// Read plugin manifest to know what to remove
|
|
255
|
+
const pluginsDir = path.join(projectPath, 'src', 'plugins');
|
|
256
|
+
const pluginPath = path.join(pluginsDir, pluginName);
|
|
257
|
+
|
|
258
|
+
if (!(await fs.pathExists(pluginPath))) {
|
|
259
|
+
console.warn(`â ī¸ Plugin ${pluginName} not found`);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Load plugin to get its components
|
|
264
|
+
const { PluginLoader } = await import('../../core/plugin-loader.js');
|
|
265
|
+
const loader = new PluginLoader();
|
|
266
|
+
const plugin = await loader.loadFromDirectory(pluginPath);
|
|
267
|
+
|
|
268
|
+
// Remove skills
|
|
269
|
+
for (const skill of plugin.skills) {
|
|
270
|
+
const skillPath = path.join(claudeDir, 'skills', skill.name);
|
|
271
|
+
if (await fs.pathExists(skillPath)) {
|
|
272
|
+
await fs.remove(skillPath);
|
|
273
|
+
console.log(` â Removed skill: ${skill.name}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Remove agents
|
|
278
|
+
for (const agent of plugin.agents) {
|
|
279
|
+
const agentPath = path.join(claudeDir, 'agents', agent.name);
|
|
280
|
+
if (await fs.pathExists(agentPath)) {
|
|
281
|
+
await fs.remove(agentPath);
|
|
282
|
+
console.log(` â Removed agent: ${agent.name}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Remove commands
|
|
287
|
+
for (const command of plugin.commands) {
|
|
288
|
+
const fileName = command.name.replace(/\./g, '-') + '.md';
|
|
289
|
+
const commandPath = path.join(claudeDir, 'commands', fileName);
|
|
290
|
+
if (await fs.pathExists(commandPath)) {
|
|
291
|
+
await fs.remove(commandPath);
|
|
292
|
+
console.log(` â Removed command: /${command.name}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
console.log(`\nâ
Plugin ${pluginName} unloaded!`);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Get list of installed plugins
|
|
301
|
+
*
|
|
302
|
+
* Returns plugin names that are currently installed in .claude/
|
|
303
|
+
*
|
|
304
|
+
* @returns Array of installed plugin names
|
|
305
|
+
*/
|
|
306
|
+
async getInstalledPlugins(): Promise<string[]> {
|
|
307
|
+
const projectPath = process.cwd();
|
|
308
|
+
const configPath = path.join(projectPath, '.specweave', 'config.yaml');
|
|
309
|
+
|
|
310
|
+
if (!(await fs.pathExists(configPath))) {
|
|
311
|
+
return [];
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Read config to get enabled plugins
|
|
315
|
+
const yaml = await import('js-yaml');
|
|
316
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
317
|
+
const config = yaml.load(content) as any;
|
|
318
|
+
|
|
319
|
+
return config.plugins?.enabled || [];
|
|
320
|
+
}
|
|
157
321
|
}
|
|
@@ -11,6 +11,7 @@ import * as path from 'path';
|
|
|
11
11
|
import fs from 'fs-extra';
|
|
12
12
|
import { AdapterBase } from '../adapter-base.js';
|
|
13
13
|
import { AdapterOptions, AdapterFile } from '../adapter-interface.js';
|
|
14
|
+
import type { Plugin } from '../../core/types/plugin.js';
|
|
14
15
|
|
|
15
16
|
export class CopilotAdapter extends AdapterBase {
|
|
16
17
|
name = 'copilot';
|
|
@@ -178,4 +179,141 @@ Note: For better automation, consider Claude Code (full) or Cursor (semi).
|
|
|
178
179
|
Copilot is best for simple projects or when already using VS Code + Copilot.
|
|
179
180
|
`;
|
|
180
181
|
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Check if Copilot adapter supports plugins
|
|
185
|
+
*
|
|
186
|
+
* Copilot has plugin support via AGENTS.md compilation (same as Cursor)
|
|
187
|
+
*
|
|
188
|
+
* @returns boolean True for Copilot
|
|
189
|
+
*/
|
|
190
|
+
supportsPlugins(): boolean {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Compile and install a plugin for Copilot
|
|
196
|
+
*
|
|
197
|
+
* Copilot uses AGENTS.md compilation (same as Cursor)
|
|
198
|
+
*
|
|
199
|
+
* @param plugin Plugin to install
|
|
200
|
+
*/
|
|
201
|
+
async compilePlugin(plugin: Plugin): Promise<void> {
|
|
202
|
+
const projectPath = process.cwd();
|
|
203
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
204
|
+
|
|
205
|
+
console.log(`\nđĻ Compiling plugin for Copilot: ${plugin.manifest.name}`);
|
|
206
|
+
|
|
207
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
208
|
+
throw new Error('AGENTS.md not found. Run specweave init first.');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
let agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
212
|
+
|
|
213
|
+
const pluginMarker = `<!-- Plugin: ${plugin.manifest.name} -->`;
|
|
214
|
+
if (agentsMd.includes(pluginMarker)) {
|
|
215
|
+
console.log(` âšī¸ Plugin ${plugin.manifest.name} already compiled to AGENTS.md`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
let pluginSection = `\n\n${pluginMarker}\n\n`;
|
|
220
|
+
pluginSection += `# Plugin: ${plugin.manifest.name}\n\n`;
|
|
221
|
+
pluginSection += `${plugin.manifest.description}\n\n`;
|
|
222
|
+
|
|
223
|
+
if (plugin.skills.length > 0) {
|
|
224
|
+
pluginSection += `## Skills\n\n`;
|
|
225
|
+
for (const skill of plugin.skills) {
|
|
226
|
+
const skillContent = await fs.readFile(path.join(skill.path, 'SKILL.md'), 'utf-8');
|
|
227
|
+
const contentWithoutFrontmatter = skillContent.replace(/^---\n[\s\S]+?\n---\n/, '');
|
|
228
|
+
pluginSection += `### ${skill.name}\n\n${contentWithoutFrontmatter}\n\n`;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (plugin.agents.length > 0) {
|
|
233
|
+
pluginSection += `## Agents\n\n`;
|
|
234
|
+
for (const agent of plugin.agents) {
|
|
235
|
+
const agentContent = await fs.readFile(path.join(agent.path, 'AGENT.md'), 'utf-8');
|
|
236
|
+
pluginSection += `### ${agent.name}\n\n${agentContent}\n\n`;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (plugin.commands.length > 0) {
|
|
241
|
+
pluginSection += `## Commands\n\n`;
|
|
242
|
+
for (const command of plugin.commands) {
|
|
243
|
+
const commandContent = await fs.readFile(command.path, 'utf-8');
|
|
244
|
+
const contentWithoutFrontmatter = commandContent.replace(/^---\n[\s\S]+?\n---\n/, '');
|
|
245
|
+
pluginSection += `### /${command.name}\n\n${contentWithoutFrontmatter}\n\n`;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
pluginSection += `<!-- End Plugin: ${plugin.manifest.name} -->\n`;
|
|
250
|
+
|
|
251
|
+
agentsMd += pluginSection;
|
|
252
|
+
await fs.writeFile(agentsMdPath, agentsMd, 'utf-8');
|
|
253
|
+
|
|
254
|
+
console.log(` â Compiled to AGENTS.md`);
|
|
255
|
+
console.log(` â ${plugin.skills.length} skills, ${plugin.agents.length} agents, ${plugin.commands.length} commands`);
|
|
256
|
+
console.log(`\nâ
Plugin ${plugin.manifest.name} compiled for Copilot!`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Unload a plugin from Copilot
|
|
261
|
+
*/
|
|
262
|
+
async unloadPlugin(pluginName: string): Promise<void> {
|
|
263
|
+
const projectPath = process.cwd();
|
|
264
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
265
|
+
|
|
266
|
+
console.log(`\nđī¸ Unloading plugin from Copilot: ${pluginName}`);
|
|
267
|
+
|
|
268
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
269
|
+
console.warn(`â ī¸ AGENTS.md not found`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
let agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
274
|
+
|
|
275
|
+
const startMarker = `<!-- Plugin: ${pluginName} -->`;
|
|
276
|
+
const endMarker = `<!-- End Plugin: ${pluginName} -->`;
|
|
277
|
+
|
|
278
|
+
const startIndex = agentsMd.indexOf(startMarker);
|
|
279
|
+
if (startIndex === -1) {
|
|
280
|
+
console.warn(`â ī¸ Plugin ${pluginName} not found in AGENTS.md`);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const endIndex = agentsMd.indexOf(endMarker, startIndex);
|
|
285
|
+
if (endIndex === -1) {
|
|
286
|
+
console.warn(`â ī¸ Plugin ${pluginName} section malformed`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
agentsMd = agentsMd.slice(0, startIndex) + agentsMd.slice(endIndex + endMarker.length);
|
|
291
|
+
await fs.writeFile(agentsMdPath, agentsMd, 'utf-8');
|
|
292
|
+
|
|
293
|
+
console.log(` â Removed from AGENTS.md`);
|
|
294
|
+
console.log(`\nâ
Plugin ${pluginName} unloaded!`);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Get list of installed plugins for Copilot
|
|
299
|
+
*/
|
|
300
|
+
async getInstalledPlugins(): Promise<string[]> {
|
|
301
|
+
const projectPath = process.cwd();
|
|
302
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
303
|
+
|
|
304
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
309
|
+
const pluginMarkerRegex = /<!-- Plugin: (specweave-[a-z0-9-]+) -->/g;
|
|
310
|
+
const matches = agentsMd.matchAll(pluginMarkerRegex);
|
|
311
|
+
|
|
312
|
+
const plugins: string[] = [];
|
|
313
|
+
for (const match of matches) {
|
|
314
|
+
plugins.push(match[1]);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return plugins;
|
|
318
|
+
}
|
|
181
319
|
}
|
|
@@ -12,6 +12,7 @@ import * as path from 'path';
|
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import { AdapterBase } from '../adapter-base.js';
|
|
14
14
|
import { AdapterOptions, AdapterFile } from '../adapter-interface.js';
|
|
15
|
+
import type { Plugin } from '../../core/types/plugin.js';
|
|
15
16
|
|
|
16
17
|
export class CursorAdapter extends AdapterBase {
|
|
17
18
|
name = 'cursor';
|
|
@@ -219,4 +220,173 @@ Pro tip: Say "act as [role]" to follow AGENTS.md patterns:
|
|
|
219
220
|
- "act as DevOps and create infrastructure" (AGENTS.md defines DevOps role)
|
|
220
221
|
`;
|
|
221
222
|
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Check if Cursor adapter supports plugins
|
|
226
|
+
*
|
|
227
|
+
* Cursor has plugin support via AGENTS.md compilation
|
|
228
|
+
*
|
|
229
|
+
* @returns boolean True for Cursor
|
|
230
|
+
*/
|
|
231
|
+
supportsPlugins(): boolean {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Compile and install a plugin for Cursor
|
|
237
|
+
*
|
|
238
|
+
* Cursor uses AGENTS.md compilation:
|
|
239
|
+
* - Append skills to AGENTS.md
|
|
240
|
+
* - Append agents to AGENTS.md
|
|
241
|
+
* - Append commands to team commands JSON
|
|
242
|
+
*
|
|
243
|
+
* @param plugin Plugin to install
|
|
244
|
+
*/
|
|
245
|
+
async compilePlugin(plugin: Plugin): Promise<void> {
|
|
246
|
+
const projectPath = process.cwd();
|
|
247
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
248
|
+
|
|
249
|
+
console.log(`\nđĻ Compiling plugin for Cursor: ${plugin.manifest.name}`);
|
|
250
|
+
|
|
251
|
+
// Ensure AGENTS.md exists
|
|
252
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
253
|
+
throw new Error('AGENTS.md not found. Run specweave init first.');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Read current AGENTS.md
|
|
257
|
+
let agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
258
|
+
|
|
259
|
+
// Check if plugin already compiled
|
|
260
|
+
const pluginMarker = `<!-- Plugin: ${plugin.manifest.name} -->`;
|
|
261
|
+
if (agentsMd.includes(pluginMarker)) {
|
|
262
|
+
console.log(` âšī¸ Plugin ${plugin.manifest.name} already compiled to AGENTS.md`);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Generate plugin section for AGENTS.md
|
|
267
|
+
let pluginSection = `\n\n${pluginMarker}\n\n`;
|
|
268
|
+
pluginSection += `# Plugin: ${plugin.manifest.name}\n\n`;
|
|
269
|
+
pluginSection += `${plugin.manifest.description}\n\n`;
|
|
270
|
+
|
|
271
|
+
// Add skills
|
|
272
|
+
if (plugin.skills.length > 0) {
|
|
273
|
+
pluginSection += `## Skills\n\n`;
|
|
274
|
+
for (const skill of plugin.skills) {
|
|
275
|
+
const skillContent = await fs.readFile(path.join(skill.path, 'SKILL.md'), 'utf-8');
|
|
276
|
+
// Remove frontmatter for AGENTS.md
|
|
277
|
+
const contentWithoutFrontmatter = skillContent.replace(/^---\n[\s\S]+?\n---\n/, '');
|
|
278
|
+
pluginSection += `### ${skill.name}\n\n`;
|
|
279
|
+
pluginSection += `${contentWithoutFrontmatter}\n\n`;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Add agents
|
|
284
|
+
if (plugin.agents.length > 0) {
|
|
285
|
+
pluginSection += `## Agents\n\n`;
|
|
286
|
+
for (const agent of plugin.agents) {
|
|
287
|
+
const agentContent = await fs.readFile(path.join(agent.path, 'AGENT.md'), 'utf-8');
|
|
288
|
+
pluginSection += `### ${agent.name}\n\n`;
|
|
289
|
+
pluginSection += `${agentContent}\n\n`;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Add commands
|
|
294
|
+
if (plugin.commands.length > 0) {
|
|
295
|
+
pluginSection += `## Commands\n\n`;
|
|
296
|
+
for (const command of plugin.commands) {
|
|
297
|
+
const commandContent = await fs.readFile(command.path, 'utf-8');
|
|
298
|
+
// Remove frontmatter
|
|
299
|
+
const contentWithoutFrontmatter = commandContent.replace(/^---\n[\s\S]+?\n---\n/, '');
|
|
300
|
+
pluginSection += `### /${command.name}\n\n`;
|
|
301
|
+
pluginSection += `${contentWithoutFrontmatter}\n\n`;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
pluginSection += `<!-- End Plugin: ${plugin.manifest.name} -->\n`;
|
|
306
|
+
|
|
307
|
+
// Append to AGENTS.md
|
|
308
|
+
agentsMd += pluginSection;
|
|
309
|
+
await fs.writeFile(agentsMdPath, agentsMd, 'utf-8');
|
|
310
|
+
|
|
311
|
+
console.log(` â Compiled to AGENTS.md`);
|
|
312
|
+
console.log(` â ${plugin.skills.length} skills added`);
|
|
313
|
+
console.log(` â ${plugin.agents.length} agents added`);
|
|
314
|
+
console.log(` â ${plugin.commands.length} commands added`);
|
|
315
|
+
|
|
316
|
+
console.log(`\nâ
Plugin ${plugin.manifest.name} compiled for Cursor!`);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Unload a plugin from Cursor
|
|
321
|
+
*
|
|
322
|
+
* Removes plugin section from AGENTS.md
|
|
323
|
+
*
|
|
324
|
+
* @param pluginName Name of plugin to unload
|
|
325
|
+
*/
|
|
326
|
+
async unloadPlugin(pluginName: string): Promise<void> {
|
|
327
|
+
const projectPath = process.cwd();
|
|
328
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
329
|
+
|
|
330
|
+
console.log(`\nđī¸ Unloading plugin from Cursor: ${pluginName}`);
|
|
331
|
+
|
|
332
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
333
|
+
console.warn(`â ī¸ AGENTS.md not found`);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Read AGENTS.md
|
|
338
|
+
let agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
339
|
+
|
|
340
|
+
// Find plugin section
|
|
341
|
+
const startMarker = `<!-- Plugin: ${pluginName} -->`;
|
|
342
|
+
const endMarker = `<!-- End Plugin: ${pluginName} -->`;
|
|
343
|
+
|
|
344
|
+
const startIndex = agentsMd.indexOf(startMarker);
|
|
345
|
+
if (startIndex === -1) {
|
|
346
|
+
console.warn(`â ī¸ Plugin ${pluginName} not found in AGENTS.md`);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const endIndex = agentsMd.indexOf(endMarker, startIndex);
|
|
351
|
+
if (endIndex === -1) {
|
|
352
|
+
console.warn(`â ī¸ Plugin ${pluginName} section malformed in AGENTS.md`);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Remove plugin section
|
|
357
|
+
agentsMd = agentsMd.slice(0, startIndex) + agentsMd.slice(endIndex + endMarker.length);
|
|
358
|
+
|
|
359
|
+
// Write back
|
|
360
|
+
await fs.writeFile(agentsMdPath, agentsMd, 'utf-8');
|
|
361
|
+
|
|
362
|
+
console.log(` â Removed from AGENTS.md`);
|
|
363
|
+
console.log(`\nâ
Plugin ${pluginName} unloaded!`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Get list of installed plugins for Cursor
|
|
368
|
+
*
|
|
369
|
+
* Parses AGENTS.md for plugin markers
|
|
370
|
+
*
|
|
371
|
+
* @returns Array of installed plugin names
|
|
372
|
+
*/
|
|
373
|
+
async getInstalledPlugins(): Promise<string[]> {
|
|
374
|
+
const projectPath = process.cwd();
|
|
375
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
376
|
+
|
|
377
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
382
|
+
const pluginMarkerRegex = /<!-- Plugin: (specweave-[a-z0-9-]+) -->/g;
|
|
383
|
+
const matches = agentsMd.matchAll(pluginMarkerRegex);
|
|
384
|
+
|
|
385
|
+
const plugins: string[] = [];
|
|
386
|
+
for (const match of matches) {
|
|
387
|
+
plugins.push(match[1]);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return plugins;
|
|
391
|
+
}
|
|
222
392
|
}
|
|
@@ -12,6 +12,7 @@ import * as path from 'path';
|
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import { AdapterBase } from '../adapter-base.js';
|
|
14
14
|
import { AdapterOptions, AdapterFile } from '../adapter-interface.js';
|
|
15
|
+
import type { Plugin } from '../../core/types/plugin.js';
|
|
15
16
|
|
|
16
17
|
export class GenericAdapter extends AdapterBase {
|
|
17
18
|
name = 'generic';
|
|
@@ -160,4 +161,140 @@ You're ready to build with SpecWeave using ANY AI tool!
|
|
|
160
161
|
Remember: AGENTS.md is the universal standard - it works everywhere!
|
|
161
162
|
`;
|
|
162
163
|
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Check if Generic adapter supports plugins
|
|
167
|
+
*
|
|
168
|
+
* Generic has manual plugin support via AGENTS.md
|
|
169
|
+
*
|
|
170
|
+
* @returns boolean True
|
|
171
|
+
*/
|
|
172
|
+
supportsPlugins(): boolean {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Compile and install a plugin for Generic adapter
|
|
178
|
+
*
|
|
179
|
+
* Appends plugin content to AGENTS.md for manual copy-paste workflows
|
|
180
|
+
*
|
|
181
|
+
* @param plugin Plugin to install
|
|
182
|
+
*/
|
|
183
|
+
async compilePlugin(plugin: Plugin): Promise<void> {
|
|
184
|
+
const projectPath = process.cwd();
|
|
185
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
186
|
+
|
|
187
|
+
console.log(`\nđĻ Adding plugin to AGENTS.md: ${plugin.manifest.name}`);
|
|
188
|
+
|
|
189
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
190
|
+
throw new Error('AGENTS.md not found. Run specweave init first.');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
194
|
+
|
|
195
|
+
const pluginMarker = `<!-- Plugin: ${plugin.manifest.name} -->`;
|
|
196
|
+
if (agentsMd.includes(pluginMarker)) {
|
|
197
|
+
console.log(` âšī¸ Plugin ${plugin.manifest.name} already in AGENTS.md`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let pluginSection = `\n\n${pluginMarker}\n\n`;
|
|
202
|
+
pluginSection += `# Plugin: ${plugin.manifest.name}\n\n`;
|
|
203
|
+
pluginSection += `${plugin.manifest.description}\n\n`;
|
|
204
|
+
|
|
205
|
+
if (plugin.skills.length > 0) {
|
|
206
|
+
pluginSection += `## Skills\n\n`;
|
|
207
|
+
for (const skill of plugin.skills) {
|
|
208
|
+
const skillContent = await fs.readFile(path.join(skill.path, 'SKILL.md'), 'utf-8');
|
|
209
|
+
const contentWithoutFrontmatter = skillContent.replace(/^---\n[\s\S]+?\n---\n/, '');
|
|
210
|
+
pluginSection += `### ${skill.name}\n\n${contentWithoutFrontmatter}\n\n`;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (plugin.agents.length > 0) {
|
|
215
|
+
pluginSection += `## Agents\n\n`;
|
|
216
|
+
for (const agent of plugin.agents) {
|
|
217
|
+
const agentContent = await fs.readFile(path.join(agent.path, 'AGENT.md'), 'utf-8');
|
|
218
|
+
pluginSection += `### ${agent.name}\n\n${agentContent}\n\n`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (plugin.commands.length > 0) {
|
|
223
|
+
pluginSection += `## Workflows (Manual)\n\n`;
|
|
224
|
+
for (const command of plugin.commands) {
|
|
225
|
+
const commandContent = await fs.readFile(command.path, 'utf-8');
|
|
226
|
+
const contentWithoutFrontmatter = commandContent.replace(/^---\n[\s\S]+?\n---\n/, '');
|
|
227
|
+
pluginSection += `### ${command.name.replace('specweave.', '')}\n\n${contentWithoutFrontmatter}\n\n`;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
pluginSection += `<!-- End Plugin: ${plugin.manifest.name} -->\n`;
|
|
232
|
+
|
|
233
|
+
agentsMd += pluginSection;
|
|
234
|
+
await fs.writeFile(agentsMdPath, agentsMd, 'utf-8');
|
|
235
|
+
|
|
236
|
+
console.log(` â Added to AGENTS.md (copy-paste workflows)`);
|
|
237
|
+
console.log(`\nâ
Plugin ${plugin.manifest.name} available for manual use!`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Unload a plugin from Generic adapter
|
|
242
|
+
*/
|
|
243
|
+
async unloadPlugin(pluginName: string): Promise<void> {
|
|
244
|
+
const projectPath = process.cwd();
|
|
245
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
246
|
+
|
|
247
|
+
console.log(`\nđī¸ Removing plugin from AGENTS.md: ${pluginName}`);
|
|
248
|
+
|
|
249
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
250
|
+
console.warn(`â ī¸ AGENTS.md not found`);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
255
|
+
|
|
256
|
+
const startMarker = `<!-- Plugin: ${pluginName} -->`;
|
|
257
|
+
const endMarker = `<!-- End Plugin: ${pluginName} -->`;
|
|
258
|
+
|
|
259
|
+
const startIndex = agentsMd.indexOf(startMarker);
|
|
260
|
+
if (startIndex === -1) {
|
|
261
|
+
console.warn(`â ī¸ Plugin ${pluginName} not found in AGENTS.md`);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const endIndex = agentsMd.indexOf(endMarker, startIndex);
|
|
266
|
+
if (endIndex === -1) {
|
|
267
|
+
console.warn(`â ī¸ Plugin ${pluginName} section malformed`);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
agentsMd = agentsMd.slice(0, startIndex) + agentsMd.slice(endIndex + endMarker.length);
|
|
272
|
+
await fs.writeFile(agentsMdPath, agentsMd, 'utf-8');
|
|
273
|
+
|
|
274
|
+
console.log(` â Removed from AGENTS.md`);
|
|
275
|
+
console.log(`\nâ
Plugin ${pluginName} removed!`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Get list of installed plugins for Generic adapter
|
|
280
|
+
*/
|
|
281
|
+
async getInstalledPlugins(): Promise<string[]> {
|
|
282
|
+
const projectPath = process.cwd();
|
|
283
|
+
const agentsMdPath = path.join(projectPath, 'AGENTS.md');
|
|
284
|
+
|
|
285
|
+
if (!(await fs.pathExists(agentsMdPath))) {
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const agentsMd = await fs.readFile(agentsMdPath, 'utf-8');
|
|
290
|
+
const pluginMarkerRegex = /<!-- Plugin: (specweave-[a-z0-9-]+) -->/g;
|
|
291
|
+
const matches = agentsMd.matchAll(pluginMarkerRegex);
|
|
292
|
+
|
|
293
|
+
const plugins: string[] = [];
|
|
294
|
+
for (const match of matches) {
|
|
295
|
+
plugins.push(match[1]);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return plugins;
|
|
299
|
+
}
|
|
163
300
|
}
|
|
@@ -3,6 +3,9 @@ name: architect
|
|
|
3
3
|
description: System Architect and technical design expert. Creates system architecture, technical specifications, Architecture Decision Records (ADRs), component designs, API contracts, data models, and deployment architectures. Handles design patterns, scalability planning, technology stack decisions, microservices architecture, event-driven systems, CQRS, domain-driven design. Activates for: architecture, system design, technical design, ADR, architecture decision record, design patterns, microservices, API design, data model, database schema, scalability, performance architecture, technology stack, tech stack selection, distributed systems, event-driven, CQRS, DDD, domain model, component architecture, integration patterns, CAP theorem, consistency, availability, partition tolerance.
|
|
4
4
|
tools: Read, Write, Edit
|
|
5
5
|
model: claude-sonnet-4-5-20250929
|
|
6
|
+
model_preference: sonnet
|
|
7
|
+
cost_profile: planning
|
|
8
|
+
fallback_behavior: strict
|
|
6
9
|
---
|
|
7
10
|
|
|
8
11
|
# Architect Agent - System Architecture & Technical Design Expert
|