@krr2020/taskflow-core 0.1.0-beta.4 → 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 +41 -3
- 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 +15 -1
- package/dist/commands/prd/create.d.ts +1 -1
- package/dist/commands/prd/create.js +26 -8
- package/dist/commands/tasks/generate.d.ts +1 -1
- package/dist/commands/tasks/generate.js +81 -55
- package/dist/commands/upgrade.js +35 -2
- package/dist/commands/workflow/check.d.ts +16 -0
- package/dist/commands/workflow/check.js +355 -32
- package/dist/commands/workflow/do.js +157 -62
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -0
- package/dist/lib/config-paths.js +6 -1
- package/dist/lib/file-validator.d.ts +119 -0
- package/dist/lib/file-validator.js +291 -0
- 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 +110 -0
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/types.js +12 -8
- 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/package.json +43 -43
- package/dist/lib/package-manager.d.ts +0 -17
- package/dist/lib/package-manager.js +0 -53
|
@@ -11,66 +11,101 @@ export class TasksGenerateCommand extends BaseCommand {
|
|
|
11
11
|
const configLoader = new ConfigLoader(this.context.projectRoot);
|
|
12
12
|
const config = configLoader.load();
|
|
13
13
|
const paths = configLoader.getPaths();
|
|
14
|
-
// Validate PRD file parameter
|
|
15
|
-
if (!prdFile || prdFile.trim().length === 0) {
|
|
16
|
-
return this.failure("PRD file is required", ["You must specify the PRD file to generate tasks from"], [
|
|
17
|
-
"Generate tasks from a PRD:",
|
|
18
|
-
" taskflow tasks generate <prd-filename>",
|
|
19
|
-
"",
|
|
20
|
-
"Example:",
|
|
21
|
-
" taskflow tasks generate 2024-01-15-user-auth.md",
|
|
22
|
-
].join("\n"));
|
|
23
|
-
}
|
|
24
14
|
// Resolve PRD file path
|
|
25
15
|
const prdsDir = path.join(paths.tasksDir, "prds");
|
|
26
|
-
const prdFilePath = path.join(prdsDir, prdFile);
|
|
27
|
-
//
|
|
28
|
-
|
|
16
|
+
const prdFilePath = prdFile ? path.join(prdsDir, prdFile) : null;
|
|
17
|
+
// Scan for all PRDs if no file specified
|
|
18
|
+
let availablePrds = [];
|
|
19
|
+
if (fs.existsSync(prdsDir)) {
|
|
20
|
+
availablePrds = fs.readdirSync(prdsDir).filter((f) => f.endsWith(".md"));
|
|
21
|
+
}
|
|
22
|
+
// Validate PRD file parameter
|
|
23
|
+
if (prdFile &&
|
|
24
|
+
availablePrds.length > 0 &&
|
|
25
|
+
!availablePrds.includes(prdFile)) {
|
|
29
26
|
return this.failure("PRD file not found", [`PRD file does not exist: ${prdFilePath}`], [
|
|
30
|
-
"Available
|
|
27
|
+
"Available PRDs:",
|
|
28
|
+
...availablePrds.map((p) => ` - ${p}`),
|
|
29
|
+
"",
|
|
30
|
+
"Options:",
|
|
31
31
|
"1. Check the filename and try again",
|
|
32
|
-
"2.
|
|
32
|
+
"2. Run without arguments to see all PRDs",
|
|
33
33
|
"3. Create a new PRD: taskflow prd create <feature-name>",
|
|
34
34
|
].join("\n"));
|
|
35
35
|
}
|
|
36
|
+
if (availablePrds.length === 0) {
|
|
37
|
+
return this.failure("No PRDs found", ["No PRD files found in tasks/prds/"], [
|
|
38
|
+
"Create a PRD first:",
|
|
39
|
+
" taskflow prd create <feature-name>",
|
|
40
|
+
"",
|
|
41
|
+
"Then generate tasks from it.",
|
|
42
|
+
].join("\n"));
|
|
43
|
+
}
|
|
44
|
+
// Check if tasks already exist (don't block, just inform AI)
|
|
45
|
+
const progressFilePath = path.join(paths.tasksDir, "tasks-progress.json");
|
|
36
46
|
// Check if architecture files exist
|
|
37
47
|
const codingStandardsPath = getRefFilePath(paths.refDir, REF_FILES.codingStandards);
|
|
38
48
|
const architectureRulesPath = getRefFilePath(paths.refDir, REF_FILES.architectureRules);
|
|
39
49
|
const codingStandardsExist = fs.existsSync(codingStandardsPath);
|
|
40
50
|
const architectureRulesExist = fs.existsSync(architectureRulesPath);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"",
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
"",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"",
|
|
55
|
-
"
|
|
51
|
+
// Build output messages
|
|
52
|
+
const outputParts = [];
|
|
53
|
+
if (availablePrds.length > 1 && !prdFile) {
|
|
54
|
+
outputParts.push([
|
|
55
|
+
"AVAILABLE PRDs:",
|
|
56
|
+
"─────────────────",
|
|
57
|
+
...availablePrds.map((p, i) => ` [${i + 1}] ${p} ${fs.existsSync(progressFilePath) ? "(tasks generated ✓)" : ""}`),
|
|
58
|
+
"",
|
|
59
|
+
"DECISION NEEDED:",
|
|
60
|
+
"─────────────────",
|
|
61
|
+
"AI Agent should:",
|
|
62
|
+
" 1. Analyze project context",
|
|
63
|
+
" 2. Determine which PRD(s) to generate tasks for",
|
|
64
|
+
" 3. Consider: Is this adding features to existing project?",
|
|
65
|
+
" 4. Select appropriate PRD or combine multiple PRDs",
|
|
66
|
+
"",
|
|
67
|
+
"OPTIONS:",
|
|
68
|
+
"─────────",
|
|
69
|
+
" - Generate tasks for specific PRD: taskflow tasks generate <filename>",
|
|
70
|
+
" - Generate for all ready PRDs (if appropriate)",
|
|
71
|
+
" - Combine related PRDs into one feature set",
|
|
56
72
|
].join("\n"));
|
|
57
73
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
74
|
+
else if (prdFile) {
|
|
75
|
+
outputParts.push(`PRD loaded: ${prdFile}`);
|
|
76
|
+
if (!codingStandardsExist || !architectureRulesExist) {
|
|
77
|
+
outputParts.push("⚠️ Architecture files missing - Run: taskflow prd generate-arch");
|
|
78
|
+
}
|
|
79
|
+
outputParts.push([
|
|
80
|
+
codingStandardsExist
|
|
81
|
+
? "✓ coding-standards.md found"
|
|
82
|
+
: "⚠️ coding-standards.md missing",
|
|
83
|
+
architectureRulesExist
|
|
84
|
+
? "✓ architecture-rules.md found"
|
|
85
|
+
: "⚠️ architecture-rules.md missing",
|
|
69
86
|
].join("\n"));
|
|
87
|
+
outputParts.push("");
|
|
88
|
+
outputParts.push("TASK:");
|
|
89
|
+
outputParts.push("─".repeat(60));
|
|
90
|
+
outputParts.push("Generate a complete task breakdown from PRD.", "Create features, stories, and tasks with proper dependencies.");
|
|
91
|
+
}
|
|
92
|
+
// Add existing tasks warning if applicable
|
|
93
|
+
const existingTasks = fs.existsSync(progressFilePath);
|
|
94
|
+
if (existingTasks) {
|
|
95
|
+
outputParts.push("");
|
|
96
|
+
outputParts.push("⚠️ EXISTING TASKS DETECTED:");
|
|
97
|
+
outputParts.push("───────────────────────────────");
|
|
98
|
+
outputParts.push(`File: ${progressFilePath} exists`);
|
|
99
|
+
outputParts.push("");
|
|
100
|
+
outputParts.push("OPTIONS:");
|
|
101
|
+
outputParts.push("────────");
|
|
102
|
+
outputParts.push("1. APPEND: Add new PRDs to existing structure");
|
|
103
|
+
outputParts.push("2. MERGE: Combine new PRDs with existing tasks");
|
|
104
|
+
outputParts.push("3. RESET: Delete existing and regenerate (CAUTION: loses progress)");
|
|
105
|
+
outputParts.push("4. SELECTIVE: Generate only specific PRDs");
|
|
106
|
+
outputParts.push("");
|
|
107
|
+
outputParts.push("AI Agent should decide based on project state and user intent.");
|
|
70
108
|
}
|
|
71
|
-
// Read PRD content
|
|
72
|
-
const _prdContent = fs.readFileSync(prdFilePath, "utf-8");
|
|
73
|
-
void _prdContent; // Intentionally unused - PRD content is loaded for reference
|
|
74
109
|
// Get all available skill files
|
|
75
110
|
const availableSkills = Object.values(SKILL_FILES)
|
|
76
111
|
.map((skillFile) => {
|
|
@@ -80,16 +115,7 @@ export class TasksGenerateCommand extends BaseCommand {
|
|
|
80
115
|
: null;
|
|
81
116
|
})
|
|
82
117
|
.filter(Boolean);
|
|
83
|
-
return this.success([
|
|
84
|
-
`PRD loaded: ${prdFile}`,
|
|
85
|
-
"✓ coding-standards.md found",
|
|
86
|
-
"✓ architecture-rules.md found",
|
|
87
|
-
"",
|
|
88
|
-
"TASK:",
|
|
89
|
-
"─".repeat(60),
|
|
90
|
-
"Generate a complete task breakdown from the PRD.",
|
|
91
|
-
"Create features, stories, and tasks with proper dependencies.",
|
|
92
|
-
].join("\n"), [
|
|
118
|
+
return this.success(outputParts.join("\n"), [
|
|
93
119
|
"This is an AI-assisted task. The breakdown will be created as:",
|
|
94
120
|
` ${progressFilePath}`,
|
|
95
121
|
"",
|
|
@@ -355,7 +381,7 @@ export class TasksGenerateCommand extends BaseCommand {
|
|
|
355
381
|
"3. Run: taskflow start <task-id> (start working)",
|
|
356
382
|
].join("\n"),
|
|
357
383
|
contextFiles: [
|
|
358
|
-
`${prdFilePath} - PRD with requirements
|
|
384
|
+
...(prdFilePath ? [`${prdFilePath} - PRD with requirements`] : []),
|
|
359
385
|
`${codingStandardsPath} - Project coding standards`,
|
|
360
386
|
`${architectureRulesPath} - Project architecture rules`,
|
|
361
387
|
`${getRefFilePath(paths.refDir, REF_FILES.taskGenerator)} - Task generation guidelines`,
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -57,6 +57,23 @@ export class UpgradeCommand extends BaseCommand {
|
|
|
57
57
|
nextSteps: "Run without --diff flag to perform the update, or use --auto to skip prompts.",
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
+
// Check for customized files that will be overwritten
|
|
61
|
+
const customizedFiles = updatePlan.files.filter((f) => f.isCustomized && f.strategy !== "NEVER");
|
|
62
|
+
if (customizedFiles.length > 0 && !options?.force) {
|
|
63
|
+
output += `${colors.errorBold("⚠️ WARNING: Customized files detected!")}\n\n`;
|
|
64
|
+
output += `The following files have been modified and will be overwritten:\n`;
|
|
65
|
+
for (const file of customizedFiles) {
|
|
66
|
+
output += ` ${colors.error(`- ${file.name}`)}\n`;
|
|
67
|
+
}
|
|
68
|
+
output += `\n${colors.warning("Your customizations will be LOST!")}\n\n`;
|
|
69
|
+
output += `${colors.highlight("To proceed anyway, use:")}\n`;
|
|
70
|
+
output += ` ${colors.command("taskflow upgrade --force")}\n\n`;
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
output,
|
|
74
|
+
nextSteps: "Review your customizations, then run with --force if you want to proceed",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
60
77
|
// Show files to update
|
|
61
78
|
output += `${colors.highlight("Files to update:")}\n`;
|
|
62
79
|
for (const file of updatePlan.files) {
|
|
@@ -64,16 +81,24 @@ export class UpgradeCommand extends BaseCommand {
|
|
|
64
81
|
output += ` ${colors.muted(`${icons.success} ${file.name} (never touched)`)}\n`;
|
|
65
82
|
}
|
|
66
83
|
else if (file.strategy === "PROMPT") {
|
|
67
|
-
output += ` ${colors.warning(`⚠️ ${file.name} (user-generated, will
|
|
84
|
+
output += ` ${colors.warning(`⚠️ ${file.name} (user-generated, will skip)`)}\n`;
|
|
68
85
|
}
|
|
69
86
|
else if (file.strategy === "SUGGEST") {
|
|
70
|
-
|
|
87
|
+
if (file.isCustomized) {
|
|
88
|
+
output += ` ${colors.warning(`⚠️ ${file.name} (customized, will be overwritten)`)}\n`;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
output += ` ${colors.info(`📝 ${file.name} (will update)`)}\n`;
|
|
92
|
+
}
|
|
71
93
|
}
|
|
72
94
|
}
|
|
73
95
|
// Create backup
|
|
74
96
|
output += `\n${colors.highlight("Creating backup...")}\n`;
|
|
75
97
|
const backupDir = this.createBackup(refDir, currentVersion || "unknown");
|
|
76
98
|
output += `${colors.success(`${icons.success} Backup created:`)} ${backupDir}\n\n`;
|
|
99
|
+
output += `${colors.warning("⚠️ IMPORTANT: Backup location saved above")}\n`;
|
|
100
|
+
output += `You can restore your files if needed:\n`;
|
|
101
|
+
output += ` ${colors.command(`cp ${backupDir}/* ${refDir}/`)}\n\n`;
|
|
77
102
|
// Update files
|
|
78
103
|
let updatedCount = 0;
|
|
79
104
|
let skippedCount = 0;
|
|
@@ -160,12 +185,20 @@ export class UpgradeCommand extends BaseCommand {
|
|
|
160
185
|
const templatePath = templateRelativePath
|
|
161
186
|
? path.join(templateDir, templateRelativePath)
|
|
162
187
|
: path.join(templateDir, fileName);
|
|
188
|
+
// Check if file is customized (exists and differs from template)
|
|
189
|
+
let isCustomized = false;
|
|
190
|
+
if (fs.existsSync(currentPath) && fs.existsSync(templatePath)) {
|
|
191
|
+
const currentContent = fs.readFileSync(currentPath, "utf-8");
|
|
192
|
+
const templateContent = fs.readFileSync(templatePath, "utf-8");
|
|
193
|
+
isCustomized = currentContent !== templateContent;
|
|
194
|
+
}
|
|
163
195
|
files.push({
|
|
164
196
|
name: fileName,
|
|
165
197
|
strategy,
|
|
166
198
|
currentPath,
|
|
167
199
|
templatePath,
|
|
168
200
|
exists: fs.existsSync(currentPath),
|
|
201
|
+
isCustomized,
|
|
169
202
|
});
|
|
170
203
|
}
|
|
171
204
|
return {
|
|
@@ -9,4 +9,20 @@ export declare class CheckCommand extends BaseCommand {
|
|
|
9
9
|
private advanceToVerifying;
|
|
10
10
|
private advanceToValidating;
|
|
11
11
|
private advanceToCommitting;
|
|
12
|
+
/**
|
|
13
|
+
* Run AI-powered validation on changed files
|
|
14
|
+
*/
|
|
15
|
+
private runAIValidation;
|
|
16
|
+
/**
|
|
17
|
+
* Find modified files for validation
|
|
18
|
+
*/
|
|
19
|
+
private findModifiedFiles;
|
|
20
|
+
/**
|
|
21
|
+
* Create error summary from logs and validation results
|
|
22
|
+
*/
|
|
23
|
+
private createErrorSummary;
|
|
24
|
+
/**
|
|
25
|
+
* Format validation results
|
|
26
|
+
*/
|
|
27
|
+
private formatValidationResults;
|
|
12
28
|
}
|