@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
@@ -36,19 +36,19 @@ export class DoCommand extends BaseCommand {
36
36
  let result = {};
37
37
  switch (status) {
38
38
  case "setup":
39
- result = this.getSetupState(paths.refDir, content, taskId);
39
+ result = await this.getSetupState(paths.refDir, content, taskId);
40
40
  break;
41
41
  case "planning":
42
- result = this.getPlanningState(paths.refDir, content, taskId);
42
+ result = await this.getPlanningState(paths.refDir, content, taskId);
43
43
  break;
44
44
  case "implementing":
45
- result = this.getImplementState(paths.refDir, content, taskId);
45
+ result = await this.getImplementState(paths.refDir, content, taskId);
46
46
  break;
47
47
  case "verifying":
48
- result = this.getVerifyState(paths.refDir, content, taskId);
48
+ result = await this.getVerifyState(paths.refDir, content, taskId);
49
49
  break;
50
50
  case "validating":
51
- result = this.getValidateState();
51
+ result = await this.getValidateState();
52
52
  break;
53
53
  case "committing":
54
54
  result = this.getCommitState(feature.id, taskId, task.title);
@@ -99,7 +99,7 @@ export class DoCommand extends BaseCommand {
99
99
  }
100
100
  return parts.join("\n");
101
101
  }
102
- getSetupState(refDir, taskContent, taskId) {
102
+ async getSetupState(refDir, taskContent, taskId) {
103
103
  const skill = taskContent.skill || "backend";
104
104
  parseTaskId(taskId);
105
105
  const outputParts = [];
@@ -124,10 +124,28 @@ export class DoCommand extends BaseCommand {
124
124
  outputParts.push("1. Read RETROSPECTIVE to avoid known errors");
125
125
  outputParts.push("2. Read AI PROTOCOL to understand workflow rules");
126
126
  outputParts.push("3. Review TASK DETAILS and subtasks");
127
+ // Get LLM guidance if available
128
+ let llmGuidance = "Read and understand. Do not code yet.";
129
+ if (this.isLLMAvailable()) {
130
+ try {
131
+ const enhancedGuidance = await this.getLLMGuidance({
132
+ task: taskContent.title,
133
+ status: "setup",
134
+ files: taskContent.context,
135
+ instructions: "Focus on understanding the task context, not on implementation. Emphasize files to read and patterns to learn.",
136
+ });
137
+ if (enhancedGuidance) {
138
+ llmGuidance = enhancedGuidance;
139
+ }
140
+ }
141
+ catch {
142
+ // Use default guidance if LLM call fails
143
+ }
144
+ }
127
145
  return {
128
146
  output: outputParts.join("\n"),
129
147
  nextSteps: " When you understand the task, run 'taskflow check' to advance to PLANNING",
130
- aiGuidance: "Read and understand. do not code yet.",
148
+ aiGuidance: llmGuidance,
131
149
  contextFiles: [
132
150
  REF_FILES.aiProtocol,
133
151
  REF_FILES.retrospective,
@@ -135,7 +153,7 @@ export class DoCommand extends BaseCommand {
135
153
  ],
136
154
  };
137
155
  }
138
- getPlanningState(refDir, taskContent, taskId) {
156
+ async getPlanningState(refDir, taskContent, taskId) {
139
157
  const skill = taskContent.skill || "backend";
140
158
  const outputParts = [];
141
159
  outputParts.push(colors.infoBold(`${icons.brain} PLANNING STATE - CREATE EXECUTION PLAN`));
@@ -167,6 +185,79 @@ export class DoCommand extends BaseCommand {
167
185
  outputParts.push("3. Define implementation approach");
168
186
  outputParts.push("4. Order subtasks logically");
169
187
  outputParts.push("5. Document your plan");
188
+ // Get LLM guidance if available
189
+ let llmGuidance = [
190
+ "Current Status: PLANNING",
191
+ "Your Goal: Create a clear, documented plan before coding",
192
+ "",
193
+ "PLANNING PROCESS:",
194
+ "────────────────",
195
+ "1. SEARCH FIRST:",
196
+ " - Find existing implementations to match",
197
+ " - Study patterns used in similar code",
198
+ " - Identify relevant files and modules",
199
+ "",
200
+ "2. CONTEXT REVIEW:",
201
+ " - RETROSPECTIVE: Learn what NOT to do",
202
+ " - AI PROTOCOL: Understand workflow rules",
203
+ " - SKILL GUIDES: Domain-specific patterns",
204
+ " - ARCHITECTURE/STANDARDS: Project conventions",
205
+ "",
206
+ "3. PLAN CREATION:",
207
+ " - List files to modify",
208
+ " - Define implementation approach",
209
+ " - Order subtasks logically",
210
+ " - Note integration points",
211
+ " - Plan error handling",
212
+ "",
213
+ "4. RISK CHECK:",
214
+ " - Check RETROSPECTIVE for similar issues",
215
+ " - Identify edge cases",
216
+ " - Consider backward compatibility",
217
+ "",
218
+ "CRITICAL RULES:",
219
+ "───────────────",
220
+ "- Search BEFORE planning",
221
+ "- Match existing patterns, don't invent new ones",
222
+ "- Consider all subtasks in your plan",
223
+ "- Document the approach clearly",
224
+ "",
225
+ "DO NOT:",
226
+ "───────",
227
+ "- Skip planning and start coding",
228
+ "- Assume patterns without searching",
229
+ "- Ignore RETROSPECTIVE warnings",
230
+ "- Create vague or incomplete plans",
231
+ "",
232
+ "WHEN READY:",
233
+ "────────────",
234
+ "Run 'taskflow check' to advance to IMPLEMENTING",
235
+ "Be ready to execute your plan",
236
+ ].join("\n");
237
+ if (this.isLLMAvailable()) {
238
+ try {
239
+ // Read retrospective to include known error patterns in LLM guidance
240
+ const retrospectivePath = getRefFilePath(refDir, REF_FILES.retrospective);
241
+ const retrospectiveContent = loadReferenceFile(retrospectivePath);
242
+ // Build instructions with retrospective context
243
+ let instructions = "Focus on planning guidance: files to modify, patterns to follow, subtask order, potential pitfalls. Keep under 200 words.";
244
+ if (retrospectiveContent) {
245
+ instructions += `\n\nIMPORTANT - Learn from known errors in this project:\n${retrospectiveContent}\n\nAvoid repeating these mistakes in your plan.`;
246
+ }
247
+ const enhancedGuidance = await this.getLLMGuidance({
248
+ task: taskContent.title,
249
+ status: "planning",
250
+ files: taskContent.context,
251
+ instructions,
252
+ });
253
+ if (enhancedGuidance) {
254
+ llmGuidance = enhancedGuidance;
255
+ }
256
+ }
257
+ catch {
258
+ // Use default guidance if LLM call fails
259
+ }
260
+ }
170
261
  return {
171
262
  output: outputParts.join("\n"),
172
263
  nextSteps: [
@@ -175,54 +266,7 @@ export class DoCommand extends BaseCommand {
175
266
  "3. Complete all planning checklist items",
176
267
  "4. taskflow check (When plan is ready)",
177
268
  ].join("\n"),
178
- aiGuidance: [
179
- "Current Status: PLANNING",
180
- "Your Goal: Create a clear, documented plan before coding",
181
- "",
182
- "PLANNING PROCESS:",
183
- "────────────────",
184
- "1. SEARCH FIRST:",
185
- " - Find existing implementations to match",
186
- " - Study patterns used in similar code",
187
- " - Identify relevant files and modules",
188
- "",
189
- "2. CONTEXT REVIEW:",
190
- " - RETROSPECTIVE: Learn what NOT to do",
191
- " - AI PROTOCOL: Understand workflow rules",
192
- " - SKILL GUIDES: Domain-specific patterns",
193
- " - ARCHITECTURE/STANDARDS: Project conventions",
194
- "",
195
- "3. PLAN CREATION:",
196
- " - List files to modify",
197
- " - Define implementation approach",
198
- " - Order subtasks logically",
199
- " - Note integration points",
200
- " - Plan error handling",
201
- "",
202
- "4. RISK CHECK:",
203
- " - Check RETROSPECTIVE for similar issues",
204
- " - Identify edge cases",
205
- " - Consider backward compatibility",
206
- "",
207
- "CRITICAL RULES:",
208
- "───────────────",
209
- "- Search BEFORE planning",
210
- "- Match existing patterns, don't invent new ones",
211
- "- Consider all subtasks in your plan",
212
- "- Document the approach clearly",
213
- "",
214
- "DO NOT:",
215
- "───────",
216
- "- Skip planning and start coding",
217
- "- Assume patterns without searching",
218
- "- Ignore RETROSPECTIVE warnings",
219
- "- Create vague or incomplete plans",
220
- "",
221
- "WHEN READY:",
222
- "────────────",
223
- "Run 'taskflow check' to advance to IMPLEMENTING",
224
- "Be ready to execute your plan",
225
- ].join("\n"),
269
+ aiGuidance: llmGuidance,
226
270
  warnings: [
227
271
  "Most common AI mistake: Skipping planning and writing code immediately",
228
272
  "Always search for existing implementations first",
@@ -230,7 +274,7 @@ export class DoCommand extends BaseCommand {
230
274
  ],
231
275
  };
232
276
  }
233
- getImplementState(refDir, taskContent, taskId) {
277
+ async getImplementState(refDir, taskContent, taskId) {
234
278
  const skill = taskContent.skill || "backend";
235
279
  const outputParts = [];
236
280
  outputParts.push(colors.successBold(`${icons.code} IMPLEMENTING STATE - WRITE CODE NOW`));
@@ -238,6 +282,24 @@ export class DoCommand extends BaseCommand {
238
282
  outputParts.push(colors.error("DO NOT: Modify .taskflow/ or tasks/ directly"));
239
283
  outputParts.push(this.formatTaskDetails(taskId, taskContent.title, skill, taskContent.description, taskContent.subtasks || [], taskContent.context || []));
240
284
  outputParts.push(this.formatReference("AVOID THESE KNOWN ERRORS", getRefFilePath(refDir, REF_FILES.retrospective), colors.error));
285
+ // Get LLM guidance if available
286
+ let llmGuidance = "Implement subtasks one by one. Check off subtasks mostly mentally or via subtask command if available.";
287
+ if (this.isLLMAvailable()) {
288
+ try {
289
+ const enhancedGuidance = await this.getLLMGuidance({
290
+ task: taskContent.title,
291
+ status: "implementing",
292
+ files: taskContent.context,
293
+ instructions: "Focus on implementation guidance: files to modify, patterns to follow, subtask execution order. Keep under 200 words.",
294
+ });
295
+ if (enhancedGuidance) {
296
+ llmGuidance = enhancedGuidance;
297
+ }
298
+ }
299
+ catch {
300
+ // Use default guidance if LLM call fails
301
+ }
302
+ }
241
303
  return {
242
304
  output: outputParts.join("\n"),
243
305
  nextSteps: [
@@ -245,10 +307,10 @@ export class DoCommand extends BaseCommand {
245
307
  "2. Test your changes locally",
246
308
  "3. taskflow check (When ALL subtasks are complete)",
247
309
  ].join("\n"),
248
- aiGuidance: "Implement subtasks one by one. Check off subtasks mostly mentally or via subtask command if available.",
310
+ aiGuidance: llmGuidance,
249
311
  };
250
312
  }
251
- getVerifyState(refDir, taskContent, _taskId) {
313
+ async getVerifyState(refDir, taskContent, _taskId) {
252
314
  const outputParts = [];
253
315
  outputParts.push(colors.infoBold(`${icons.search} VERIFYING STATE - SELF-REVIEW YOUR CODE`));
254
316
  outputParts.push("DO: Review ALL code changes. Verify against checklists.");
@@ -267,6 +329,23 @@ export class DoCommand extends BaseCommand {
267
329
  }
268
330
  }
269
331
  outputParts.push(this.formatReference("CHECK AGAINST RETROSPECTIVE", getRefFilePath(refDir, REF_FILES.retrospective), colors.error));
332
+ // Get LLM guidance if available
333
+ let llmGuidance = "Self-review strictly. Don't skip this step.";
334
+ if (this.isLLMAvailable()) {
335
+ try {
336
+ const enhancedGuidance = await this.getLLMGuidance({
337
+ task: taskContent.title,
338
+ status: "verifying",
339
+ instructions: "Focus on self-review guidance: common mistakes to check, patterns to verify. Keep under 200 words.",
340
+ });
341
+ if (enhancedGuidance) {
342
+ llmGuidance = enhancedGuidance;
343
+ }
344
+ }
345
+ catch {
346
+ // Use default guidance if LLM call fails
347
+ }
348
+ }
270
349
  return {
271
350
  output: outputParts.join("\n"),
272
351
  nextSteps: [
@@ -274,19 +353,35 @@ export class DoCommand extends BaseCommand {
274
353
  "2. Fix any issues found",
275
354
  "3. taskflow check (When self-review is complete)",
276
355
  ].join("\n"),
277
- aiGuidance: "Self-review strictly. Don't skip this step.",
356
+ aiGuidance: llmGuidance,
278
357
  };
279
358
  }
280
- getValidateState() {
359
+ async getValidateState() {
281
360
  const outputParts = [];
282
361
  outputParts.push(colors.infoBold(`${icons.test} VALIDATING STATE - AUTOMATED CHECKS`));
283
362
  outputParts.push("System will run configured checks (format, lint, test, etc.)");
284
363
  outputParts.push("", "ON SUCCESS: Advances to COMMITTING");
285
364
  outputParts.push("ON FAILURE: Stay in VALIDATING details, fix errors.");
365
+ // Get LLM guidance if available
366
+ let llmGuidance = "Run validation. If fails, fix and retry.";
367
+ if (this.isLLMAvailable()) {
368
+ try {
369
+ const enhancedGuidance = await this.getLLMGuidance({
370
+ status: "validating",
371
+ instructions: "Focus on validation guidance: how to fix errors, error analysis approach. Keep under 200 words.",
372
+ });
373
+ if (enhancedGuidance) {
374
+ llmGuidance = enhancedGuidance;
375
+ }
376
+ }
377
+ catch {
378
+ // Use default guidance if LLM call fails
379
+ }
380
+ }
286
381
  return {
287
382
  output: outputParts.join("\n"),
288
383
  nextSteps: "Run 'taskflow check' to run validations",
289
- aiGuidance: "Run validation. If fails, fix and retry.",
384
+ aiGuidance: llmGuidance,
290
385
  };
291
386
  }
292
387
  getCommitState(featureId, taskId, taskTitle) {
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  export * from "./cli/index.js";
6
6
  export * from "./commands/base.js";
7
+ export * from "./commands/configure.js";
7
8
  export * from "./commands/init.js";
8
9
  export * from "./commands/prd/create.js";
9
10
  export * from "./commands/prd/generate-arch.js";
@@ -23,9 +24,12 @@ export * from "./lib/config-loader.js";
23
24
  export * from "./lib/config-paths.js";
24
25
  export * from "./lib/data-access.js";
25
26
  export * from "./lib/errors.js";
27
+ export * from "./lib/file-validator.js";
26
28
  export * from "./lib/git.js";
29
+ export * from "./lib/log-parser.js";
27
30
  export * from "./lib/output.js";
28
31
  export * from "./lib/retrospective.js";
29
32
  export type { ActiveStatus, Criticality, ErrorCategory, Feature, RetrospectiveItem, Story, Subtask, TaskFileContent, TaskflowConfig, TaskRef, TaskStatus, TasksProgress, TimeEntry, } from "./lib/types.js";
30
33
  export { parseTaskId, STATUS_TRANSITIONS, TaskStatusSchema, } from "./lib/types.js";
31
34
  export * from "./lib/validation.js";
35
+ export * from "./llm/index.js";
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ export * from "./cli/index.js";
7
7
  // Export command base (includes CommandContext and CommandResult)
8
8
  export * from "./commands/base.js";
9
9
  // Export all commands
10
+ export * from "./commands/configure.js";
10
11
  export * from "./commands/init.js";
11
12
  export * from "./commands/prd/create.js";
12
13
  export * from "./commands/prd/generate-arch.js";
@@ -29,8 +30,13 @@ export * from "./lib/config-paths.js";
29
30
  export * from "./lib/data-access.js";
30
31
  // Export errors
31
32
  export * from "./lib/errors.js";
33
+ export * from "./lib/file-validator.js";
32
34
  export * from "./lib/git.js";
35
+ // Export log parser and file validator
36
+ export * from "./lib/log-parser.js";
33
37
  export * from "./lib/output.js";
34
38
  export * from "./lib/retrospective.js";
35
39
  export { parseTaskId, STATUS_TRANSITIONS, TaskStatusSchema, } from "./lib/types.js";
36
40
  export * from "./lib/validation.js";
41
+ // Export LLM providers
42
+ export * from "./llm/index.js";
@@ -118,7 +118,12 @@ export function getProjectIndexPath(tasksDir) {
118
118
  return path.join(tasksDir, PROJECT_INDEX_FILE);
119
119
  }
120
120
  export function getFeatureFilePath(tasksDir, featurePath) {
121
- return path.join(tasksDir, featurePath, `${featurePath}.json`);
121
+ // If the path ends in .json, return it as is (relative to tasksDir)
122
+ if (featurePath.endsWith(".json")) {
123
+ return path.join(tasksDir, featurePath);
124
+ }
125
+ // Otherwise assume it's a directory and look for a json file with the same name as the directory
126
+ return path.join(tasksDir, featurePath, `${path.basename(featurePath)}.json`);
122
127
  }
123
128
  export function getRefFilePath(refDir, filename) {
124
129
  return path.join(refDir, filename);
@@ -0,0 +1,119 @@
1
+ /**
2
+ * File Validator
3
+ * Validates code files using LLM to provide fix suggestions and guidance
4
+ */
5
+ import type { LLMProvider } from "../llm/base.js";
6
+ export interface ValidationResult {
7
+ /**
8
+ * File path
9
+ */
10
+ file: string;
11
+ /**
12
+ * Whether file passed validation
13
+ */
14
+ passed: boolean;
15
+ /**
16
+ * Issues found
17
+ */
18
+ issues: ValidationIssue[];
19
+ /**
20
+ * Suggestions for fixes
21
+ */
22
+ suggestions: string[];
23
+ /**
24
+ * Validation summary
25
+ */
26
+ summary: string;
27
+ }
28
+ export interface ValidationIssue {
29
+ /**
30
+ * Severity of the issue
31
+ */
32
+ severity: "error" | "warning" | "info";
33
+ /**
34
+ * Line number (if available)
35
+ */
36
+ line?: number;
37
+ /**
38
+ * Issue description
39
+ */
40
+ message: string;
41
+ /**
42
+ * Code or type of issue
43
+ */
44
+ code?: string;
45
+ /**
46
+ * Suggested fix
47
+ */
48
+ suggestedFix?: string;
49
+ }
50
+ export interface ValidatorOptions {
51
+ /**
52
+ * Provider to use for validation
53
+ */
54
+ provider: LLMProvider;
55
+ /**
56
+ * Whether to include context in validation
57
+ */
58
+ includeContext?: boolean;
59
+ /**
60
+ * Whether to provide fix suggestions
61
+ */
62
+ provideFixes?: boolean;
63
+ /**
64
+ * Maximum issues to report
65
+ */
66
+ maxIssues?: number;
67
+ }
68
+ /**
69
+ * File Validator class
70
+ * Validates code files using LLM for analysis and fix suggestions
71
+ */
72
+ export declare class FileValidator {
73
+ private options;
74
+ constructor(options: ValidatorOptions);
75
+ /**
76
+ * Validate a file
77
+ */
78
+ validate(filePath: string): Promise<ValidationResult>;
79
+ /**
80
+ * Validate multiple files
81
+ */
82
+ validateFiles(filePaths: string[]): Promise<ValidationResult[]>;
83
+ /**
84
+ * Validate file content
85
+ */
86
+ validateContent(filePath: string, content: string): Promise<ValidationResult>;
87
+ /**
88
+ * Create validation prompt
89
+ */
90
+ private createValidationPrompt;
91
+ /**
92
+ * Truncate content to fit within context limits
93
+ */
94
+ private truncateContent;
95
+ /**
96
+ * Parse validation response from LLM
97
+ */
98
+ private parseValidationResponse;
99
+ /**
100
+ * Extract suggestions from issues
101
+ */
102
+ private extractSuggestions;
103
+ /**
104
+ * Create validation summary
105
+ */
106
+ private createSummary;
107
+ /**
108
+ * Create fallback result when LLM fails
109
+ */
110
+ private createFallbackResult;
111
+ /**
112
+ * Format validation result for display
113
+ */
114
+ formatResult(result: ValidationResult): string;
115
+ /**
116
+ * Format multiple validation results
117
+ */
118
+ formatResults(results: ValidationResult[]): string;
119
+ }