@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.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/index.js +42 -4
  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 +21 -7
  8. package/dist/commands/prd/create.d.ts +1 -1
  9. package/dist/commands/prd/create.js +29 -11
  10. package/dist/commands/prd/generate-arch.d.ts +1 -1
  11. package/dist/commands/prd/generate-arch.js +6 -5
  12. package/dist/commands/retro/list.js +6 -5
  13. package/dist/commands/tasks/generate.d.ts +1 -1
  14. package/dist/commands/tasks/generate.js +83 -56
  15. package/dist/commands/upgrade.js +49 -16
  16. package/dist/commands/workflow/check.d.ts +17 -0
  17. package/dist/commands/workflow/check.js +482 -35
  18. package/dist/commands/workflow/commit.js +117 -60
  19. package/dist/commands/workflow/do.d.ts +1 -0
  20. package/dist/commands/workflow/do.js +206 -13
  21. package/dist/commands/workflow/next.js +4 -4
  22. package/dist/commands/workflow/resume.js +9 -6
  23. package/dist/commands/workflow/start.js +11 -11
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.js +6 -0
  26. package/dist/lib/config-paths.d.ts +15 -15
  27. package/dist/lib/config-paths.js +20 -15
  28. package/dist/lib/file-validator.d.ts +119 -0
  29. package/dist/lib/file-validator.js +291 -0
  30. package/dist/lib/git.js +4 -2
  31. package/dist/lib/log-parser.d.ts +91 -0
  32. package/dist/lib/log-parser.js +178 -0
  33. package/dist/lib/retrospective.d.ts +27 -0
  34. package/dist/lib/retrospective.js +111 -1
  35. package/dist/lib/types.d.ts +19 -6
  36. package/dist/lib/types.js +20 -1
  37. package/dist/lib/validation.d.ts +0 -3
  38. package/dist/lib/validation.js +1 -15
  39. package/dist/llm/base.d.ts +52 -0
  40. package/dist/llm/base.js +35 -0
  41. package/dist/llm/factory.d.ts +39 -0
  42. package/dist/llm/factory.js +102 -0
  43. package/dist/llm/index.d.ts +7 -0
  44. package/dist/llm/index.js +7 -0
  45. package/dist/llm/model-selector.d.ts +71 -0
  46. package/dist/llm/model-selector.js +139 -0
  47. package/dist/llm/providers/anthropic.d.ts +31 -0
  48. package/dist/llm/providers/anthropic.js +116 -0
  49. package/dist/llm/providers/index.d.ts +6 -0
  50. package/dist/llm/providers/index.js +6 -0
  51. package/dist/llm/providers/ollama.d.ts +28 -0
  52. package/dist/llm/providers/ollama.js +91 -0
  53. package/dist/llm/providers/openai-compatible.d.ts +30 -0
  54. package/dist/llm/providers/openai-compatible.js +93 -0
  55. package/dist/schemas/config.d.ts +82 -0
  56. package/dist/schemas/config.js +35 -0
  57. package/dist/schemas/task.d.ts +2 -2
  58. package/dist/state-machine.d.ts +12 -0
  59. package/dist/state-machine.js +2 -2
  60. package/package.json +1 -1
  61. package/dist/lib/package-manager.d.ts +0 -17
  62. package/dist/lib/package-manager.js +0 -53
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PRD Generate Architecture command - Generate CODING-STANDARDS.md and ARCHITECTURE-RULES.md
2
+ * PRD Generate Architecture command - Generate coding-standards.md and architecture-rules.md
3
3
  */
4
4
  import { BaseCommand, type CommandResult } from "../base.js";
5
5
  export declare class PrdGenerateArchCommand extends BaseCommand {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PRD Generate Architecture command - Generate CODING-STANDARDS.md and ARCHITECTURE-RULES.md
2
+ * PRD Generate Architecture command - Generate coding-standards.md and architecture-rules.md
3
3
  */
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -40,10 +40,10 @@ export class PrdGenerateArchCommand extends BaseCommand {
40
40
  if (codingStandardsExist || architectureRulesExist) {
41
41
  return this.failure("Architecture files already exist", [
42
42
  codingStandardsExist
43
- ? `CODING-STANDARDS.md exists at: ${codingStandardsPath}`
43
+ ? `coding-standards.md exists at: ${codingStandardsPath}`
44
44
  : "",
45
45
  architectureRulesExist
46
- ? `ARCHITECTURE-RULES.md exists at: ${architectureRulesPath}`
46
+ ? `architecture-rules.md exists at: ${architectureRulesPath}`
47
47
  : "",
48
48
  ].filter((s) => s.length > 0), [
49
49
  "Options:",
@@ -54,6 +54,7 @@ export class PrdGenerateArchCommand extends BaseCommand {
54
54
  }
55
55
  // Read PRD content
56
56
  const _prdContent = fs.readFileSync(prdFilePath, "utf-8");
57
+ void _prdContent; // Intentionally unused - PRD content is loaded for reference
57
58
  return this.success([
58
59
  `PRD loaded: ${prdFile}`,
59
60
  "",
@@ -121,7 +122,7 @@ export class PrdGenerateArchCommand extends BaseCommand {
121
122
  "- Component patterns (HOCs, hooks, render props)",
122
123
  "- Build and bundling setup",
123
124
  "",
124
- "STEP 3: CREATE CODING-STANDARDS.md",
125
+ "STEP 3: CREATE coding-standards.md",
125
126
  "────────────────────────────────────",
126
127
  `File to create: ${codingStandardsPath}`,
127
128
  "",
@@ -156,7 +157,7 @@ export class PrdGenerateArchCommand extends BaseCommand {
156
157
  " - JSDoc requirements",
157
158
  " - README standards",
158
159
  "",
159
- "STEP 4: CREATE ARCHITECTURE-RULES.md",
160
+ "STEP 4: CREATE architecture-rules.md",
160
161
  "──────────────────────────────────────",
161
162
  `File to create: ${architectureRulesPath}`,
162
163
  "",
@@ -46,7 +46,7 @@ export class RetroListCommand extends BaseCommand {
46
46
  if (!acc[entry.category]) {
47
47
  acc[entry.category] = [];
48
48
  }
49
- acc[entry.category].push(entry);
49
+ acc[entry.category]?.push(entry);
50
50
  return acc;
51
51
  }, {});
52
52
  // Format output
@@ -136,13 +136,13 @@ export class RetroListCommand extends BaseCommand {
136
136
  for (const line of lines) {
137
137
  // Category header: ### TYPE_ERROR
138
138
  const categoryMatch = line.match(/^###\s+(.+)/);
139
- if (categoryMatch) {
139
+ if (categoryMatch?.[1]) {
140
140
  currentCategory = categoryMatch[1].toLowerCase().replace(/\s+/g, "_");
141
141
  continue;
142
142
  }
143
143
  // Entry header: #### TE001: Pattern text (count: 5)
144
144
  const entryMatch = line.match(/^####\s+([A-Z]+\d+):\s+(.+?)\s+\(count:\s*(\d+)\)/i);
145
- if (entryMatch) {
145
+ if (entryMatch?.[1] && entryMatch[2] && entryMatch[3]) {
146
146
  // Save previous entry if exists
147
147
  if (currentEntry?.id) {
148
148
  entries.push(currentEntry);
@@ -151,19 +151,20 @@ export class RetroListCommand extends BaseCommand {
151
151
  id: entryMatch[1],
152
152
  category: currentCategory,
153
153
  pattern: entryMatch[2],
154
+ solution: "", // Required field, will be set when solution is found
154
155
  count: parseInt(entryMatch[3], 10),
155
156
  };
156
157
  continue;
157
158
  }
158
159
  // Solution line: **Solution:** text
159
160
  const solutionMatch = line.match(/^\*\*Solution:\*\*\s+(.+)/);
160
- if (solutionMatch && currentEntry) {
161
+ if (solutionMatch?.[1] && currentEntry) {
161
162
  currentEntry.solution = solutionMatch[1];
162
163
  continue;
163
164
  }
164
165
  // Example line: **Example:** text
165
166
  const exampleMatch = line.match(/^\*\*Example:\*\*\s+(.+)/);
166
- if (exampleMatch && currentEntry) {
167
+ if (exampleMatch?.[1] && currentEntry) {
167
168
  currentEntry.example = exampleMatch[1];
168
169
  }
169
170
  }
@@ -3,5 +3,5 @@
3
3
  */
4
4
  import { BaseCommand, type CommandResult } from "../base.js";
5
5
  export declare class TasksGenerateCommand extends BaseCommand {
6
- execute(prdFile: string): Promise<CommandResult>;
6
+ execute(prdFile?: string): Promise<CommandResult>;
7
7
  }
@@ -11,65 +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
109
  // Get all available skill files
74
110
  const availableSkills = Object.values(SKILL_FILES)
75
111
  .map((skillFile) => {
@@ -79,16 +115,7 @@ export class TasksGenerateCommand extends BaseCommand {
79
115
  : null;
80
116
  })
81
117
  .filter(Boolean);
82
- return this.success([
83
- `PRD loaded: ${prdFile}`,
84
- "✓ CODING-STANDARDS.md found",
85
- "✓ ARCHITECTURE-RULES.md found",
86
- "",
87
- "TASK:",
88
- "─".repeat(60),
89
- "Generate a complete task breakdown from the PRD.",
90
- "Create features, stories, and tasks with proper dependencies.",
91
- ].join("\n"), [
118
+ return this.success(outputParts.join("\n"), [
92
119
  "This is an AI-assisted task. The breakdown will be created as:",
93
120
  ` ${progressFilePath}`,
94
121
  "",
@@ -333,7 +360,7 @@ export class TasksGenerateCommand extends BaseCommand {
333
360
  "",
334
361
  "CRITICAL RULES:",
335
362
  "────────────────",
336
- "1. DO read TASK-GENERATOR.md completely",
363
+ "1. DO read task-generator.md completely",
337
364
  "2. DO analyze the codebase before generating tasks",
338
365
  "3. DO make tasks atomic and independently testable",
339
366
  "4. DO assign realistic skill types",
@@ -354,7 +381,7 @@ export class TasksGenerateCommand extends BaseCommand {
354
381
  "3. Run: taskflow start <task-id> (start working)",
355
382
  ].join("\n"),
356
383
  contextFiles: [
357
- `${prdFilePath} - PRD with requirements`,
384
+ ...(prdFilePath ? [`${prdFilePath} - PRD with requirements`] : []),
358
385
  `${codingStandardsPath} - Project coding standards`,
359
386
  `${architectureRulesPath} - Project architecture rules`,
360
387
  `${getRefFilePath(paths.refDir, REF_FILES.taskGenerator)} - Task generation guidelines`,
@@ -363,7 +390,7 @@ export class TasksGenerateCommand extends BaseCommand {
363
390
  ],
364
391
  warnings: [
365
392
  "DO NOT create overly broad tasks - break them down",
366
- "DO NOT skip reading TASK-GENERATOR.md",
393
+ "DO NOT skip reading task-generator.md",
367
394
  "DO NOT invent context files - reference actual codebase files",
368
395
  "DO ensure every task has clear acceptance criteria",
369
396
  "DO make sure task IDs follow the N.M.K format exactly",
@@ -8,13 +8,13 @@ import { colors, icons } from "../lib/output.js";
8
8
  import { BaseCommand } from "./base.js";
9
9
  const CURRENT_TEMPLATE_VERSION = "0.1.0";
10
10
  const UPDATE_STRATEGIES = {
11
- NEVER: ["RETROSPECTIVE.md"],
12
- PROMPT: ["CODING-STANDARDS.md", "ARCHITECTURE-RULES.md"],
11
+ NEVER: ["retrospective.md"],
12
+ PROMPT: ["coding-standards.md", "architecture-rules.md"],
13
13
  SUGGEST: [
14
- "AI-PROTOCOL.md",
15
- "TASK-GENERATOR.md",
16
- "TASK-EXECUTOR.md",
17
- "PRD-GENERATOR.md",
14
+ "ai-protocol.md",
15
+ "task-generator.md",
16
+ "task-executor.md",
17
+ "prd-generator.md",
18
18
  ],
19
19
  AUTO: [".version"],
20
20
  };
@@ -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;
@@ -97,7 +122,7 @@ export class UpgradeCommand extends BaseCommand {
97
122
  output += `\n${colors.successBold(`${icons.success} Upgrade complete!`)}\n`;
98
123
  output += ` Updated: ${updatedCount} files\n`;
99
124
  output += ` Skipped: ${skippedCount} files\n`;
100
- output += ` Preserved: RETROSPECTIVE.md, logs\n`;
125
+ output += ` Preserved: retrospective.md, logs\n`;
101
126
  return {
102
127
  success: true,
103
128
  output,
@@ -130,13 +155,13 @@ export class UpgradeCommand extends BaseCommand {
130
155
  const files = [];
131
156
  // Map file names to their template paths using the new structure
132
157
  const fileToTemplatePath = {
133
- "AI-PROTOCOL.md": TEMPLATE_FILES.protocols.aiProtocol,
134
- "TASK-GENERATOR.md": TEMPLATE_FILES.protocols.taskGenerator,
135
- "TASK-EXECUTOR.md": TEMPLATE_FILES.protocols.taskExecutor,
136
- "PRD-GENERATOR.md": TEMPLATE_FILES.prd.prdGenerator,
137
- "CODING-STANDARDS.md": TEMPLATE_FILES.project.codingStandards,
138
- "ARCHITECTURE-RULES.md": TEMPLATE_FILES.project.architectureRules,
139
- "RETROSPECTIVE.md": TEMPLATE_FILES.retrospective.retrospective,
158
+ "ai-protocol.md": TEMPLATE_FILES.protocols.aiProtocol,
159
+ "task-generator.md": TEMPLATE_FILES.protocols.taskGenerator,
160
+ "task-executor.md": TEMPLATE_FILES.protocols.taskExecutor,
161
+ "prd-generator.md": TEMPLATE_FILES.prd.prdGenerator,
162
+ "coding-standards.md": TEMPLATE_FILES.project.codingStandards,
163
+ "architecture-rules.md": TEMPLATE_FILES.project.architectureRules,
164
+ "retrospective.md": TEMPLATE_FILES.retrospective.retrospective,
140
165
  };
141
166
  // Get all template files
142
167
  const allFiles = [
@@ -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 {
@@ -4,8 +4,25 @@
4
4
  import { BaseCommand, type CommandResult } from "../base.js";
5
5
  export declare class CheckCommand extends BaseCommand {
6
6
  execute(): Promise<CommandResult>;
7
+ private advanceToPlanning;
7
8
  private advanceToImplementing;
8
9
  private advanceToVerifying;
9
10
  private advanceToValidating;
10
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;
11
28
  }