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,458 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wogi Flow - Capture Corrections
|
|
5
|
+
*
|
|
6
|
+
* Records corrections/learnings to ensure they are preserved and tracked.
|
|
7
|
+
* Supports both interactive and quick CLI modes.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* flow correct # Interactive mode
|
|
11
|
+
* flow correct "brief description" # Quick mode
|
|
12
|
+
* flow correct --task TASK-XXX "desc" # Link to task
|
|
13
|
+
* flow correct --skill nestjs "desc" # Link to skill
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const readline = require('readline');
|
|
19
|
+
const {
|
|
20
|
+
PATHS,
|
|
21
|
+
PROJECT_ROOT,
|
|
22
|
+
fileExists,
|
|
23
|
+
dirExists,
|
|
24
|
+
readFile,
|
|
25
|
+
writeFile,
|
|
26
|
+
color,
|
|
27
|
+
success,
|
|
28
|
+
warn,
|
|
29
|
+
error
|
|
30
|
+
} = require('./flow-utils');
|
|
31
|
+
|
|
32
|
+
// ============================================================
|
|
33
|
+
// Paths
|
|
34
|
+
// ============================================================
|
|
35
|
+
|
|
36
|
+
function getCorrectionsDir() {
|
|
37
|
+
try {
|
|
38
|
+
const config = JSON.parse(fs.readFileSync(PATHS.config, 'utf-8'));
|
|
39
|
+
const detailPath = config?.corrections?.detailPath;
|
|
40
|
+
if (detailPath) {
|
|
41
|
+
return path.isAbsolute(detailPath) ? detailPath : path.join(PROJECT_ROOT, detailPath);
|
|
42
|
+
}
|
|
43
|
+
} catch (err) {
|
|
44
|
+
// Fall back to default if config can't be read
|
|
45
|
+
}
|
|
46
|
+
return path.join(PROJECT_ROOT, '.workflow', 'corrections');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const CORRECTIONS_DIR = getCorrectionsDir();
|
|
50
|
+
|
|
51
|
+
// ============================================================
|
|
52
|
+
// Interactive Prompt Utilities
|
|
53
|
+
// ============================================================
|
|
54
|
+
|
|
55
|
+
function createInterface() {
|
|
56
|
+
return readline.createInterface({
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stdout
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function prompt(rl, question, defaultValue = '') {
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
const suffix = defaultValue ? ` (${defaultValue})` : '';
|
|
65
|
+
rl.question(`${question}${suffix}: `, (answer) => {
|
|
66
|
+
resolve(answer.trim() || defaultValue);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function promptMultiline(rl, question) {
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
console.log(`${question} (end with empty line):`);
|
|
74
|
+
const lines = [];
|
|
75
|
+
|
|
76
|
+
const readLine = () => {
|
|
77
|
+
rl.question(' ', (line) => {
|
|
78
|
+
if (line === '') {
|
|
79
|
+
resolve(lines.join('\n'));
|
|
80
|
+
} else {
|
|
81
|
+
lines.push(line);
|
|
82
|
+
readLine();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
readLine();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ============================================================
|
|
92
|
+
// Core Functions
|
|
93
|
+
// ============================================================
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Generate next correction ID
|
|
97
|
+
*/
|
|
98
|
+
function getNextCorrectionId() {
|
|
99
|
+
if (!dirExists(CORRECTIONS_DIR)) {
|
|
100
|
+
fs.mkdirSync(CORRECTIONS_DIR, { recursive: true });
|
|
101
|
+
return 'CORR-001';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const files = fs.readdirSync(CORRECTIONS_DIR)
|
|
105
|
+
.filter(f => f.startsWith('CORR-') && f.endsWith('.md'));
|
|
106
|
+
|
|
107
|
+
if (files.length === 0) {
|
|
108
|
+
return 'CORR-001';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const numbers = files.map(f => {
|
|
112
|
+
const match = f.match(/CORR-(\d+)/);
|
|
113
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const maxNum = Math.max(...numbers);
|
|
117
|
+
return `CORR-${String(maxNum + 1).padStart(3, '0')}`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create correction file
|
|
122
|
+
*/
|
|
123
|
+
function createCorrectionFile(data) {
|
|
124
|
+
const {
|
|
125
|
+
id,
|
|
126
|
+
brief,
|
|
127
|
+
whatHappened,
|
|
128
|
+
whatShouldHappen,
|
|
129
|
+
rootCause,
|
|
130
|
+
taskId,
|
|
131
|
+
skillName,
|
|
132
|
+
files,
|
|
133
|
+
tags
|
|
134
|
+
} = data;
|
|
135
|
+
|
|
136
|
+
const date = new Date().toISOString().split('T')[0];
|
|
137
|
+
const timestamp = new Date().toISOString();
|
|
138
|
+
|
|
139
|
+
const content = `# ${id} - ${brief}
|
|
140
|
+
|
|
141
|
+
**Date**: ${date}
|
|
142
|
+
**Timestamp**: ${timestamp}
|
|
143
|
+
${taskId ? `**Task**: ${taskId}` : ''}
|
|
144
|
+
${skillName ? `**Skill**: ${skillName}` : ''}
|
|
145
|
+
${tags.length > 0 ? `**Tags**: ${tags.map(t => `#${t}`).join(' ')}` : ''}
|
|
146
|
+
|
|
147
|
+
## What Happened
|
|
148
|
+
|
|
149
|
+
${whatHappened || '_Not specified_'}
|
|
150
|
+
|
|
151
|
+
## What Should Happen
|
|
152
|
+
|
|
153
|
+
${whatShouldHappen || '_Not specified_'}
|
|
154
|
+
|
|
155
|
+
## Root Cause
|
|
156
|
+
|
|
157
|
+
${rootCause || '_Not specified_'}
|
|
158
|
+
|
|
159
|
+
${files.length > 0 ? `## Files Affected\n\n${files.map(f => `- \`${f}\``).join('\n')}` : ''}
|
|
160
|
+
|
|
161
|
+
## Status
|
|
162
|
+
|
|
163
|
+
- [ ] Pattern identified
|
|
164
|
+
- [ ] Added to knowledge base
|
|
165
|
+
- [ ] Promoted to instruction file (if pattern repeats)
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
_Generated by \`flow correct\`_
|
|
170
|
+
`;
|
|
171
|
+
|
|
172
|
+
const filePath = path.join(CORRECTIONS_DIR, `${id}.md`);
|
|
173
|
+
writeFile(filePath, content);
|
|
174
|
+
return filePath;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Update feedback-patterns.md with the correction
|
|
179
|
+
*/
|
|
180
|
+
function updateFeedbackPatterns(brief, taskId, skillName) {
|
|
181
|
+
const date = new Date().toISOString().split('T')[0];
|
|
182
|
+
|
|
183
|
+
let content = readFile(PATHS.feedbackPatterns, '');
|
|
184
|
+
|
|
185
|
+
// Check if similar correction exists (simple substring match)
|
|
186
|
+
const briefLower = brief.toLowerCase();
|
|
187
|
+
const lines = content.split('\n');
|
|
188
|
+
let existingIndex = -1;
|
|
189
|
+
let existingCount = 1;
|
|
190
|
+
|
|
191
|
+
// Look in the table for similar entries
|
|
192
|
+
for (let i = 0; i < lines.length; i++) {
|
|
193
|
+
const line = lines[i];
|
|
194
|
+
if (line.startsWith('|') && !line.includes('---') && !line.includes('Date')) {
|
|
195
|
+
const cells = line.split('|').map(c => c.trim());
|
|
196
|
+
if (cells[2] && cells[2].toLowerCase().includes(briefLower.slice(0, 20))) {
|
|
197
|
+
// Found similar entry, extract count
|
|
198
|
+
existingIndex = i;
|
|
199
|
+
const countMatch = cells[3]?.match(/(\d+)/);
|
|
200
|
+
existingCount = countMatch ? parseInt(countMatch[1], 10) + 1 : 2;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (existingIndex > 0) {
|
|
207
|
+
// Update existing entry count
|
|
208
|
+
const cells = lines[existingIndex].split('|');
|
|
209
|
+
cells[1] = ` ${date} `;
|
|
210
|
+
cells[3] = ` ${existingCount} `;
|
|
211
|
+
lines[existingIndex] = cells.join('|');
|
|
212
|
+
content = lines.join('\n');
|
|
213
|
+
} else {
|
|
214
|
+
// Add new entry after the example row
|
|
215
|
+
const tableIndex = content.indexOf('| _example_');
|
|
216
|
+
if (tableIndex > -1) {
|
|
217
|
+
const lineEnd = content.indexOf('\n', tableIndex);
|
|
218
|
+
const newRow = `\n| ${date} | "${brief.slice(0, 40)}${brief.length > 40 ? '...' : ''}" | 1 | - | Pending |`;
|
|
219
|
+
content = content.slice(0, lineEnd) + newRow + content.slice(lineEnd);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
writeFile(PATHS.feedbackPatterns, content);
|
|
224
|
+
return existingCount;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Update skill learnings if skill is specified
|
|
229
|
+
*/
|
|
230
|
+
function updateSkillLearnings(skillName, data) {
|
|
231
|
+
const skillDir = path.join(PROJECT_ROOT, '.claude', 'skills', skillName, 'knowledge');
|
|
232
|
+
const learningsPath = path.join(skillDir, 'learnings.md');
|
|
233
|
+
|
|
234
|
+
if (!dirExists(skillDir)) {
|
|
235
|
+
warn(`Skill directory not found: ${skillDir}`);
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const date = new Date().toISOString().split('T')[0];
|
|
240
|
+
|
|
241
|
+
let content = readFile(learningsPath, '# Learnings\n\n');
|
|
242
|
+
|
|
243
|
+
const entry = `
|
|
244
|
+
### ${date} - ${data.brief}
|
|
245
|
+
|
|
246
|
+
**Context**: ${data.whatHappened || 'Correction captured via CLI'}
|
|
247
|
+
**Trigger**: manual
|
|
248
|
+
**Issue**: ${data.rootCause || 'See correction file'}
|
|
249
|
+
**Learning**: ${data.whatShouldHappen || 'See correction file'}
|
|
250
|
+
**Files**: ${data.files.join(', ') || 'N/A'}
|
|
251
|
+
`;
|
|
252
|
+
|
|
253
|
+
// Append after the header
|
|
254
|
+
if (content.includes('# Learnings')) {
|
|
255
|
+
content = content.replace('# Learnings', `# Learnings\n${entry}`);
|
|
256
|
+
} else {
|
|
257
|
+
content += entry;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
writeFile(learningsPath, content);
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ============================================================
|
|
265
|
+
// Interactive Mode
|
|
266
|
+
// ============================================================
|
|
267
|
+
|
|
268
|
+
async function runInteractive() {
|
|
269
|
+
const rl = createInterface();
|
|
270
|
+
|
|
271
|
+
console.log(color('cyan', '═══════════════════════════════════════════'));
|
|
272
|
+
console.log(color('cyan', ' Capture Correction'));
|
|
273
|
+
console.log(color('cyan', '═══════════════════════════════════════════'));
|
|
274
|
+
console.log('');
|
|
275
|
+
|
|
276
|
+
try {
|
|
277
|
+
const brief = await prompt(rl, 'Brief description');
|
|
278
|
+
if (!brief) {
|
|
279
|
+
error('Brief description is required');
|
|
280
|
+
rl.close();
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const whatHappened = await promptMultiline(rl, 'What happened (the mistake)');
|
|
285
|
+
const whatShouldHappen = await promptMultiline(rl, 'What should happen instead');
|
|
286
|
+
const rootCause = await prompt(rl, 'Root cause (optional)');
|
|
287
|
+
const taskId = await prompt(rl, 'Related task ID (optional)');
|
|
288
|
+
const skillName = await prompt(rl, 'Related skill name (optional)');
|
|
289
|
+
const filesStr = await prompt(rl, 'Affected files (comma-separated, optional)');
|
|
290
|
+
const tagsStr = await prompt(rl, 'Tags (comma-separated, optional)');
|
|
291
|
+
|
|
292
|
+
const files = filesStr ? filesStr.split(',').map(f => f.trim()) : [];
|
|
293
|
+
const tags = tagsStr ? tagsStr.split(',').map(t => t.trim()) : [];
|
|
294
|
+
|
|
295
|
+
rl.close();
|
|
296
|
+
|
|
297
|
+
// Create correction
|
|
298
|
+
const id = getNextCorrectionId();
|
|
299
|
+
const data = {
|
|
300
|
+
id,
|
|
301
|
+
brief,
|
|
302
|
+
whatHappened,
|
|
303
|
+
whatShouldHappen,
|
|
304
|
+
rootCause,
|
|
305
|
+
taskId,
|
|
306
|
+
skillName,
|
|
307
|
+
files,
|
|
308
|
+
tags
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
const filePath = createCorrectionFile(data);
|
|
312
|
+
const count = updateFeedbackPatterns(brief, taskId, skillName);
|
|
313
|
+
|
|
314
|
+
if (skillName) {
|
|
315
|
+
updateSkillLearnings(skillName, data);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
console.log('');
|
|
319
|
+
success(`Correction saved: ${id}`);
|
|
320
|
+
console.log(` File: ${filePath}`);
|
|
321
|
+
console.log(` Pattern count: ${count}`);
|
|
322
|
+
|
|
323
|
+
if (count >= 3) {
|
|
324
|
+
console.log('');
|
|
325
|
+
warn('This pattern has occurred 3+ times!');
|
|
326
|
+
console.log(' Consider promoting to an instruction file:');
|
|
327
|
+
console.log(' - decisions.md (project rules)');
|
|
328
|
+
console.log(' - agents/*.md (process changes)');
|
|
329
|
+
console.log(' - CLAUDE.md (core workflow)');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
} catch (err) {
|
|
333
|
+
rl.close();
|
|
334
|
+
error(`Failed: ${err.message}`);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// ============================================================
|
|
340
|
+
// Quick Mode
|
|
341
|
+
// ============================================================
|
|
342
|
+
|
|
343
|
+
function runQuick(brief, options) {
|
|
344
|
+
const { taskId, skillName } = options;
|
|
345
|
+
|
|
346
|
+
const id = getNextCorrectionId();
|
|
347
|
+
const data = {
|
|
348
|
+
id,
|
|
349
|
+
brief,
|
|
350
|
+
whatHappened: '',
|
|
351
|
+
whatShouldHappen: '',
|
|
352
|
+
rootCause: '',
|
|
353
|
+
taskId: taskId || '',
|
|
354
|
+
skillName: skillName || '',
|
|
355
|
+
files: [],
|
|
356
|
+
tags: []
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const filePath = createCorrectionFile(data);
|
|
360
|
+
const count = updateFeedbackPatterns(brief, taskId, skillName);
|
|
361
|
+
|
|
362
|
+
if (skillName) {
|
|
363
|
+
updateSkillLearnings(skillName, data);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
success(`Correction saved: ${id}`);
|
|
367
|
+
console.log(` File: ${filePath}`);
|
|
368
|
+
console.log(` Pattern count: ${count}`);
|
|
369
|
+
|
|
370
|
+
if (count >= 3) {
|
|
371
|
+
console.log('');
|
|
372
|
+
warn('This pattern has occurred 3+ times - consider promoting to instruction file');
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// ============================================================
|
|
377
|
+
// List Mode
|
|
378
|
+
// ============================================================
|
|
379
|
+
|
|
380
|
+
function listCorrections() {
|
|
381
|
+
if (!dirExists(CORRECTIONS_DIR)) {
|
|
382
|
+
console.log('No corrections recorded yet.');
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const files = fs.readdirSync(CORRECTIONS_DIR)
|
|
387
|
+
.filter(f => f.startsWith('CORR-') && f.endsWith('.md'))
|
|
388
|
+
.sort()
|
|
389
|
+
.reverse();
|
|
390
|
+
|
|
391
|
+
if (files.length === 0) {
|
|
392
|
+
console.log('No corrections recorded yet.');
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
console.log(color('cyan', 'Recent Corrections'));
|
|
397
|
+
console.log('');
|
|
398
|
+
|
|
399
|
+
for (const file of files.slice(0, 10)) {
|
|
400
|
+
const content = readFile(path.join(CORRECTIONS_DIR, file), '');
|
|
401
|
+
const titleMatch = content.match(/^# (CORR-\d+) - (.+)$/m);
|
|
402
|
+
const dateMatch = content.match(/\*\*Date\*\*: (.+)$/m);
|
|
403
|
+
|
|
404
|
+
const id = titleMatch ? titleMatch[1] : file.replace('.md', '');
|
|
405
|
+
const title = titleMatch ? titleMatch[2] : 'Unknown';
|
|
406
|
+
const date = dateMatch ? dateMatch[1] : 'Unknown';
|
|
407
|
+
|
|
408
|
+
console.log(` ${color('yellow', id)} | ${date} | ${title.slice(0, 50)}`);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (files.length > 10) {
|
|
412
|
+
console.log('');
|
|
413
|
+
console.log(` ... and ${files.length - 10} more`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// ============================================================
|
|
418
|
+
// Main
|
|
419
|
+
// ============================================================
|
|
420
|
+
|
|
421
|
+
function main() {
|
|
422
|
+
const args = process.argv.slice(2);
|
|
423
|
+
|
|
424
|
+
// Parse options
|
|
425
|
+
let taskId = '';
|
|
426
|
+
let skillName = '';
|
|
427
|
+
let brief = '';
|
|
428
|
+
let listMode = false;
|
|
429
|
+
|
|
430
|
+
for (let i = 0; i < args.length; i++) {
|
|
431
|
+
if (args[i] === '--task' && args[i + 1]) {
|
|
432
|
+
taskId = args[i + 1];
|
|
433
|
+
i++;
|
|
434
|
+
} else if (args[i] === '--skill' && args[i + 1]) {
|
|
435
|
+
skillName = args[i + 1];
|
|
436
|
+
i++;
|
|
437
|
+
} else if (args[i] === 'list' || args[i] === '--list') {
|
|
438
|
+
listMode = true;
|
|
439
|
+
} else if (!args[i].startsWith('-')) {
|
|
440
|
+
brief = args[i];
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (listMode) {
|
|
445
|
+
listCorrections();
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (brief) {
|
|
450
|
+
// Quick mode
|
|
451
|
+
runQuick(brief, { taskId, skillName });
|
|
452
|
+
} else {
|
|
453
|
+
// Interactive mode
|
|
454
|
+
runInteractive();
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
main();
|