@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.
Files changed (47) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/index.js +41 -3
  3. package/dist/commands/base.d.ts +41 -0
  4. package/dist/commands/base.js +141 -0
  5. package/dist/commands/configure.d.ts +29 -0
  6. package/dist/commands/configure.js +187 -0
  7. package/dist/commands/init.js +15 -1
  8. package/dist/commands/prd/create.d.ts +1 -1
  9. package/dist/commands/prd/create.js +26 -8
  10. package/dist/commands/tasks/generate.d.ts +1 -1
  11. package/dist/commands/tasks/generate.js +81 -55
  12. package/dist/commands/upgrade.js +35 -2
  13. package/dist/commands/workflow/check.d.ts +16 -0
  14. package/dist/commands/workflow/check.js +355 -32
  15. package/dist/commands/workflow/do.js +157 -62
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.js +6 -0
  18. package/dist/lib/config-paths.js +6 -1
  19. package/dist/lib/file-validator.d.ts +119 -0
  20. package/dist/lib/file-validator.js +291 -0
  21. package/dist/lib/log-parser.d.ts +91 -0
  22. package/dist/lib/log-parser.js +178 -0
  23. package/dist/lib/retrospective.d.ts +27 -0
  24. package/dist/lib/retrospective.js +110 -0
  25. package/dist/lib/types.d.ts +8 -0
  26. package/dist/lib/types.js +12 -8
  27. package/dist/llm/base.d.ts +52 -0
  28. package/dist/llm/base.js +35 -0
  29. package/dist/llm/factory.d.ts +39 -0
  30. package/dist/llm/factory.js +102 -0
  31. package/dist/llm/index.d.ts +7 -0
  32. package/dist/llm/index.js +7 -0
  33. package/dist/llm/model-selector.d.ts +71 -0
  34. package/dist/llm/model-selector.js +139 -0
  35. package/dist/llm/providers/anthropic.d.ts +31 -0
  36. package/dist/llm/providers/anthropic.js +116 -0
  37. package/dist/llm/providers/index.d.ts +6 -0
  38. package/dist/llm/providers/index.js +6 -0
  39. package/dist/llm/providers/ollama.d.ts +28 -0
  40. package/dist/llm/providers/ollama.js +91 -0
  41. package/dist/llm/providers/openai-compatible.d.ts +30 -0
  42. package/dist/llm/providers/openai-compatible.js +93 -0
  43. package/dist/schemas/config.d.ts +82 -0
  44. package/dist/schemas/config.js +35 -0
  45. package/package.json +43 -43
  46. package/dist/lib/package-manager.d.ts +0 -17
  47. 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
- // Check if PRD file exists
28
- if (!fs.existsSync(prdFilePath)) {
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 options:",
27
+ "Available PRDs:",
28
+ ...availablePrds.map((p) => ` - ${p}`),
29
+ "",
30
+ "Options:",
31
31
  "1. Check the filename and try again",
32
- "2. List PRD files in tasks/prds/",
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
- if (!codingStandardsExist || !architectureRulesExist) {
42
- return this.failure("Architecture files missing", [
43
- !codingStandardsExist ? "coding-standards.md not found" : "",
44
- !architectureRulesExist ? "architecture-rules.md not found" : "",
45
- "",
46
- "These files must exist before generating tasks.",
47
- ].filter((s) => s.length > 0), [
48
- "Generate architecture files first:",
49
- ` taskflow prd generate-arch ${prdFile}`,
50
- "",
51
- "This will create:",
52
- " - coding-standards.md",
53
- " - architecture-rules.md",
54
- "",
55
- "Then you can generate tasks.",
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
- // Check if tasks already exist
59
- const progressFilePath = path.join(paths.tasksDir, "tasks-progress.json");
60
- if (fs.existsSync(progressFilePath)) {
61
- return this.failure("Tasks already exist", [
62
- "Task breakdown already exists in this project",
63
- `File: ${progressFilePath}`,
64
- ], [
65
- "Options:",
66
- "1. Review existing tasks: taskflow status",
67
- "2. Delete tasks-progress.json to regenerate (CAUTION: loses all progress)",
68
- "3. Manually add new features to the existing structure",
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`,
@@ -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 prompt)`)}\n`;
84
+ output += ` ${colors.warning(`⚠️ ${file.name} (user-generated, will skip)`)}\n`;
68
85
  }
69
86
  else if (file.strategy === "SUGGEST") {
70
- output += ` ${colors.info(`📝 ${file.name} (will update)`)}\n`;
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
  }