wogiflow 1.0.0
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/.workflow/agents/reviewer.md +81 -0
- package/.workflow/agents/security.md +94 -0
- package/.workflow/agents/story-writer.md +58 -0
- package/.workflow/bridges/base-bridge.js +395 -0
- package/.workflow/bridges/claude-bridge.js +434 -0
- package/.workflow/bridges/index.js +130 -0
- package/.workflow/lib/assumption-detector.js +481 -0
- package/.workflow/lib/config-substitution.js +371 -0
- package/.workflow/lib/failure-categories.js +478 -0
- package/.workflow/state/app-map.md.template +15 -0
- package/.workflow/state/architecture.md.template +24 -0
- package/.workflow/state/component-index.json.template +5 -0
- package/.workflow/state/decisions.md.template +15 -0
- package/.workflow/state/feedback-patterns.md.template +9 -0
- package/.workflow/state/knowledge-sync.json.template +6 -0
- package/.workflow/state/progress.md.template +14 -0
- package/.workflow/state/ready.json.template +7 -0
- package/.workflow/state/request-log.md.template +14 -0
- package/.workflow/state/session-state.json.template +11 -0
- package/.workflow/state/stack.md.template +33 -0
- package/.workflow/state/testing.md.template +36 -0
- package/.workflow/templates/claude-md.hbs +257 -0
- package/.workflow/templates/correction-report.md +67 -0
- package/.workflow/templates/gemini-md.hbs +52 -0
- package/README.md +1802 -0
- package/bin/flow +205 -0
- package/lib/index.js +33 -0
- package/lib/installer.js +467 -0
- package/lib/release-channel.js +269 -0
- package/lib/skill-registry.js +526 -0
- package/lib/upgrader.js +401 -0
- package/lib/utils.js +305 -0
- package/package.json +64 -0
- package/scripts/flow +985 -0
- package/scripts/flow-adaptive-learning.js +1259 -0
- package/scripts/flow-aggregate.js +488 -0
- package/scripts/flow-archive +133 -0
- package/scripts/flow-auto-context.js +1015 -0
- package/scripts/flow-auto-learn.js +615 -0
- package/scripts/flow-bridge.js +223 -0
- package/scripts/flow-browser-suggest.js +316 -0
- package/scripts/flow-bug.js +247 -0
- package/scripts/flow-cascade.js +711 -0
- package/scripts/flow-changelog +85 -0
- package/scripts/flow-checkpoint.js +483 -0
- package/scripts/flow-cli.js +403 -0
- package/scripts/flow-code-intelligence.js +760 -0
- package/scripts/flow-complexity.js +502 -0
- package/scripts/flow-config-set.js +152 -0
- package/scripts/flow-constants.js +157 -0
- package/scripts/flow-context +152 -0
- package/scripts/flow-context-init.js +482 -0
- package/scripts/flow-context-monitor.js +384 -0
- package/scripts/flow-context-scoring.js +886 -0
- package/scripts/flow-correct.js +458 -0
- package/scripts/flow-damage-control.js +985 -0
- package/scripts/flow-deps +101 -0
- package/scripts/flow-diff.js +700 -0
- package/scripts/flow-done +151 -0
- package/scripts/flow-done.js +489 -0
- package/scripts/flow-durable-session.js +1541 -0
- package/scripts/flow-entropy-monitor.js +345 -0
- package/scripts/flow-export-profile +349 -0
- package/scripts/flow-export-scanner.js +1046 -0
- package/scripts/flow-figma-confirm.js +400 -0
- package/scripts/flow-figma-extract.js +496 -0
- package/scripts/flow-figma-generate.js +683 -0
- package/scripts/flow-figma-index.js +909 -0
- package/scripts/flow-figma-match.js +617 -0
- package/scripts/flow-figma-mcp-server.js +518 -0
- package/scripts/flow-figma-pipeline.js +414 -0
- package/scripts/flow-file-ops.js +301 -0
- package/scripts/flow-gate-confidence.js +825 -0
- package/scripts/flow-guided-edit.js +659 -0
- package/scripts/flow-health +185 -0
- package/scripts/flow-health.js +413 -0
- package/scripts/flow-hooks.js +556 -0
- package/scripts/flow-http-client.js +249 -0
- package/scripts/flow-hybrid-detect.js +167 -0
- package/scripts/flow-hybrid-interactive.js +591 -0
- package/scripts/flow-hybrid-test.js +152 -0
- package/scripts/flow-import-profile +439 -0
- package/scripts/flow-init +253 -0
- package/scripts/flow-instruction-richness.js +827 -0
- package/scripts/flow-jira-integration.js +579 -0
- package/scripts/flow-knowledge-router.js +522 -0
- package/scripts/flow-knowledge-sync.js +589 -0
- package/scripts/flow-linear-integration.js +631 -0
- package/scripts/flow-links.js +774 -0
- package/scripts/flow-log-manager.js +559 -0
- package/scripts/flow-loop-enforcer.js +1246 -0
- package/scripts/flow-loop-retry-learning.js +630 -0
- package/scripts/flow-lsp.js +923 -0
- package/scripts/flow-map-index +348 -0
- package/scripts/flow-map-sync +201 -0
- package/scripts/flow-memory-blocks.js +668 -0
- package/scripts/flow-memory-compactor.js +350 -0
- package/scripts/flow-memory-db.js +1110 -0
- package/scripts/flow-memory-sync.js +484 -0
- package/scripts/flow-metrics.js +353 -0
- package/scripts/flow-migrate-ids.js +370 -0
- package/scripts/flow-model-adapter.js +802 -0
- package/scripts/flow-model-router.js +884 -0
- package/scripts/flow-models.js +1231 -0
- package/scripts/flow-morning.js +517 -0
- package/scripts/flow-multi-approach.js +660 -0
- package/scripts/flow-new-feature +86 -0
- package/scripts/flow-onboard +1042 -0
- package/scripts/flow-orchestrate-llm.js +459 -0
- package/scripts/flow-orchestrate.js +3592 -0
- package/scripts/flow-output.js +123 -0
- package/scripts/flow-parallel-detector.js +399 -0
- package/scripts/flow-parallel-dispatch.js +987 -0
- package/scripts/flow-parallel.js +428 -0
- package/scripts/flow-pattern-enforcer.js +600 -0
- package/scripts/flow-prd-manager.js +282 -0
- package/scripts/flow-progress.js +323 -0
- package/scripts/flow-project-analyzer.js +975 -0
- package/scripts/flow-prompt-composer.js +487 -0
- package/scripts/flow-providers.js +1381 -0
- package/scripts/flow-queue.js +308 -0
- package/scripts/flow-ready +82 -0
- package/scripts/flow-ready.js +189 -0
- package/scripts/flow-regression.js +396 -0
- package/scripts/flow-response-parser.js +450 -0
- package/scripts/flow-resume.js +284 -0
- package/scripts/flow-rules-sync.js +439 -0
- package/scripts/flow-run-trace.js +718 -0
- package/scripts/flow-safety.js +587 -0
- package/scripts/flow-search +104 -0
- package/scripts/flow-security.js +481 -0
- package/scripts/flow-session-end +106 -0
- package/scripts/flow-session-end.js +437 -0
- package/scripts/flow-session-state.js +671 -0
- package/scripts/flow-setup-hooks +216 -0
- package/scripts/flow-setup-hooks.js +377 -0
- package/scripts/flow-skill-create.js +329 -0
- package/scripts/flow-skill-creator.js +572 -0
- package/scripts/flow-skill-generator.js +1046 -0
- package/scripts/flow-skill-learn.js +880 -0
- package/scripts/flow-skill-matcher.js +578 -0
- package/scripts/flow-spec-generator.js +820 -0
- package/scripts/flow-stack-wizard.js +895 -0
- package/scripts/flow-standup +162 -0
- package/scripts/flow-start +74 -0
- package/scripts/flow-start.js +235 -0
- package/scripts/flow-status +110 -0
- package/scripts/flow-status.js +301 -0
- package/scripts/flow-step-browser.js +83 -0
- package/scripts/flow-step-changelog.js +217 -0
- package/scripts/flow-step-comments.js +306 -0
- package/scripts/flow-step-complexity.js +234 -0
- package/scripts/flow-step-coverage.js +218 -0
- package/scripts/flow-step-knowledge.js +193 -0
- package/scripts/flow-step-pr-tests.js +364 -0
- package/scripts/flow-step-regression.js +89 -0
- package/scripts/flow-step-review.js +516 -0
- package/scripts/flow-step-security.js +162 -0
- package/scripts/flow-step-silent-failures.js +290 -0
- package/scripts/flow-step-simplifier.js +346 -0
- package/scripts/flow-story +105 -0
- package/scripts/flow-story.js +500 -0
- package/scripts/flow-suspend.js +252 -0
- package/scripts/flow-sync-daemon.js +654 -0
- package/scripts/flow-task-analyzer.js +606 -0
- package/scripts/flow-team-dashboard.js +748 -0
- package/scripts/flow-team-sync.js +752 -0
- package/scripts/flow-team.js +977 -0
- package/scripts/flow-tech-options.js +528 -0
- package/scripts/flow-templates.js +812 -0
- package/scripts/flow-tiered-learning.js +728 -0
- package/scripts/flow-trace +204 -0
- package/scripts/flow-transcript-chunking.js +1106 -0
- package/scripts/flow-transcript-digest.js +7918 -0
- package/scripts/flow-transcript-language.js +465 -0
- package/scripts/flow-transcript-parsing.js +1085 -0
- package/scripts/flow-transcript-stories.js +2194 -0
- package/scripts/flow-update-map +224 -0
- package/scripts/flow-utils.js +2242 -0
- package/scripts/flow-verification.js +644 -0
- package/scripts/flow-verify.js +1177 -0
- package/scripts/flow-voice-input.js +638 -0
- package/scripts/flow-watch +168 -0
- package/scripts/flow-workflow-steps.js +521 -0
- package/scripts/flow-workflow.js +1029 -0
- package/scripts/flow-worktree.js +489 -0
- package/scripts/hooks/adapters/base-adapter.js +102 -0
- package/scripts/hooks/adapters/claude-code.js +359 -0
- package/scripts/hooks/adapters/index.js +79 -0
- package/scripts/hooks/core/component-check.js +341 -0
- package/scripts/hooks/core/index.js +35 -0
- package/scripts/hooks/core/loop-check.js +241 -0
- package/scripts/hooks/core/session-context.js +294 -0
- package/scripts/hooks/core/task-gate.js +177 -0
- package/scripts/hooks/core/validation.js +230 -0
- package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
- package/scripts/hooks/entry/claude-code/session-end.js +87 -0
- package/scripts/hooks/entry/claude-code/session-start.js +46 -0
- package/scripts/hooks/entry/claude-code/stop.js +43 -0
- package/scripts/postinstall.js +139 -0
- package/templates/browser-test-flow.json +56 -0
- package/templates/bug-report.md +43 -0
- package/templates/component-detail.md +42 -0
- package/templates/component.stories.tsx +49 -0
- package/templates/context/constraints.md +83 -0
- package/templates/context/conventions.md +177 -0
- package/templates/context/stack.md +60 -0
- package/templates/correction-report.md +90 -0
- package/templates/feature-proposal.md +35 -0
- package/templates/hybrid/_base.md +254 -0
- package/templates/hybrid/_patterns.md +45 -0
- package/templates/hybrid/create-component.md +127 -0
- package/templates/hybrid/create-file.md +56 -0
- package/templates/hybrid/create-hook.md +145 -0
- package/templates/hybrid/create-service.md +70 -0
- package/templates/hybrid/fix-bug.md +33 -0
- package/templates/hybrid/modify-file.md +55 -0
- package/templates/story.md +68 -0
- package/templates/task.json +56 -0
- package/templates/trace.md +69 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Skill Auto-Creator
|
|
5
|
+
*
|
|
6
|
+
* Automatically detects frameworks in the project and offers to create
|
|
7
|
+
* skills with knowledge from official documentation.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Scans project for framework indicators (package.json, file patterns)
|
|
11
|
+
* - Fetches official documentation summaries
|
|
12
|
+
* - Generates skill structure with patterns/anti-patterns
|
|
13
|
+
* - Integrates with existing skill system
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const { getConfig, getProjectRoot } = require('./flow-utils');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Detect frameworks in the project
|
|
22
|
+
*/
|
|
23
|
+
function detectFrameworks() {
|
|
24
|
+
const projectRoot = getProjectRoot();
|
|
25
|
+
const config = getConfig();
|
|
26
|
+
const skillLearning = config.skillLearning || {};
|
|
27
|
+
const patterns = skillLearning.frameworkDetectionPatterns || {};
|
|
28
|
+
|
|
29
|
+
const detected = [];
|
|
30
|
+
|
|
31
|
+
// Check package.json for dependencies
|
|
32
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
33
|
+
let packageDeps = {};
|
|
34
|
+
|
|
35
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
36
|
+
try {
|
|
37
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
38
|
+
packageDeps = {
|
|
39
|
+
...pkg.dependencies,
|
|
40
|
+
...pkg.devDependencies
|
|
41
|
+
};
|
|
42
|
+
} catch {
|
|
43
|
+
// Ignore parse errors
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check requirements.txt for Python
|
|
48
|
+
const requirementsPath = path.join(projectRoot, 'requirements.txt');
|
|
49
|
+
let pythonDeps = [];
|
|
50
|
+
|
|
51
|
+
if (fs.existsSync(requirementsPath)) {
|
|
52
|
+
try {
|
|
53
|
+
pythonDeps = fs.readFileSync(requirementsPath, 'utf-8')
|
|
54
|
+
.split('\n')
|
|
55
|
+
.map(line => line.split('==')[0].split('>=')[0].trim().toLowerCase())
|
|
56
|
+
.filter(Boolean);
|
|
57
|
+
} catch {
|
|
58
|
+
// Ignore
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Scan for file patterns
|
|
63
|
+
const srcDirs = ['src', 'app', 'lib', 'components', '.'];
|
|
64
|
+
const foundFiles = {};
|
|
65
|
+
|
|
66
|
+
for (const dir of srcDirs) {
|
|
67
|
+
const fullDir = path.join(projectRoot, dir);
|
|
68
|
+
if (!fs.existsSync(fullDir) || !fs.statSync(fullDir).isDirectory()) continue;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const files = scanDirectory(fullDir, 3); // Scan 3 levels deep
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
const ext = path.extname(file);
|
|
74
|
+
const basename = path.basename(file);
|
|
75
|
+
if (!foundFiles[ext]) foundFiles[ext] = [];
|
|
76
|
+
foundFiles[ext].push(basename);
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
// Ignore scan errors
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Check each framework
|
|
84
|
+
for (const [framework, framePatterns] of Object.entries(patterns)) {
|
|
85
|
+
const reasons = [];
|
|
86
|
+
|
|
87
|
+
for (const pattern of framePatterns) {
|
|
88
|
+
// Check if pattern is a package name
|
|
89
|
+
if (pattern.startsWith('@') || !pattern.includes('*')) {
|
|
90
|
+
if (packageDeps[pattern]) {
|
|
91
|
+
reasons.push(`package: ${pattern}`);
|
|
92
|
+
}
|
|
93
|
+
if (pythonDeps.includes(pattern.toLowerCase())) {
|
|
94
|
+
reasons.push(`python-package: ${pattern}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Check file patterns
|
|
99
|
+
if (pattern.includes('*')) {
|
|
100
|
+
const ext = path.extname(pattern);
|
|
101
|
+
const prefix = path.basename(pattern).replace('*', '');
|
|
102
|
+
|
|
103
|
+
if (foundFiles[ext]) {
|
|
104
|
+
const matches = foundFiles[ext].filter(f =>
|
|
105
|
+
prefix ? f.includes(prefix.replace('.', '')) : true
|
|
106
|
+
);
|
|
107
|
+
if (matches.length > 0) {
|
|
108
|
+
reasons.push(`files: ${matches.slice(0, 3).join(', ')}${matches.length > 3 ? '...' : ''}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (reasons.length > 0) {
|
|
115
|
+
detected.push({
|
|
116
|
+
framework,
|
|
117
|
+
confidence: Math.min(reasons.length / 2, 1), // 0-1 scale
|
|
118
|
+
reasons,
|
|
119
|
+
docsUrl: (skillLearning.officialDocsUrls || {})[framework] || null
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Sort by confidence
|
|
125
|
+
detected.sort((a, b) => b.confidence - a.confidence);
|
|
126
|
+
|
|
127
|
+
return detected;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Scan directory recursively
|
|
132
|
+
*/
|
|
133
|
+
function scanDirectory(dir, maxDepth, currentDepth = 0) {
|
|
134
|
+
if (currentDepth >= maxDepth) return [];
|
|
135
|
+
|
|
136
|
+
const files = [];
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
140
|
+
|
|
141
|
+
for (const entry of entries) {
|
|
142
|
+
// Skip common non-source directories
|
|
143
|
+
if (entry.isDirectory()) {
|
|
144
|
+
if (['node_modules', '.git', 'dist', 'build', '__pycache__', '.next'].includes(entry.name)) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
files.push(...scanDirectory(path.join(dir, entry.name), maxDepth, currentDepth + 1));
|
|
148
|
+
} else if (entry.isFile()) {
|
|
149
|
+
files.push(path.join(dir, entry.name));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
// Ignore permission errors
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return files;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Check if skill already exists
|
|
161
|
+
*/
|
|
162
|
+
function skillExists(framework) {
|
|
163
|
+
const projectRoot = getProjectRoot();
|
|
164
|
+
const skillPath = path.join(projectRoot, '.claude', 'skills', framework);
|
|
165
|
+
return fs.existsSync(skillPath);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Get installed skills
|
|
170
|
+
*/
|
|
171
|
+
function getInstalledSkills() {
|
|
172
|
+
const config = getConfig();
|
|
173
|
+
return config.skills?.installed || [];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Generate skill structure for a framework
|
|
178
|
+
*/
|
|
179
|
+
function generateSkillStructure(framework, docsUrl) {
|
|
180
|
+
const projectRoot = getProjectRoot();
|
|
181
|
+
const skillPath = path.join(projectRoot, '.claude', 'skills', framework);
|
|
182
|
+
|
|
183
|
+
// Create directory structure
|
|
184
|
+
const dirs = [
|
|
185
|
+
skillPath,
|
|
186
|
+
path.join(skillPath, 'knowledge'),
|
|
187
|
+
path.join(skillPath, 'rules'),
|
|
188
|
+
path.join(skillPath, 'commands'),
|
|
189
|
+
path.join(skillPath, 'templates')
|
|
190
|
+
];
|
|
191
|
+
|
|
192
|
+
for (const dir of dirs) {
|
|
193
|
+
if (!fs.existsSync(dir)) {
|
|
194
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Generate skill.md
|
|
199
|
+
const skillMd = `# ${framework} Skill
|
|
200
|
+
|
|
201
|
+
## Overview
|
|
202
|
+
Auto-generated skill for ${framework} framework.
|
|
203
|
+
|
|
204
|
+
## Official Documentation
|
|
205
|
+
${docsUrl || 'Not specified'}
|
|
206
|
+
|
|
207
|
+
## File Patterns
|
|
208
|
+
Load this skill when working with files matching:
|
|
209
|
+
${getFilePatterns(framework)}
|
|
210
|
+
|
|
211
|
+
## Quick Reference
|
|
212
|
+
- See \`knowledge/patterns.md\` for common patterns
|
|
213
|
+
- See \`knowledge/anti-patterns.md\` for things to avoid
|
|
214
|
+
- See \`rules/conventions.md\` for coding conventions
|
|
215
|
+
|
|
216
|
+
## Commands
|
|
217
|
+
${generateCommandsList(framework)}
|
|
218
|
+
|
|
219
|
+
## Templates
|
|
220
|
+
See \`templates/\` for code templates.
|
|
221
|
+
`;
|
|
222
|
+
|
|
223
|
+
fs.writeFileSync(path.join(skillPath, 'skill.md'), skillMd);
|
|
224
|
+
|
|
225
|
+
// Generate knowledge files
|
|
226
|
+
generateKnowledgeFiles(skillPath, framework);
|
|
227
|
+
|
|
228
|
+
// Generate rules
|
|
229
|
+
generateRulesFiles(skillPath, framework);
|
|
230
|
+
|
|
231
|
+
return skillPath;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get file patterns for a framework
|
|
236
|
+
*/
|
|
237
|
+
function getFilePatterns(framework) {
|
|
238
|
+
const patterns = {
|
|
239
|
+
nestjs: '- `*.module.ts`\n- `*.controller.ts`\n- `*.service.ts`\n- `*.entity.ts`',
|
|
240
|
+
react: '- `*.tsx`\n- `*.jsx`\n- `use*.ts` (hooks)',
|
|
241
|
+
vue: '- `*.vue`\n- `composables/*.ts`',
|
|
242
|
+
angular: '- `*.component.ts`\n- `*.service.ts`\n- `*.module.ts`',
|
|
243
|
+
fastapi: '- `main.py`\n- `routers/*.py`\n- `models/*.py`',
|
|
244
|
+
django: '- `views.py`\n- `models.py`\n- `urls.py`',
|
|
245
|
+
express: '- `routes/*.js`\n- `middleware/*.js`\n- `controllers/*.js`'
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
return patterns[framework] || '- TBD based on project analysis';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Generate commands list
|
|
253
|
+
*/
|
|
254
|
+
function generateCommandsList(framework) {
|
|
255
|
+
const commands = {
|
|
256
|
+
nestjs: `- \`/${framework}-scaffold [name]\` - Create module with controller/service\n- \`/${framework}-entity [name]\` - Create TypeORM entity`,
|
|
257
|
+
react: `- \`/${framework}-component [name]\` - Create component\n- \`/${framework}-hook [name]\` - Create custom hook`,
|
|
258
|
+
vue: `- \`/${framework}-component [name]\` - Create Vue component\n- \`/${framework}-composable [name]\` - Create composable`,
|
|
259
|
+
fastapi: `- \`/${framework}-router [name]\` - Create router\n- \`/${framework}-model [name]\` - Create Pydantic model`,
|
|
260
|
+
default: 'No commands defined yet. Add to `commands/` directory.'
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
return commands[framework] || commands.default;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Generate knowledge files
|
|
268
|
+
*/
|
|
269
|
+
function generateKnowledgeFiles(skillPath, framework) {
|
|
270
|
+
// patterns.md
|
|
271
|
+
const patternsContent = `# ${framework} Patterns
|
|
272
|
+
|
|
273
|
+
## Common Patterns
|
|
274
|
+
|
|
275
|
+
### Pattern 1: [Name]
|
|
276
|
+
**When to use:** [Description]
|
|
277
|
+
**Example:**
|
|
278
|
+
\`\`\`typescript
|
|
279
|
+
// Code example
|
|
280
|
+
\`\`\`
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
*Add more patterns as you learn them. This file is automatically updated.*
|
|
285
|
+
`;
|
|
286
|
+
|
|
287
|
+
fs.writeFileSync(path.join(skillPath, 'knowledge', 'patterns.md'), patternsContent);
|
|
288
|
+
|
|
289
|
+
// anti-patterns.md
|
|
290
|
+
const antiPatternsContent = `# ${framework} Anti-Patterns
|
|
291
|
+
|
|
292
|
+
## Things to Avoid
|
|
293
|
+
|
|
294
|
+
### Anti-Pattern 1: [Name]
|
|
295
|
+
**Why it's bad:** [Explanation]
|
|
296
|
+
**Instead, do:** [Better approach]
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
*Add more anti-patterns as you learn them. This file is automatically updated.*
|
|
301
|
+
`;
|
|
302
|
+
|
|
303
|
+
fs.writeFileSync(path.join(skillPath, 'knowledge', 'anti-patterns.md'), antiPatternsContent);
|
|
304
|
+
|
|
305
|
+
// learnings.md
|
|
306
|
+
const learningsContent = `# ${framework} Learnings
|
|
307
|
+
|
|
308
|
+
## Session Learnings
|
|
309
|
+
|
|
310
|
+
*This file is automatically updated when the skill learning system detects relevant corrections or patterns.*
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
| Date | Learning | Source |
|
|
315
|
+
|------|----------|--------|
|
|
316
|
+
`;
|
|
317
|
+
|
|
318
|
+
fs.writeFileSync(path.join(skillPath, 'knowledge', 'learnings.md'), learningsContent);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Generate rules files
|
|
323
|
+
*/
|
|
324
|
+
function generateRulesFiles(skillPath, framework) {
|
|
325
|
+
const conventions = {
|
|
326
|
+
nestjs: `# NestJS Conventions
|
|
327
|
+
|
|
328
|
+
## File Naming
|
|
329
|
+
- Modules: \`[name].module.ts\`
|
|
330
|
+
- Controllers: \`[name].controller.ts\`
|
|
331
|
+
- Services: \`[name].service.ts\`
|
|
332
|
+
- Entities: \`[name].entity.ts\`
|
|
333
|
+
|
|
334
|
+
## Structure
|
|
335
|
+
- One module per feature/domain
|
|
336
|
+
- Controllers handle HTTP, services handle logic
|
|
337
|
+
- Use DTOs for request/response validation
|
|
338
|
+
|
|
339
|
+
## Dependency Injection
|
|
340
|
+
- Always inject via constructor
|
|
341
|
+
- Use interfaces for loose coupling
|
|
342
|
+
`,
|
|
343
|
+
react: `# React Conventions
|
|
344
|
+
|
|
345
|
+
## File Naming
|
|
346
|
+
- Components: PascalCase \`ComponentName.tsx\`
|
|
347
|
+
- Hooks: camelCase with \`use\` prefix \`useHookName.ts\`
|
|
348
|
+
|
|
349
|
+
## Component Structure
|
|
350
|
+
- Functional components only
|
|
351
|
+
- Props interface above component
|
|
352
|
+
- Hooks at top of component
|
|
353
|
+
|
|
354
|
+
## State Management
|
|
355
|
+
- Local state for component-specific data
|
|
356
|
+
- Context for shared state
|
|
357
|
+
- Avoid prop drilling > 2 levels
|
|
358
|
+
`,
|
|
359
|
+
default: `# ${framework} Conventions
|
|
360
|
+
|
|
361
|
+
## File Naming
|
|
362
|
+
TBD based on project conventions.
|
|
363
|
+
|
|
364
|
+
## Structure
|
|
365
|
+
TBD based on project structure.
|
|
366
|
+
|
|
367
|
+
## Best Practices
|
|
368
|
+
TBD based on official documentation.
|
|
369
|
+
`
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const content = conventions[framework] || conventions.default;
|
|
373
|
+
fs.writeFileSync(path.join(skillPath, 'rules', 'conventions.md'), content);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Register skill in config.json
|
|
378
|
+
*/
|
|
379
|
+
function registerSkill(framework) {
|
|
380
|
+
const projectRoot = getProjectRoot();
|
|
381
|
+
const configPath = path.join(projectRoot, '.workflow', 'config.json');
|
|
382
|
+
|
|
383
|
+
const config = getConfig();
|
|
384
|
+
|
|
385
|
+
if (!config.skills) {
|
|
386
|
+
config.skills = { installed: [] };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
if (!config.skills.installed.includes(framework)) {
|
|
390
|
+
config.skills.installed.push(framework);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Generate detection report
|
|
398
|
+
*/
|
|
399
|
+
function generateDetectionReport(detected) {
|
|
400
|
+
const lines = [
|
|
401
|
+
'',
|
|
402
|
+
'╔════════════════════════════════════════════════════════╗',
|
|
403
|
+
'║ 🔍 FRAMEWORK DETECTION REPORT ║',
|
|
404
|
+
'╠════════════════════════════════════════════════════════╣'
|
|
405
|
+
];
|
|
406
|
+
|
|
407
|
+
if (detected.length === 0) {
|
|
408
|
+
lines.push('║ No frameworks detected in this project.'.padEnd(57) + '║');
|
|
409
|
+
lines.push('╚════════════════════════════════════════════════════════╝');
|
|
410
|
+
return lines.join('\n');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const installed = getInstalledSkills();
|
|
414
|
+
|
|
415
|
+
for (const fw of detected) {
|
|
416
|
+
const status = installed.includes(fw.framework) ? '✅' :
|
|
417
|
+
skillExists(fw.framework) ? '📦' : '❌';
|
|
418
|
+
const confidence = Math.round(fw.confidence * 100);
|
|
419
|
+
|
|
420
|
+
lines.push(`║ ${status} ${fw.framework.padEnd(20)} Confidence: ${confidence}%`.padEnd(57) + '║');
|
|
421
|
+
|
|
422
|
+
for (const reason of fw.reasons.slice(0, 2)) {
|
|
423
|
+
lines.push(`║ └─ ${reason}`.padEnd(57) + '║');
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
lines.push('╠════════════════════════════════════════════════════════╣');
|
|
428
|
+
lines.push('║ Legend: ✅ installed 📦 exists ❌ not created'.padEnd(57) + '║');
|
|
429
|
+
lines.push('╚════════════════════════════════════════════════════════╝');
|
|
430
|
+
|
|
431
|
+
// Add suggestions
|
|
432
|
+
const needsCreation = detected.filter(fw =>
|
|
433
|
+
!installed.includes(fw.framework) && !skillExists(fw.framework)
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
if (needsCreation.length > 0) {
|
|
437
|
+
lines.push('');
|
|
438
|
+
lines.push('💡 Suggested skills to create:');
|
|
439
|
+
for (const fw of needsCreation) {
|
|
440
|
+
lines.push(` ./scripts/flow skill-create ${fw.framework}`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return lines.join('\n');
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Create a skill interactively
|
|
449
|
+
*/
|
|
450
|
+
function createSkill(framework, options = {}) {
|
|
451
|
+
const { docsUrl = null, autoRegister = true } = options;
|
|
452
|
+
|
|
453
|
+
// Check if already exists
|
|
454
|
+
if (skillExists(framework)) {
|
|
455
|
+
return {
|
|
456
|
+
success: false,
|
|
457
|
+
message: `Skill '${framework}' already exists`,
|
|
458
|
+
path: null
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Get docs URL from config if not provided
|
|
463
|
+
const config = getConfig();
|
|
464
|
+
const finalDocsUrl = docsUrl ||
|
|
465
|
+
(config.skillLearning?.officialDocsUrls || {})[framework] ||
|
|
466
|
+
null;
|
|
467
|
+
|
|
468
|
+
// Generate skill structure
|
|
469
|
+
const skillPath = generateSkillStructure(framework, finalDocsUrl);
|
|
470
|
+
|
|
471
|
+
// Register in config
|
|
472
|
+
if (autoRegister) {
|
|
473
|
+
registerSkill(framework);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
return {
|
|
477
|
+
success: true,
|
|
478
|
+
message: `Skill '${framework}' created successfully`,
|
|
479
|
+
path: skillPath,
|
|
480
|
+
docsUrl: finalDocsUrl
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ============================================================
|
|
485
|
+
// Exports
|
|
486
|
+
// ============================================================
|
|
487
|
+
|
|
488
|
+
module.exports = {
|
|
489
|
+
detectFrameworks,
|
|
490
|
+
skillExists,
|
|
491
|
+
getInstalledSkills,
|
|
492
|
+
generateSkillStructure,
|
|
493
|
+
registerSkill,
|
|
494
|
+
generateDetectionReport,
|
|
495
|
+
createSkill
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
// ============================================================
|
|
499
|
+
// CLI
|
|
500
|
+
// ============================================================
|
|
501
|
+
|
|
502
|
+
if (require.main === module) {
|
|
503
|
+
const args = process.argv.slice(2);
|
|
504
|
+
const command = args[0];
|
|
505
|
+
|
|
506
|
+
switch (command) {
|
|
507
|
+
case 'detect': {
|
|
508
|
+
const detected = detectFrameworks();
|
|
509
|
+
console.log(generateDetectionReport(detected));
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
case 'create': {
|
|
514
|
+
const framework = args[1];
|
|
515
|
+
if (!framework) {
|
|
516
|
+
console.error('Usage: node flow-skill-creator.js create <framework>');
|
|
517
|
+
process.exit(1);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const result = createSkill(framework);
|
|
521
|
+
if (result.success) {
|
|
522
|
+
console.log(`\n✅ ${result.message}`);
|
|
523
|
+
console.log(` Path: ${result.path}`);
|
|
524
|
+
if (result.docsUrl) {
|
|
525
|
+
console.log(` Docs: ${result.docsUrl}`);
|
|
526
|
+
}
|
|
527
|
+
console.log('\nNext steps:');
|
|
528
|
+
console.log('1. Review generated files in .claude/skills/' + framework);
|
|
529
|
+
console.log('2. Add patterns from official documentation');
|
|
530
|
+
console.log('3. Add project-specific conventions');
|
|
531
|
+
} else {
|
|
532
|
+
console.error(`\n❌ ${result.message}`);
|
|
533
|
+
process.exit(1);
|
|
534
|
+
}
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
case 'list': {
|
|
539
|
+
const installed = getInstalledSkills();
|
|
540
|
+
console.log('\n📚 Installed Skills\n');
|
|
541
|
+
if (installed.length === 0) {
|
|
542
|
+
console.log('No skills installed.');
|
|
543
|
+
} else {
|
|
544
|
+
installed.forEach(s => console.log(` • ${s}`));
|
|
545
|
+
}
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
default:
|
|
550
|
+
console.log(`
|
|
551
|
+
Wogi Flow - Skill Auto-Creator
|
|
552
|
+
|
|
553
|
+
Usage:
|
|
554
|
+
node flow-skill-creator.js <command> [args]
|
|
555
|
+
|
|
556
|
+
Commands:
|
|
557
|
+
detect Scan project and detect frameworks
|
|
558
|
+
create <framework> Create skill for a framework
|
|
559
|
+
list List installed skills
|
|
560
|
+
|
|
561
|
+
Examples:
|
|
562
|
+
node flow-skill-creator.js detect
|
|
563
|
+
node flow-skill-creator.js create nestjs
|
|
564
|
+
node flow-skill-creator.js create react
|
|
565
|
+
|
|
566
|
+
Configuration (config.json):
|
|
567
|
+
skillLearning.autoDetectFrameworks: true
|
|
568
|
+
skillLearning.frameworkDetectionPatterns: { ... }
|
|
569
|
+
skillLearning.officialDocsUrls: { ... }
|
|
570
|
+
`);
|
|
571
|
+
}
|
|
572
|
+
}
|