specweave 0.3.8 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,410 @@
1
+ /**
2
+ * Skills Index Generator
3
+ *
4
+ * Generates SKILLS-INDEX.md from all SKILL.md files
5
+ * Simulates Claude Code's progressive disclosure for non-native tools
6
+ *
7
+ * This allows GitHub Copilot, Cursor, and other AI tools to:
8
+ * 1. Quickly scan all available skills (single file read)
9
+ * 2. Match user requests to activation keywords
10
+ * 3. Load full SKILL.md only when relevant
11
+ * 4. Follow skill workflows for consistent output
12
+ *
13
+ * Usage:
14
+ * import { generateSkillsIndex } from './generate-skills-index';
15
+ * await generateSkillsIndex();
16
+ *
17
+ * Or run directly:
18
+ * npx ts-node src/utils/generate-skills-index.ts
19
+ */
20
+ import * as fs from 'fs';
21
+ import * as path from 'path';
22
+ import * as yaml from 'js-yaml';
23
+ import { fileURLToPath } from 'url';
24
+ import { dirname } from 'path';
25
+ const __filename = fileURLToPath(import.meta.url);
26
+ const __dirname = dirname(__filename);
27
+ /**
28
+ * Skill categories for organization
29
+ */
30
+ const SkillCategory = {
31
+ FRAMEWORK: 'Framework Core',
32
+ INTEGRATIONS: 'External Integrations',
33
+ ARCHITECTURE: 'Architecture & Design',
34
+ DEVELOPMENT: 'Development',
35
+ QUALITY: 'Quality & Testing',
36
+ INFRASTRUCTURE: 'Infrastructure',
37
+ DOCUMENTATION: 'Documentation',
38
+ ORCHESTRATION: 'Orchestration & Planning',
39
+ OTHER: 'Other',
40
+ };
41
+ /**
42
+ * Parse YAML frontmatter from SKILL.md
43
+ */
44
+ function parseSkillMetadata(content, filePath) {
45
+ try {
46
+ // Extract YAML frontmatter
47
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
48
+ if (!frontmatterMatch) {
49
+ console.warn(`⚠️ No frontmatter found in: ${filePath}`);
50
+ return null;
51
+ }
52
+ let frontmatter;
53
+ try {
54
+ frontmatter = yaml.load(frontmatterMatch[1]);
55
+ }
56
+ catch (yamlError) {
57
+ // If YAML parsing fails, try manual parsing for simple key-value pairs
58
+ // This handles cases where descriptions have unquoted colons
59
+ frontmatter = {};
60
+ const lines = frontmatterMatch[1].split('\n');
61
+ for (const line of lines) {
62
+ const colonIndex = line.indexOf(':');
63
+ if (colonIndex > 0) {
64
+ const key = line.substring(0, colonIndex).trim();
65
+ const value = line.substring(colonIndex + 1).trim();
66
+ frontmatter[key] = value;
67
+ }
68
+ }
69
+ }
70
+ if (!frontmatter.name || !frontmatter.description) {
71
+ console.warn(`⚠️ Missing name or description in: ${filePath}`);
72
+ return null;
73
+ }
74
+ // Extract activation keywords from description
75
+ // Look for "Activates for:" or "Activates when user mentions:" in description
76
+ const activationKeywords = [];
77
+ const activatesMatch = frontmatter.description.match(/Activates (?:for|when user mentions):\s*(.+?)(?:\.|$)/i);
78
+ if (activatesMatch) {
79
+ // Split by comma and clean up
80
+ const keywords = activatesMatch[1]
81
+ .split(',')
82
+ .map((k) => k.trim())
83
+ .filter((k) => k.length > 0);
84
+ activationKeywords.push(...keywords);
85
+ }
86
+ // Determine category from skill name
87
+ const category = categorizeSkill(frontmatter.name, frontmatter.description);
88
+ // Relative path from .claude/skills/
89
+ const skillDir = path.basename(path.dirname(filePath));
90
+ const location = `.claude/skills/${skillDir}/SKILL.md`;
91
+ return {
92
+ name: frontmatter.name,
93
+ description: frontmatter.description,
94
+ activationKeywords,
95
+ location,
96
+ allowedTools: frontmatter['allowed-tools'],
97
+ category,
98
+ };
99
+ }
100
+ catch (error) {
101
+ console.error(`❌ Error parsing ${filePath}:`, error);
102
+ return null;
103
+ }
104
+ }
105
+ /**
106
+ * Categorize skill based on name and description
107
+ */
108
+ function categorizeSkill(name, description) {
109
+ const nameLower = name.toLowerCase();
110
+ const descLower = description.toLowerCase();
111
+ // Framework core
112
+ if (nameLower.includes('increment') ||
113
+ nameLower.includes('context') ||
114
+ nameLower.includes('specweave') ||
115
+ nameLower.includes('skill-creator')) {
116
+ return SkillCategory.FRAMEWORK;
117
+ }
118
+ // Integrations
119
+ if (nameLower.includes('jira') ||
120
+ nameLower.includes('ado') ||
121
+ nameLower.includes('github') ||
122
+ nameLower.includes('sync') ||
123
+ nameLower.includes('figma-mcp')) {
124
+ return SkillCategory.INTEGRATIONS;
125
+ }
126
+ // Architecture & Design
127
+ if (nameLower.includes('diagram') ||
128
+ nameLower.includes('architect') ||
129
+ nameLower.includes('design-system') ||
130
+ descLower.includes('architecture') ||
131
+ descLower.includes('c4 model')) {
132
+ return SkillCategory.ARCHITECTURE;
133
+ }
134
+ // Development
135
+ if (nameLower.includes('frontend') ||
136
+ nameLower.includes('backend') ||
137
+ nameLower.includes('nodejs') ||
138
+ nameLower.includes('python') ||
139
+ nameLower.includes('dotnet') ||
140
+ nameLower.includes('nextjs') ||
141
+ nameLower.includes('figma-implementer') ||
142
+ nameLower.includes('figma-to-code')) {
143
+ return SkillCategory.DEVELOPMENT;
144
+ }
145
+ // Quality & Testing
146
+ if (nameLower.includes('quality') ||
147
+ nameLower.includes('test') ||
148
+ nameLower.includes('e2e') ||
149
+ nameLower.includes('playwright') ||
150
+ descLower.includes('testing') ||
151
+ descLower.includes('validation')) {
152
+ return SkillCategory.QUALITY;
153
+ }
154
+ // Infrastructure
155
+ if (nameLower.includes('hetzner') ||
156
+ nameLower.includes('provision') ||
157
+ nameLower.includes('cost-optimizer') ||
158
+ descLower.includes('infrastructure') ||
159
+ descLower.includes('deployment') ||
160
+ descLower.includes('hosting')) {
161
+ return SkillCategory.INFRASTRUCTURE;
162
+ }
163
+ // Documentation
164
+ if (nameLower.includes('docusaurus') ||
165
+ nameLower.includes('docs') ||
166
+ nameLower.includes('figma-designer') ||
167
+ descLower.includes('documentation') ||
168
+ descLower.includes('generating documentation')) {
169
+ return SkillCategory.DOCUMENTATION;
170
+ }
171
+ // Orchestration
172
+ if (nameLower.includes('orchestrat') ||
173
+ nameLower.includes('role-orchestrator') ||
174
+ nameLower.includes('skill-router') ||
175
+ nameLower.includes('brainstorm') ||
176
+ descLower.includes('multi-agent') ||
177
+ descLower.includes('coordinates') ||
178
+ descLower.includes('routing')) {
179
+ return SkillCategory.ORCHESTRATION;
180
+ }
181
+ return SkillCategory.OTHER;
182
+ }
183
+ /**
184
+ * Generate markdown for skills index
185
+ */
186
+ function generateIndexMarkdown(skills) {
187
+ const now = new Date().toISOString();
188
+ const totalSkills = skills.length;
189
+ // Group skills by category
190
+ const categorized = new Map();
191
+ for (const skill of skills) {
192
+ const category = skill.category;
193
+ if (!categorized.has(category)) {
194
+ categorized.set(category, []);
195
+ }
196
+ categorized.get(category).push(skill);
197
+ }
198
+ // Sort skills within each category alphabetically
199
+ for (const skillList of categorized.values()) {
200
+ skillList.sort((a, b) => a.name.localeCompare(b.name));
201
+ }
202
+ let markdown = `# SpecWeave Skills Index
203
+
204
+ **Purpose**: Quick reference for all available skills. Read this file BEFORE starting any task.
205
+
206
+ **Last Updated**: ${now} (auto-generated, do not edit manually)
207
+
208
+ **Total Skills**: ${totalSkills}
209
+
210
+ ---
211
+
212
+ ## 🚀 Quick Start (Progressive Disclosure)
213
+
214
+ **MANDATORY**: Skills are your expert manuals. Always check for relevant skills BEFORE starting implementation.
215
+
216
+ ### Progressive Disclosure Pattern
217
+
218
+ 1. **Scan this index** to find skills matching your task
219
+ 2. **Match activation keywords** to your current request
220
+ 3. **Load full SKILL.md** for matching skills
221
+ 4. **Follow the workflow** in SKILL.md precisely
222
+
223
+ ### Example Workflow
224
+
225
+ \`\`\`
226
+ User asks: "Plan a new feature for user authentication"
227
+
228
+ Step 1: Scan this index → Find "increment-planner" skill
229
+ Step 2: Check keywords → Matches "feature planning", "create increment"
230
+ Step 3: Load skill → cat .claude/skills/increment-planner/SKILL.md
231
+ Step 4: Execute → Follow the increment planning workflow
232
+ \`\`\`
233
+
234
+ ---
235
+
236
+ ## 📚 All Available Skills
237
+
238
+ `;
239
+ // Define category order
240
+ const categoryOrder = [
241
+ SkillCategory.FRAMEWORK,
242
+ SkillCategory.ORCHESTRATION,
243
+ SkillCategory.INTEGRATIONS,
244
+ SkillCategory.ARCHITECTURE,
245
+ SkillCategory.DEVELOPMENT,
246
+ SkillCategory.QUALITY,
247
+ SkillCategory.INFRASTRUCTURE,
248
+ SkillCategory.DOCUMENTATION,
249
+ SkillCategory.OTHER,
250
+ ];
251
+ // Generate sections by category
252
+ for (const category of categoryOrder) {
253
+ const skillList = categorized.get(category);
254
+ if (!skillList || skillList.length === 0)
255
+ continue;
256
+ markdown += `\n### ${category}\n\n`;
257
+ for (const skill of skillList) {
258
+ markdown += `#### ${skill.name}\n\n`;
259
+ markdown += `**Description**: ${skill.description}\n\n`;
260
+ if (skill.activationKeywords.length > 0) {
261
+ markdown += `**Activates for**: ${skill.activationKeywords.join(', ')}\n\n`;
262
+ }
263
+ markdown += `**Location**: \`${skill.location}\`\n\n`;
264
+ if (skill.allowedTools && Array.isArray(skill.allowedTools)) {
265
+ markdown += `**Allowed tools**: ${skill.allowedTools.join(', ')}\n\n`;
266
+ }
267
+ else if (skill.allowedTools && typeof skill.allowedTools === 'string') {
268
+ markdown += `**Allowed tools**: ${skill.allowedTools}\n\n`;
269
+ }
270
+ markdown += '---\n\n';
271
+ }
272
+ }
273
+ // Add usage guide
274
+ markdown += `
275
+ ## 💡 How Skills Work
276
+
277
+ **Level 1 - Discovery (this file)**:
278
+ - Scan activation keywords
279
+ - Match to your current task
280
+ - Identify 1-3 relevant skills
281
+
282
+ **Level 2 - Deep Dive (SKILL.md)**:
283
+ - Load full skill documentation
284
+ - Read required prerequisites
285
+ - Follow step-by-step workflow
286
+
287
+ **Level 3 - Execution**:
288
+ - Apply skill's instructions
289
+ - Use recommended tools
290
+ - Follow SpecWeave best practices
291
+
292
+ ---
293
+
294
+ ## 🎯 Task → Skill Matching Guide
295
+
296
+ | Your Task | Relevant Skill | Keywords |
297
+ |-----------|---------------|----------|
298
+ | "Plan a new feature" | \`increment-planner\` | "feature planning", "create increment" |
299
+ | "Sync to JIRA" | \`jira-sync\` | "JIRA sync", "create JIRA issue" |
300
+ | "Create diagram" | \`diagrams-architect\` | "architecture diagram", "C4 diagram" |
301
+ | "Build React UI" | \`frontend\` | "React", "components", "UI" |
302
+ | "Deploy to cloud" | \`hetzner-provisioner\` | "deploy", "infrastructure" |
303
+ | "Quality check" | \`increment-quality-judge\` | "quality check", "assess spec" |
304
+ | "E2E testing" | \`e2e-playwright\` | "E2E test", "browser test" |
305
+ | "Generate docs site" | \`docusaurus\` | "documentation site", "docs" |
306
+
307
+ ---
308
+
309
+ ## ⚡ Why Skills Matter
310
+
311
+ **Without skills**:
312
+ - ❌ Reinvent workflows every session
313
+ - ❌ Inconsistent increment structure
314
+ - ❌ Miss SpecWeave conventions
315
+ - ❌ Waste tokens on irrelevant docs
316
+
317
+ **With skills**:
318
+ - ✅ Proven workflows ready to use
319
+ - ✅ Consistent high-quality output
320
+ - ✅ SpecWeave best practices enforced
321
+ - ✅ Efficient token usage (load only what's needed)
322
+
323
+ ---
324
+
325
+ ## 🔧 For AI Tool Developers
326
+
327
+ This index simulates Claude Code's native progressive disclosure:
328
+ - Claude pre-loads skill metadata at startup (name + description)
329
+ - Other tools read this index file for same benefit
330
+ - Single file read replaces ${totalSkills} individual file scans
331
+ - Token savings: ~97% (1 file vs ${totalSkills} files)
332
+
333
+ **How to use in your AI tool**:
334
+ 1. Load this file at session start
335
+ 2. Parse activation keywords
336
+ 3. Match user requests to keywords
337
+ 4. Load full SKILL.md when matched
338
+ 5. Execute skill workflow
339
+
340
+ ---
341
+
342
+ **Generated by**: \`src/utils/generate-skills-index.ts\`
343
+
344
+ **Regenerate with**: \`npm run generate-skills-index\`
345
+ `;
346
+ return markdown;
347
+ }
348
+ /**
349
+ * Main function: Generate skills index
350
+ */
351
+ export async function generateSkillsIndex(outputPath) {
352
+ console.log('🔍 Scanning skills...');
353
+ // Determine skills directory
354
+ const skillsDir = path.join(__dirname, '../../src/skills');
355
+ if (!fs.existsSync(skillsDir)) {
356
+ throw new Error(`Skills directory not found: ${skillsDir}`);
357
+ }
358
+ // Scan all SKILL.md files
359
+ const skills = [];
360
+ const skillDirs = fs.readdirSync(skillsDir).filter(name => {
361
+ const fullPath = path.join(skillsDir, name);
362
+ return fs.statSync(fullPath).isDirectory();
363
+ });
364
+ for (const skillDir of skillDirs) {
365
+ const skillPath = path.join(skillsDir, skillDir, 'SKILL.md');
366
+ if (fs.existsSync(skillPath)) {
367
+ const content = fs.readFileSync(skillPath, 'utf-8');
368
+ const metadata = parseSkillMetadata(content, skillPath);
369
+ if (metadata) {
370
+ skills.push(metadata);
371
+ }
372
+ }
373
+ }
374
+ console.log(`✅ Found ${skills.length} skills`);
375
+ // Generate markdown
376
+ const markdown = generateIndexMarkdown(skills);
377
+ // Determine output path
378
+ const defaultOutputPath = path.join(__dirname, '../../src/skills/SKILLS-INDEX.md');
379
+ const finalOutputPath = outputPath || defaultOutputPath;
380
+ // Write to file
381
+ fs.writeFileSync(finalOutputPath, markdown, 'utf-8');
382
+ console.log(`✅ Generated skills index: ${finalOutputPath}`);
383
+ console.log('');
384
+ console.log('📊 Summary:');
385
+ console.log(` Total skills: ${skills.length}`);
386
+ // Count by category
387
+ const categoryCounts = new Map();
388
+ for (const skill of skills) {
389
+ categoryCounts.set(skill.category, (categoryCounts.get(skill.category) || 0) + 1);
390
+ }
391
+ for (const [category, count] of Array.from(categoryCounts.entries()).sort((a, b) => b[1] - a[1])) {
392
+ console.log(` ${category}: ${count}`);
393
+ }
394
+ }
395
+ /**
396
+ * CLI entry point (check if this file is being run directly)
397
+ */
398
+ if (import.meta.url === `file://${process.argv[1]}`) {
399
+ generateSkillsIndex()
400
+ .then(() => {
401
+ console.log('');
402
+ console.log('✅ Skills index generation complete!');
403
+ process.exit(0);
404
+ })
405
+ .catch((error) => {
406
+ console.error('❌ Error generating skills index:', error);
407
+ process.exit(1);
408
+ });
409
+ }
410
+ //# sourceMappingURL=generate-skills-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-skills-index.js","sourceRoot":"","sources":["../../src/utils/generate-skills-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Model Selection Utilities
3
+ *
4
+ * Intelligent model selection for SpecWeave tasks based on complexity,
5
+ * instruction detail, and task characteristics.
6
+ *
7
+ * Strategy:
8
+ * - Haiku: Detailed instructions, clear acceptance criteria, mechanical work
9
+ * - Sonnet: Complex decisions, architecture, creative problem-solving
10
+ * - Opus: Critical architecture, high-stakes decisions (rare)
11
+ */
12
+ export type ModelTier = 'haiku' | 'sonnet' | 'opus';
13
+ export interface Task {
14
+ id: string;
15
+ content: string;
16
+ description?: string;
17
+ acceptanceCriteria?: string[];
18
+ specReference?: string;
19
+ planReference?: string;
20
+ priority?: 'P1' | 'P2' | 'P3';
21
+ estimatedHours?: number;
22
+ }
23
+ export interface DetectionResult {
24
+ model: ModelTier;
25
+ confidence: number;
26
+ reasoning: string;
27
+ }
28
+ /**
29
+ * Detects the optimal model for a given task
30
+ *
31
+ * @param task - The task to analyze
32
+ * @param options - Additional context (spec detail level, etc.)
33
+ * @returns Detection result with model recommendation and reasoning
34
+ */
35
+ export declare function detectModelForTask(task: Task, options?: {
36
+ specDetailLevel?: number;
37
+ hasDetailedPlan?: boolean;
38
+ isArchitectural?: boolean;
39
+ }): DetectionResult;
40
+ /**
41
+ * Batch detect models for multiple tasks
42
+ * Useful when generating tasks.md from plan.md
43
+ */
44
+ export declare function detectModelsForTasks(tasks: Task[], options?: {
45
+ specDetailLevel?: number;
46
+ hasDetailedPlan?: boolean;
47
+ }): Map<string, DetectionResult>;
48
+ /**
49
+ * Format model hint for tasks.md
50
+ *
51
+ * @param model - The model tier
52
+ * @returns Formatted string for inclusion in tasks.md
53
+ */
54
+ export declare function formatModelHint(model: ModelTier): string;
55
+ /**
56
+ * Parse model hint from tasks.md line
57
+ *
58
+ * @param line - A line from tasks.md
59
+ * @returns Detected model or null
60
+ */
61
+ export declare function parseModelHint(line: string): ModelTier | null;
62
+ /**
63
+ * Cost estimation utilities
64
+ */
65
+ export declare function estimateTaskCost(model: ModelTier, estimatedTokens?: number): number;
66
+ /**
67
+ * Calculate total cost savings when using smart model selection
68
+ */
69
+ export declare function calculateCostSavings(tasksWithModels: Map<string, ModelTier>, averageTokensPerTask?: number): {
70
+ optimizedCost: number;
71
+ allSonnetCost: number;
72
+ savings: number;
73
+ savingsPercent: number;
74
+ };
75
+ //# sourceMappingURL=model-selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-selection.d.ts","sourceRoot":"","sources":["../../src/utils/model-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AA4BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,GACL,eAAe,CAkGjB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,OAAO,GAAE;IACP,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;CACtB,GACL,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAS9B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAQxD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAU7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAChB,eAAe,GAAE,MAAa,GAC7B,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EACvC,oBAAoB,GAAE,MAAa,GAClC;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB,CAkBA"}