@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,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PRD Generate Architecture command - Generate
|
|
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
|
|
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
|
-
? `
|
|
43
|
+
? `coding-standards.md exists at: ${codingStandardsPath}`
|
|
44
44
|
: "",
|
|
45
45
|
architectureRulesExist
|
|
46
|
-
? `
|
|
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
|
|
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
|
|
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]
|
|
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
|
}
|
|
@@ -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
|
-
//
|
|
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
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
|
|
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
|
|
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",
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -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: ["
|
|
12
|
-
PROMPT: ["
|
|
11
|
+
NEVER: ["retrospective.md"],
|
|
12
|
+
PROMPT: ["coding-standards.md", "architecture-rules.md"],
|
|
13
13
|
SUGGEST: [
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
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
|
|
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;
|
|
@@ -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:
|
|
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
|
-
"
|
|
134
|
-
"
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
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
|
}
|