@krr2020/taskflow-core 0.1.0-beta.3 → 0.1.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.js +42 -4
- package/dist/commands/base.d.ts +41 -0
- package/dist/commands/base.js +141 -0
- package/dist/commands/configure.d.ts +29 -0
- package/dist/commands/configure.js +187 -0
- package/dist/commands/init.js +21 -7
- package/dist/commands/prd/create.d.ts +1 -1
- package/dist/commands/prd/create.js +29 -11
- package/dist/commands/prd/generate-arch.d.ts +1 -1
- package/dist/commands/prd/generate-arch.js +6 -5
- package/dist/commands/retro/list.js +6 -5
- package/dist/commands/tasks/generate.d.ts +1 -1
- package/dist/commands/tasks/generate.js +83 -56
- package/dist/commands/upgrade.js +49 -16
- package/dist/commands/workflow/check.d.ts +17 -0
- package/dist/commands/workflow/check.js +482 -35
- package/dist/commands/workflow/commit.js +117 -60
- package/dist/commands/workflow/do.d.ts +1 -0
- package/dist/commands/workflow/do.js +206 -13
- package/dist/commands/workflow/next.js +4 -4
- package/dist/commands/workflow/resume.js +9 -6
- package/dist/commands/workflow/start.js +11 -11
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -0
- package/dist/lib/config-paths.d.ts +15 -15
- package/dist/lib/config-paths.js +20 -15
- package/dist/lib/file-validator.d.ts +119 -0
- package/dist/lib/file-validator.js +291 -0
- package/dist/lib/git.js +4 -2
- package/dist/lib/log-parser.d.ts +91 -0
- package/dist/lib/log-parser.js +178 -0
- package/dist/lib/retrospective.d.ts +27 -0
- package/dist/lib/retrospective.js +111 -1
- package/dist/lib/types.d.ts +19 -6
- package/dist/lib/types.js +20 -1
- package/dist/lib/validation.d.ts +0 -3
- package/dist/lib/validation.js +1 -15
- package/dist/llm/base.d.ts +52 -0
- package/dist/llm/base.js +35 -0
- package/dist/llm/factory.d.ts +39 -0
- package/dist/llm/factory.js +102 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.js +7 -0
- package/dist/llm/model-selector.d.ts +71 -0
- package/dist/llm/model-selector.js +139 -0
- package/dist/llm/providers/anthropic.d.ts +31 -0
- package/dist/llm/providers/anthropic.js +116 -0
- package/dist/llm/providers/index.d.ts +6 -0
- package/dist/llm/providers/index.js +6 -0
- package/dist/llm/providers/ollama.d.ts +28 -0
- package/dist/llm/providers/ollama.js +91 -0
- package/dist/llm/providers/openai-compatible.d.ts +30 -0
- package/dist/llm/providers/openai-compatible.js +93 -0
- package/dist/schemas/config.d.ts +82 -0
- package/dist/schemas/config.js +35 -0
- package/dist/schemas/task.d.ts +2 -2
- package/dist/state-machine.d.ts +12 -0
- package/dist/state-machine.js +2 -2
- package/package.json +1 -1
- package/dist/lib/package-manager.d.ts +0 -17
- package/dist/lib/package-manager.js +0 -53
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Check command - Validate and advance task state
|
|
3
3
|
*/
|
|
4
|
+
import { execSync } from "node:child_process";
|
|
5
|
+
import { readdir } from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
4
7
|
import { ConfigLoader } from "../../lib/config-loader.js";
|
|
5
8
|
import { getRefFilePath, REF_FILES } from "../../lib/config-paths.js";
|
|
6
9
|
import { findActiveTask, loadTasksProgress, updateTaskStatus, } from "../../lib/data-access.js";
|
|
7
10
|
import { NoActiveSessionError } from "../../lib/errors.js";
|
|
8
|
-
import {
|
|
11
|
+
import { FileValidator, } from "../../lib/file-validator.js";
|
|
12
|
+
import { LogParser } from "../../lib/log-parser.js";
|
|
13
|
+
import { extractNewPatterns, formatNewPatternForDisplay, processValidationOutput, } from "../../lib/retrospective.js";
|
|
9
14
|
import { runValidations } from "../../lib/validation.js";
|
|
15
|
+
import { Phase } from "../../llm/base.js";
|
|
16
|
+
import { ProviderFactory } from "../../llm/factory.js";
|
|
10
17
|
import { BaseCommand } from "../base.js";
|
|
11
18
|
export class CheckCommand extends BaseCommand {
|
|
12
19
|
async execute() {
|
|
@@ -25,6 +32,8 @@ export class CheckCommand extends BaseCommand {
|
|
|
25
32
|
// Handle each status transition
|
|
26
33
|
switch (currentStatus) {
|
|
27
34
|
case "setup":
|
|
35
|
+
return this.advanceToPlanning(paths.tasksDir, tasksProgress, taskId, content);
|
|
36
|
+
case "planning":
|
|
28
37
|
return this.advanceToImplementing(paths.tasksDir, tasksProgress, taskId, content);
|
|
29
38
|
case "implementing":
|
|
30
39
|
return this.advanceToVerifying(paths.tasksDir, tasksProgress, taskId, content);
|
|
@@ -44,14 +53,98 @@ export class CheckCommand extends BaseCommand {
|
|
|
44
53
|
return this.failure(`Unknown status: ${currentStatus}`, [`Task ${taskId} has an invalid status`], "Check the task file and fix the status manually.");
|
|
45
54
|
}
|
|
46
55
|
}
|
|
56
|
+
advanceToPlanning(tasksDir, tasksProgress, taskId, content) {
|
|
57
|
+
// Advance to planning
|
|
58
|
+
updateTaskStatus(tasksDir, tasksProgress, taskId, "planning");
|
|
59
|
+
return this.success([
|
|
60
|
+
`✓ Status advanced: setup → planning`,
|
|
61
|
+
`✓ Task ${taskId}: ${content.title}`,
|
|
62
|
+
"",
|
|
63
|
+
"Now create your execution plan before writing code.",
|
|
64
|
+
].join("\n"), [
|
|
65
|
+
"1. Create execution plan:",
|
|
66
|
+
" - Review all context files (RETROSPECTIVE, AI PROTOCOL, etc.)",
|
|
67
|
+
" - Identify files to modify",
|
|
68
|
+
" - Determine implementation approach",
|
|
69
|
+
" - Plan subtask execution order",
|
|
70
|
+
"",
|
|
71
|
+
"2. Check planning checklist:",
|
|
72
|
+
" - [ ] Reviewed RETROSPECTIVE for known issues",
|
|
73
|
+
" - [ ] Understood task requirements",
|
|
74
|
+
" - [ ] Identified affected files and patterns",
|
|
75
|
+
" - [ ] Planned implementation approach",
|
|
76
|
+
" - [ ] Considered edge cases",
|
|
77
|
+
"",
|
|
78
|
+
"3. When plan is ready, run:",
|
|
79
|
+
" taskflow check",
|
|
80
|
+
" This will advance you to IMPLEMENTING status",
|
|
81
|
+
].join("\n"), {
|
|
82
|
+
aiGuidance: [
|
|
83
|
+
"Current Status: PLANNING",
|
|
84
|
+
"Your Goal: Create a clear execution plan",
|
|
85
|
+
"",
|
|
86
|
+
"PLANNING CHECKLIST:",
|
|
87
|
+
"─────────────────────",
|
|
88
|
+
"1. CONTEXT REVIEW:",
|
|
89
|
+
" - Read RETROSPECTIVE - know what NOT to do",
|
|
90
|
+
" - Read AI PROTOCOL - understand workflow rules",
|
|
91
|
+
" - Review TASK DETAILS - understand requirements",
|
|
92
|
+
" - Check SKILL guidelines - domain-specific rules",
|
|
93
|
+
" - Review ARCHITECTURE/CODING STANDARDS",
|
|
94
|
+
"",
|
|
95
|
+
"2. ANALYSIS:",
|
|
96
|
+
" - Search for similar implementations in codebase",
|
|
97
|
+
" - Identify patterns to follow",
|
|
98
|
+
" - List files to modify",
|
|
99
|
+
" - Identify dependencies",
|
|
100
|
+
" - Check for library conflicts (verify no similar library exists, check compatibility)",
|
|
101
|
+
"",
|
|
102
|
+
"3. PLAN CREATION:",
|
|
103
|
+
" - Define implementation approach",
|
|
104
|
+
" - Order subtasks logically",
|
|
105
|
+
" - Consider error handling needs",
|
|
106
|
+
" - Note integration points",
|
|
107
|
+
" - Use EARS syntax for acceptance criteria: WHEN [event] THEN [system] SHALL [response]",
|
|
108
|
+
" - Present alternatives with pros/cons when multiple approaches exist",
|
|
109
|
+
"",
|
|
110
|
+
"4. RISK ASSESSMENT:",
|
|
111
|
+
" - Check RETROSPECTIVE for known issues",
|
|
112
|
+
" - Identify potential edge cases",
|
|
113
|
+
" - Plan for backward compatibility",
|
|
114
|
+
" - Ask for explicit approval (yes/approved/LGTM?) before proceeding",
|
|
115
|
+
"",
|
|
116
|
+
"OUTPUT DOCUMENT:",
|
|
117
|
+
"─────────────────",
|
|
118
|
+
"Create a brief plan covering:",
|
|
119
|
+
"- Files to modify",
|
|
120
|
+
"- Implementation approach",
|
|
121
|
+
"- Patterns to follow",
|
|
122
|
+
"- Subtask execution order",
|
|
123
|
+
"- Acceptance criteria (EARS syntax)",
|
|
124
|
+
"",
|
|
125
|
+
"ASK ONE QUESTION AT A TIME:",
|
|
126
|
+
"───────────────────────────",
|
|
127
|
+
"Build understanding iteratively - ask ONE clarifying question, wait for answer, then ask the next. Do NOT batch questions.",
|
|
128
|
+
"",
|
|
129
|
+
"WHEN READY:",
|
|
130
|
+
"────────────",
|
|
131
|
+
"Run 'taskflow check' to advance to IMPLEMENTING",
|
|
132
|
+
].join("\n"),
|
|
133
|
+
warnings: [
|
|
134
|
+
"Do NOT skip planning - it prevents costly mistakes",
|
|
135
|
+
"Do NOT start coding until plan is complete",
|
|
136
|
+
"Review RETROSPECTIVE carefully - avoid known errors",
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
}
|
|
47
140
|
advanceToImplementing(tasksDir, tasksProgress, taskId, content) {
|
|
48
141
|
// Advance to implementing
|
|
49
142
|
updateTaskStatus(tasksDir, tasksProgress, taskId, "implementing");
|
|
50
143
|
return this.success([
|
|
51
|
-
`✓ Status advanced:
|
|
144
|
+
`✓ Status advanced: planning → implementing`,
|
|
52
145
|
`✓ Task ${taskId}: ${content.title}`,
|
|
53
146
|
"",
|
|
54
|
-
"You may now write code to implement this task.",
|
|
147
|
+
"You may now write code to implement this task based on your plan.",
|
|
55
148
|
].join("\n"), [
|
|
56
149
|
"1. Write the code to implement the task",
|
|
57
150
|
" - Follow the patterns in the codebase",
|
|
@@ -77,6 +170,8 @@ export class CheckCommand extends BaseCommand {
|
|
|
77
170
|
"3. MATCH PATTERNS - Code should be indistinguishable from existing",
|
|
78
171
|
"4. HANDLE ERRORS - Every external call needs error handling",
|
|
79
172
|
"5. NO GUESSING - Verify everything before declaring done",
|
|
173
|
+
"6. CHECK LIBRARY COMPATIBILITY - Before suggesting new libraries, verify no similar library exists, check compatibility, consider security/maintenance",
|
|
174
|
+
"7. SECURITY & PERFORMANCE - Consider security implications, performance impact, backward compatibility",
|
|
80
175
|
"",
|
|
81
176
|
"Operating Mode Selection:",
|
|
82
177
|
"- REACTIVE: Simple, clear, single file",
|
|
@@ -91,6 +186,23 @@ export class CheckCommand extends BaseCommand {
|
|
|
91
186
|
"- Create new patterns when existing ones work",
|
|
92
187
|
"- Declare done without verifying",
|
|
93
188
|
"",
|
|
189
|
+
"3-RETRY LIMIT FOR TESTS:",
|
|
190
|
+
"────────────────────────",
|
|
191
|
+
"Automated tests: Implement test, run full suite, fix failures. Max 3 retry attempts. If still failing, STOP and analyze root cause.",
|
|
192
|
+
"Manual tests: STOP and ask user to verify. Do NOT auto-proceed.",
|
|
193
|
+
"",
|
|
194
|
+
"LEARNINGS TRACKING:",
|
|
195
|
+
"────────────────────",
|
|
196
|
+
"Track learnings for future tasks: capture only general, project-wide insights (not implementation details, not what you did but what you learned, prevent repeated mistakes).",
|
|
197
|
+
"",
|
|
198
|
+
"TECH DEBT REPORTING:",
|
|
199
|
+
"────────────────────────",
|
|
200
|
+
"Report after implementation: tech debt introduced, unfinished work, most impactful next step (focus on high-impact items only).",
|
|
201
|
+
"",
|
|
202
|
+
"DEFINITION OF DONE:",
|
|
203
|
+
"────────────────────",
|
|
204
|
+
"Before declaring complete: functional requirements implemented, tests passing (3-retry limit for automated), lint/type-check pass, documentation updated (if applicable), code reviewed (mandatory), no tech debt or explicitly reported.",
|
|
205
|
+
"",
|
|
94
206
|
"WHEN DONE:",
|
|
95
207
|
"───────────",
|
|
96
208
|
"Run 'taskflow check' to advance to VERIFYING",
|
|
@@ -120,7 +232,7 @@ export class CheckCommand extends BaseCommand {
|
|
|
120
232
|
"2. Verify all acceptance criteria are met:",
|
|
121
233
|
...(content.subtasks || []).map((st) => ` [${st.status === "completed" ? "x" : " "}] ${st.id}. ${st.description}`),
|
|
122
234
|
"",
|
|
123
|
-
"3. Check against .taskflow/ref/
|
|
235
|
+
"3. Check against .taskflow/ref/retrospective.md:",
|
|
124
236
|
" Ensure you haven't repeated known mistakes",
|
|
125
237
|
"",
|
|
126
238
|
"4. When self-review is complete, run:",
|
|
@@ -141,9 +253,17 @@ export class CheckCommand extends BaseCommand {
|
|
|
141
253
|
"□ All subtasks completed",
|
|
142
254
|
"□ Acceptance criteria met",
|
|
143
255
|
"",
|
|
256
|
+
"LEARNINGS TRACKING:",
|
|
257
|
+
"────────────────────",
|
|
258
|
+
"Capture only general, project-wide insights: not implementation details ('I added a function'), not what you did but what you learned, prevent repeated mistakes in future tasks.",
|
|
259
|
+
"",
|
|
260
|
+
"TECH DEBT REPORTING:",
|
|
261
|
+
"────────────────────────",
|
|
262
|
+
"Report after implementation: tech debt introduced, unfinished work, most impactful next step (focus on high-impact items only).",
|
|
263
|
+
"",
|
|
144
264
|
"RETROSPECTIVE CHECK:",
|
|
145
265
|
"────────────────────",
|
|
146
|
-
"Read .taskflow/ref/
|
|
266
|
+
"Read .taskflow/ref/retrospective.md",
|
|
147
267
|
"Confirm you haven't made any known mistakes",
|
|
148
268
|
"These are errors that have been made before",
|
|
149
269
|
"Do NOT repeat them",
|
|
@@ -206,6 +326,12 @@ export class CheckCommand extends BaseCommand {
|
|
|
206
326
|
"3. Lint - check code quality",
|
|
207
327
|
"4. Tests - verify functionality (if configured)",
|
|
208
328
|
"",
|
|
329
|
+
"TEST HANDLING:",
|
|
330
|
+
"────────────────",
|
|
331
|
+
"Automated tests: Implement test, run full suite, fix failures. Max 3 retry attempts. If still failing, STOP and analyze root cause.",
|
|
332
|
+
"Manual tests: STOP and ask user to verify. Do NOT auto-proceed.",
|
|
333
|
+
"Database tests: Do NOT clean up test data.",
|
|
334
|
+
"",
|
|
209
335
|
"IF VALIDATION FAILS:",
|
|
210
336
|
"────────────────────",
|
|
211
337
|
"1. Read the error summary in the output",
|
|
@@ -228,51 +354,138 @@ export class CheckCommand extends BaseCommand {
|
|
|
228
354
|
});
|
|
229
355
|
}
|
|
230
356
|
async advanceToCommitting(tasksDir, logsDir, refDir, tasksProgress, taskId, content, validationCommands) {
|
|
231
|
-
//
|
|
357
|
+
// Check if AI validation is enabled
|
|
358
|
+
const configLoader = new ConfigLoader(this.context.projectRoot);
|
|
359
|
+
const config = configLoader.load();
|
|
360
|
+
// Run AI-powered validation if configured
|
|
361
|
+
if (config.ai?.enabled && config.ai.provider) {
|
|
362
|
+
const aiResult = await this.runAIValidation(logsDir, Phase.Analysis);
|
|
363
|
+
if (!aiResult.passed) {
|
|
364
|
+
return aiResult.result;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// Run traditional validations
|
|
232
368
|
console.log("\n🧪 Running validations...\n");
|
|
233
369
|
const summary = runValidations(logsDir, taskId, validationCommands);
|
|
234
370
|
// Check for known errors in output
|
|
235
371
|
const retroCheck = processValidationOutput(refDir, summary.allOutput);
|
|
236
372
|
if (!summary.passed) {
|
|
373
|
+
// Get LLM error analysis if available
|
|
374
|
+
let llmGuidance = [
|
|
375
|
+
"Validation Failed - Fix Required",
|
|
376
|
+
"",
|
|
377
|
+
retroCheck.knownErrors.length > 0
|
|
378
|
+
? "KNOWN ERRORS DETECTED:"
|
|
379
|
+
: "Errors found in validation.",
|
|
380
|
+
retroCheck.knownErrors.length > 0
|
|
381
|
+
? "You have made mistakes that are already documented."
|
|
382
|
+
: "",
|
|
383
|
+
retroCheck.knownErrors.length > 0
|
|
384
|
+
? "Check the output above for solutions."
|
|
385
|
+
: "",
|
|
386
|
+
retroCheck.knownErrors.length > 0
|
|
387
|
+
? "STOP REPEATING THESE MISTAKES."
|
|
388
|
+
: "",
|
|
389
|
+
"",
|
|
390
|
+
"How to fix:",
|
|
391
|
+
"1. Read error messages carefully",
|
|
392
|
+
"2. Apply solutions from retrospective (if shown)",
|
|
393
|
+
"3. Fix the code",
|
|
394
|
+
"4. Re-run: taskflow check",
|
|
395
|
+
"",
|
|
396
|
+
"DO NOT bypass validations",
|
|
397
|
+
"DO NOT use 'any' types to suppress errors",
|
|
398
|
+
"DO fix the root cause",
|
|
399
|
+
].join("\n");
|
|
400
|
+
// Parse logs and detect new error patterns
|
|
401
|
+
const logParser = new LogParser();
|
|
402
|
+
const logFiles = await readdir(logsDir);
|
|
403
|
+
const parsedErrors = [];
|
|
404
|
+
for (const logFile of logFiles) {
|
|
405
|
+
if (logFile.endsWith(".log")) {
|
|
406
|
+
try {
|
|
407
|
+
const logPath = path.join(logsDir, logFile);
|
|
408
|
+
const parseResult = await logParser.parseFile(logPath);
|
|
409
|
+
parsedErrors.push(...parseResult.errors);
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
// Ignore log parsing errors
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
// Detect NEW error patterns for retrospective
|
|
417
|
+
let newPatternsDetected = [];
|
|
418
|
+
if (parsedErrors.length > 0) {
|
|
419
|
+
const newPatterns = extractNewPatterns(parsedErrors, refDir);
|
|
420
|
+
if (newPatterns.length > 0) {
|
|
421
|
+
newPatternsDetected = newPatterns.map((pattern) => formatNewPatternForDisplay(pattern));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// Get AI error analysis if LLM available
|
|
425
|
+
if (this.isLLMAvailable() && parsedErrors.length > 0) {
|
|
426
|
+
try {
|
|
427
|
+
const errors = parsedErrors.map((error) => ({
|
|
428
|
+
file: error.file,
|
|
429
|
+
message: error.message,
|
|
430
|
+
line: error.line ?? undefined,
|
|
431
|
+
code: error.code ?? undefined,
|
|
432
|
+
}));
|
|
433
|
+
const errorAnalysis = await this.getErrorAnalysis(errors);
|
|
434
|
+
if (errorAnalysis) {
|
|
435
|
+
llmGuidance = [
|
|
436
|
+
"AI Error Analysis:",
|
|
437
|
+
"───────────────────",
|
|
438
|
+
errorAnalysis,
|
|
439
|
+
"",
|
|
440
|
+
"How to fix:",
|
|
441
|
+
"1. Review the AI analysis above",
|
|
442
|
+
"2. Apply suggested fixes file-by-file",
|
|
443
|
+
"3. Re-run: taskflow check",
|
|
444
|
+
"",
|
|
445
|
+
retroCheck.knownErrors.length > 0
|
|
446
|
+
? "⚠️ Known errors also detected - see solutions above"
|
|
447
|
+
: "",
|
|
448
|
+
"",
|
|
449
|
+
newPatternsDetected.length > 0
|
|
450
|
+
? "📝 NEW error patterns detected (see warnings below)"
|
|
451
|
+
: "",
|
|
452
|
+
].join("\n");
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
// Fall back to standard guidance
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
// Build warnings with new patterns
|
|
460
|
+
const warnings = [];
|
|
461
|
+
if (newPatternsDetected.length > 0) {
|
|
462
|
+
warnings.push("📝 NEW Error Patterns Detected:");
|
|
463
|
+
warnings.push("");
|
|
464
|
+
for (const patternDisplay of newPatternsDetected) {
|
|
465
|
+
warnings.push(patternDisplay);
|
|
466
|
+
warnings.push("");
|
|
467
|
+
}
|
|
468
|
+
warnings.push("💡 Consider adding these to retrospective: taskflow retro add");
|
|
469
|
+
warnings.push("");
|
|
470
|
+
}
|
|
471
|
+
const failureOptions = {
|
|
472
|
+
aiGuidance: llmGuidance,
|
|
473
|
+
};
|
|
474
|
+
if (warnings.length > 0) {
|
|
475
|
+
failureOptions.warnings = warnings;
|
|
476
|
+
}
|
|
237
477
|
return this.failure("Validation failed", summary.failedChecks.map((check) => `${check} failed`), [
|
|
238
478
|
"Fix the errors shown above and re-run: taskflow check",
|
|
239
479
|
"",
|
|
240
480
|
retroCheck.knownErrors.length > 0
|
|
241
481
|
? "⚠️ Known errors detected - see solutions above"
|
|
242
482
|
: "",
|
|
243
|
-
retroCheck.hasNewErrors
|
|
483
|
+
retroCheck.hasNewErrors && newPatternsDetected.length === 0
|
|
244
484
|
? "⚠️ New error detected - consider adding to retrospective: taskflow retro add"
|
|
245
485
|
: "",
|
|
246
486
|
"",
|
|
247
487
|
`Full logs: ${logsDir}`,
|
|
248
|
-
].join("\n"),
|
|
249
|
-
aiGuidance: [
|
|
250
|
-
"Validation Failed - Fix Required",
|
|
251
|
-
"",
|
|
252
|
-
retroCheck.knownErrors.length > 0
|
|
253
|
-
? "KNOWN ERRORS DETECTED:"
|
|
254
|
-
: "Errors found in validation.",
|
|
255
|
-
retroCheck.knownErrors.length > 0
|
|
256
|
-
? "You have made mistakes that are already documented."
|
|
257
|
-
: "",
|
|
258
|
-
retroCheck.knownErrors.length > 0
|
|
259
|
-
? "Check the output above for solutions."
|
|
260
|
-
: "",
|
|
261
|
-
retroCheck.knownErrors.length > 0
|
|
262
|
-
? "STOP REPEATING THESE MISTAKES."
|
|
263
|
-
: "",
|
|
264
|
-
"",
|
|
265
|
-
"How to fix:",
|
|
266
|
-
"1. Read error messages carefully",
|
|
267
|
-
"2. Apply solutions from retrospective (if shown)",
|
|
268
|
-
"3. Fix the code",
|
|
269
|
-
"4. Re-run: taskflow check",
|
|
270
|
-
"",
|
|
271
|
-
"DO NOT bypass validations",
|
|
272
|
-
"DO NOT use 'any' types to suppress errors",
|
|
273
|
-
"DO fix the root cause",
|
|
274
|
-
].join("\n"),
|
|
275
|
-
});
|
|
488
|
+
].join("\n"), failureOptions);
|
|
276
489
|
}
|
|
277
490
|
// All validations passed - advance to committing
|
|
278
491
|
updateTaskStatus(tasksDir, tasksProgress, taskId, "committing");
|
|
@@ -316,6 +529,10 @@ export class CheckCommand extends BaseCommand {
|
|
|
316
529
|
"- Be specific and concise",
|
|
317
530
|
"- Focus on user-facing or functional changes",
|
|
318
531
|
"",
|
|
532
|
+
"TECH DEBT REPORTING:",
|
|
533
|
+
"────────────────────────",
|
|
534
|
+
"Report after implementation: tech debt introduced, unfinished work, most impactful next step (focus on high-impact items only).",
|
|
535
|
+
"",
|
|
319
536
|
"WHAT HAPPENS NEXT:",
|
|
320
537
|
"───────────────────",
|
|
321
538
|
"1. Git add all changes",
|
|
@@ -333,7 +550,237 @@ export class CheckCommand extends BaseCommand {
|
|
|
333
550
|
"Commit will run git hooks - they must pass",
|
|
334
551
|
"Push may fail if remote has changes - pull first if needed",
|
|
335
552
|
"This action marks the task as completed",
|
|
553
|
+
"Report any tech debt introduced in commit message or retrospective",
|
|
336
554
|
],
|
|
337
555
|
});
|
|
338
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* Run AI-powered validation on changed files
|
|
559
|
+
*/
|
|
560
|
+
async runAIValidation(logsDir, phase) {
|
|
561
|
+
console.log("\n🤖 Running AI-powered file validation...\n");
|
|
562
|
+
try {
|
|
563
|
+
// Get AI config to create provider with correct settings
|
|
564
|
+
const config = this.configLoader.load();
|
|
565
|
+
if (!config?.ai || !config.ai.enabled) {
|
|
566
|
+
throw new Error("AI configuration not enabled");
|
|
567
|
+
}
|
|
568
|
+
if (!config.ai.provider) {
|
|
569
|
+
throw new Error("AI provider not configured");
|
|
570
|
+
}
|
|
571
|
+
// Create provider using actual config (cast to AIConfig)
|
|
572
|
+
const provider = ProviderFactory.createSelector(config.ai);
|
|
573
|
+
const analysisProvider = provider.getProvider(phase);
|
|
574
|
+
// Find modified files (git status, recent changes, etc.)
|
|
575
|
+
const modifiedFiles = await this.findModifiedFiles();
|
|
576
|
+
if (modifiedFiles.length === 0) {
|
|
577
|
+
console.log("No modified files found for validation");
|
|
578
|
+
return {
|
|
579
|
+
passed: true,
|
|
580
|
+
result: this.success("No files to validate", ""),
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
console.log(`Validating ${modifiedFiles.length} file${modifiedFiles.length > 1 ? "s" : ""}...\n`);
|
|
584
|
+
// Create file validator
|
|
585
|
+
const validator = new FileValidator({
|
|
586
|
+
provider: analysisProvider,
|
|
587
|
+
includeContext: true,
|
|
588
|
+
provideFixes: true,
|
|
589
|
+
maxIssues: 10,
|
|
590
|
+
});
|
|
591
|
+
// Validate each file
|
|
592
|
+
const results = [];
|
|
593
|
+
for (const filePath of modifiedFiles) {
|
|
594
|
+
try {
|
|
595
|
+
const result = await validator.validate(filePath);
|
|
596
|
+
results.push(result);
|
|
597
|
+
}
|
|
598
|
+
catch (error) {
|
|
599
|
+
console.warn(`Failed to validate ${filePath}: ${error.message}`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
// Check if all files passed
|
|
603
|
+
const allPassed = results.every((r) => r.passed);
|
|
604
|
+
// Format and display results
|
|
605
|
+
const output = this.formatValidationResults(results);
|
|
606
|
+
console.log(output);
|
|
607
|
+
if (allPassed) {
|
|
608
|
+
return {
|
|
609
|
+
passed: true,
|
|
610
|
+
result: this.success("All files passed AI validation", "Ready to proceed with standard validation"),
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
// Parse logs for errors to provide context
|
|
614
|
+
const logParser = new LogParser();
|
|
615
|
+
const logFiles = await readdir(logsDir);
|
|
616
|
+
const errors = [];
|
|
617
|
+
for (const logFile of logFiles) {
|
|
618
|
+
if (logFile.endsWith(".log")) {
|
|
619
|
+
try {
|
|
620
|
+
const logPath = path.join(logsDir, logFile);
|
|
621
|
+
const parseResult = await logParser.parseFile(logPath);
|
|
622
|
+
errors.push(...parseResult.errors);
|
|
623
|
+
}
|
|
624
|
+
catch {
|
|
625
|
+
// Ignore log parsing errors
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// Create AI guidance with error context
|
|
630
|
+
const errorSummary = this.createErrorSummary(errors);
|
|
631
|
+
const messages = [
|
|
632
|
+
"Fix issues shown above and re-run: taskflow check",
|
|
633
|
+
"",
|
|
634
|
+
errorSummary,
|
|
635
|
+
"",
|
|
636
|
+
"AI-Powered Validation Benefits:",
|
|
637
|
+
"- Early error detection before compilation",
|
|
638
|
+
"- Context-aware fix suggestions",
|
|
639
|
+
"- Pattern-based issue identification",
|
|
640
|
+
"- Code quality analysis",
|
|
641
|
+
];
|
|
642
|
+
const guidance = [
|
|
643
|
+
"AI Validation Results",
|
|
644
|
+
"────────────────────",
|
|
645
|
+
`Files validated: ${results.length}`,
|
|
646
|
+
`Files passed: ${results.filter((r) => r.passed).length}`,
|
|
647
|
+
`Files failed: ${results.filter((r) => !r.passed).length}`,
|
|
648
|
+
"",
|
|
649
|
+
"Fix Instructions:",
|
|
650
|
+
"1. Review issues shown above for each file",
|
|
651
|
+
"2. Apply suggested fixes",
|
|
652
|
+
"3. Re-run: taskflow check",
|
|
653
|
+
"",
|
|
654
|
+
"If errors persist, check for:",
|
|
655
|
+
"- Incorrect imports or types",
|
|
656
|
+
"- Missing dependencies",
|
|
657
|
+
"- Logic errors or bugs",
|
|
658
|
+
"- Known patterns in retrospective",
|
|
659
|
+
];
|
|
660
|
+
return {
|
|
661
|
+
passed: false,
|
|
662
|
+
result: this.failure("AI validation failed", results.flatMap((r) => r.issues.map((i) => i.message)), messages.join("\n"), {
|
|
663
|
+
aiGuidance: guidance.join("\n"),
|
|
664
|
+
}),
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
catch (error) {
|
|
668
|
+
console.warn(`AI validation failed: ${error.message}`);
|
|
669
|
+
console.log("Falling back to standard validation\n");
|
|
670
|
+
// Return passed to fall back to standard validation
|
|
671
|
+
return {
|
|
672
|
+
passed: true,
|
|
673
|
+
result: this.success("AI validation skipped", "Proceeding with standard validation"),
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Find modified files for validation
|
|
679
|
+
*/
|
|
680
|
+
async findModifiedFiles() {
|
|
681
|
+
try {
|
|
682
|
+
// Get modified, added, and untracked files from git
|
|
683
|
+
const output = execSync("git status --porcelain --untracked-files=all", {
|
|
684
|
+
cwd: this.context.projectRoot,
|
|
685
|
+
encoding: "utf-8",
|
|
686
|
+
}).trim();
|
|
687
|
+
if (!output) {
|
|
688
|
+
return [];
|
|
689
|
+
}
|
|
690
|
+
const files = [];
|
|
691
|
+
const lines = output.split("\n");
|
|
692
|
+
for (const line of lines) {
|
|
693
|
+
// Parse git status output format:
|
|
694
|
+
// XY FILENAME
|
|
695
|
+
// X = status in index, Y = status in working tree
|
|
696
|
+
// Status codes: M (modified), A (added), D (deleted), ?? (untracked), etc.
|
|
697
|
+
const match = line.match(/^(.{2})\s+(.+)$/);
|
|
698
|
+
if (!match)
|
|
699
|
+
continue;
|
|
700
|
+
const [, status, filePath] = match;
|
|
701
|
+
if (!status || !filePath)
|
|
702
|
+
continue;
|
|
703
|
+
// Skip deleted files
|
|
704
|
+
if (status.includes("D"))
|
|
705
|
+
continue;
|
|
706
|
+
// Only validate source files (ts, tsx, js, jsx) but not test files
|
|
707
|
+
const isSourceFile = /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(filePath);
|
|
708
|
+
const isTestFile = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filePath);
|
|
709
|
+
if (isSourceFile && !isTestFile) {
|
|
710
|
+
// Convert to absolute path
|
|
711
|
+
const absolutePath = path.join(this.context.projectRoot, filePath);
|
|
712
|
+
files.push(absolutePath);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return files;
|
|
716
|
+
}
|
|
717
|
+
catch (error) {
|
|
718
|
+
console.warn(`Failed to get modified files: ${error.message}`);
|
|
719
|
+
return [];
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Create error summary from logs and validation results
|
|
724
|
+
*/
|
|
725
|
+
createErrorSummary(errors) {
|
|
726
|
+
if (errors.length === 0) {
|
|
727
|
+
return "No errors found in logs.";
|
|
728
|
+
}
|
|
729
|
+
const grouped = new Map();
|
|
730
|
+
for (const error of errors) {
|
|
731
|
+
if (error.file) {
|
|
732
|
+
const existing = grouped.get(error.file) || [];
|
|
733
|
+
existing.push(error);
|
|
734
|
+
grouped.set(error.file, existing);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
const lines = ["Error Summary:", ""];
|
|
738
|
+
for (const [file, fileErrors] of grouped) {
|
|
739
|
+
lines.push(`${file}: ${fileErrors.length} error${fileErrors.length > 1 ? "s" : ""}`);
|
|
740
|
+
}
|
|
741
|
+
return lines.join("\n");
|
|
742
|
+
}
|
|
743
|
+
/**
|
|
744
|
+
* Format validation results
|
|
745
|
+
*/
|
|
746
|
+
formatValidationResults(results) {
|
|
747
|
+
const lines = [];
|
|
748
|
+
lines.push("=".repeat(80));
|
|
749
|
+
lines.push("AI-Powered Validation Results");
|
|
750
|
+
lines.push("=".repeat(80));
|
|
751
|
+
for (const result of results) {
|
|
752
|
+
lines.push("");
|
|
753
|
+
lines.push(`File: ${result.file}`);
|
|
754
|
+
lines.push(`Status: ${result.passed ? "✓ PASSED" : "✗ FAILED"}`);
|
|
755
|
+
lines.push(`Summary: ${result.summary}`);
|
|
756
|
+
if (result.issues.length > 0) {
|
|
757
|
+
lines.push("");
|
|
758
|
+
lines.push("Issues:");
|
|
759
|
+
for (const issue of result.issues) {
|
|
760
|
+
const icon = issue.severity === "error"
|
|
761
|
+
? "✗"
|
|
762
|
+
: issue.severity === "warning"
|
|
763
|
+
? "⚠"
|
|
764
|
+
: "ℹ";
|
|
765
|
+
lines.push(` ${icon} ${issue.message}`);
|
|
766
|
+
if (issue.line) {
|
|
767
|
+
lines.push(` Line: ${issue.line}`);
|
|
768
|
+
}
|
|
769
|
+
if (issue.suggestedFix) {
|
|
770
|
+
lines.push(` Suggested: ${issue.suggestedFix}`);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (result.suggestions.length > 0) {
|
|
775
|
+
lines.push("");
|
|
776
|
+
lines.push("Suggestions:");
|
|
777
|
+
for (const suggestion of result.suggestions) {
|
|
778
|
+
lines.push(` • ${suggestion}`);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
lines.push("");
|
|
783
|
+
lines.push("=".repeat(80));
|
|
784
|
+
return lines.join("\n");
|
|
785
|
+
}
|
|
339
786
|
}
|