@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
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";
@@ -11,23 +11,23 @@ export declare function getProjectPaths(projectRoot: string): {
11
11
  configPath: string;
12
12
  };
13
13
  export declare const PROJECT_INDEX_FILE = "project-index.json";
14
- export declare const RETROSPECTIVE_FILE = "RETROSPECTIVE.md";
14
+ export declare const RETROSPECTIVE_FILE = "retrospective.md";
15
15
  export declare const CONFIG_FILE = "taskflow.config.json";
16
16
  export declare const TEMPLATE_FILES: {
17
17
  readonly protocols: {
18
- readonly aiProtocol: "protocols/AI-PROTOCOL.md";
19
- readonly taskGenerator: "protocols/TASK-GENERATOR.md";
20
- readonly taskExecutor: "protocols/TASK-EXECUTOR.md";
18
+ readonly aiProtocol: "protocols/ai-protocol.md";
19
+ readonly taskGenerator: "protocols/task-generator.md";
20
+ readonly taskExecutor: "protocols/task-executor.md";
21
21
  };
22
22
  readonly prd: {
23
- readonly prdGenerator: "prd/PRD-GENERATOR.md";
23
+ readonly prdGenerator: "prd/prd-generator.md";
24
24
  };
25
25
  readonly project: {
26
- readonly codingStandards: "project/CODING-STANDARDS.md";
27
- readonly architectureRules: "project/ARCHITECTURE-RULES.md";
26
+ readonly codingStandards: "project/coding-standards.md";
27
+ readonly architectureRules: "project/architecture-rules.md";
28
28
  };
29
29
  readonly retrospective: {
30
- readonly retrospective: "retrospective/RETROSPECTIVE.md";
30
+ readonly retrospective: "retrospective/retrospective.md";
31
31
  };
32
32
  readonly skills: {
33
33
  readonly backend: "skills/backend.md";
@@ -39,13 +39,13 @@ export declare const TEMPLATE_FILES: {
39
39
  };
40
40
  };
41
41
  export declare const REF_FILES: {
42
- readonly aiProtocol: "AI-PROTOCOL.md";
43
- readonly taskGenerator: "TASK-GENERATOR.md";
44
- readonly taskExecutor: "TASK-EXECUTOR.md";
45
- readonly prdGenerator: "PRD-GENERATOR.md";
46
- readonly codingStandards: "CODING-STANDARDS.md";
47
- readonly architectureRules: "ARCHITECTURE-RULES.md";
48
- readonly retrospective: "RETROSPECTIVE.md";
42
+ readonly aiProtocol: "ai-protocol.md";
43
+ readonly taskGenerator: "task-generator.md";
44
+ readonly taskExecutor: "task-executor.md";
45
+ readonly prdGenerator: "prd-generator.md";
46
+ readonly codingStandards: "coding-standards.md";
47
+ readonly architectureRules: "architecture-rules.md";
48
+ readonly retrospective: "retrospective.md";
49
49
  };
50
50
  export declare const SKILL_FILES: {
51
51
  readonly backend: "skills/backend.md";
@@ -25,26 +25,26 @@ export function getProjectPaths(projectRoot) {
25
25
  // File Names
26
26
  // ============================================================================
27
27
  export const PROJECT_INDEX_FILE = "project-index.json";
28
- export const RETROSPECTIVE_FILE = "RETROSPECTIVE.md";
28
+ export const RETROSPECTIVE_FILE = "retrospective.md";
29
29
  export const CONFIG_FILE = "taskflow.config.json";
30
30
  // ============================================================================
31
31
  // Template Structure (source paths in package)
32
32
  // ============================================================================
33
33
  export const TEMPLATE_FILES = {
34
34
  protocols: {
35
- aiProtocol: "protocols/AI-PROTOCOL.md",
36
- taskGenerator: "protocols/TASK-GENERATOR.md",
37
- taskExecutor: "protocols/TASK-EXECUTOR.md",
35
+ aiProtocol: "protocols/ai-protocol.md",
36
+ taskGenerator: "protocols/task-generator.md",
37
+ taskExecutor: "protocols/task-executor.md",
38
38
  },
39
39
  prd: {
40
- prdGenerator: "prd/PRD-GENERATOR.md",
40
+ prdGenerator: "prd/prd-generator.md",
41
41
  },
42
42
  project: {
43
- codingStandards: "project/CODING-STANDARDS.md",
44
- architectureRules: "project/ARCHITECTURE-RULES.md",
43
+ codingStandards: "project/coding-standards.md",
44
+ architectureRules: "project/architecture-rules.md",
45
45
  },
46
46
  retrospective: {
47
- retrospective: "retrospective/RETROSPECTIVE.md",
47
+ retrospective: "retrospective/retrospective.md",
48
48
  },
49
49
  skills: {
50
50
  backend: "skills/backend.md",
@@ -59,12 +59,12 @@ export const TEMPLATE_FILES = {
59
59
  // Reference Files (destination paths in user's .taskflow/ref directory)
60
60
  // ============================================================================
61
61
  export const REF_FILES = {
62
- aiProtocol: "AI-PROTOCOL.md",
63
- taskGenerator: "TASK-GENERATOR.md",
64
- taskExecutor: "TASK-EXECUTOR.md",
65
- prdGenerator: "PRD-GENERATOR.md",
66
- codingStandards: "CODING-STANDARDS.md",
67
- architectureRules: "ARCHITECTURE-RULES.md",
62
+ aiProtocol: "ai-protocol.md",
63
+ taskGenerator: "task-generator.md",
64
+ taskExecutor: "task-executor.md",
65
+ prdGenerator: "prd-generator.md",
66
+ codingStandards: "coding-standards.md",
67
+ architectureRules: "architecture-rules.md",
68
68
  retrospective: RETROSPECTIVE_FILE,
69
69
  };
70
70
  export const SKILL_FILES = {
@@ -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
+ }
@@ -0,0 +1,291 @@
1
+ /**
2
+ * File Validator
3
+ * Validates code files using LLM to provide fix suggestions and guidance
4
+ */
5
+ import { readFile } from "node:fs/promises";
6
+ /**
7
+ * File Validator class
8
+ * Validates code files using LLM for analysis and fix suggestions
9
+ */
10
+ export class FileValidator {
11
+ options;
12
+ constructor(options) {
13
+ this.options = options;
14
+ }
15
+ /**
16
+ * Validate a file
17
+ */
18
+ async validate(filePath) {
19
+ const content = await readFile(filePath, "utf-8");
20
+ return this.validateContent(filePath, content);
21
+ }
22
+ /**
23
+ * Validate multiple files
24
+ */
25
+ async validateFiles(filePaths) {
26
+ const results = [];
27
+ for (const filePath of filePaths) {
28
+ const result = await this.validate(filePath);
29
+ results.push(result);
30
+ }
31
+ return results;
32
+ }
33
+ /**
34
+ * Validate file content
35
+ */
36
+ async validateContent(filePath, content) {
37
+ const provider = this.options.provider;
38
+ // Create validation prompt
39
+ const messages = [
40
+ {
41
+ role: "user",
42
+ content: this.createValidationPrompt(filePath, content),
43
+ },
44
+ ];
45
+ try {
46
+ // Call LLM for validation
47
+ const response = await provider.generate(messages, {
48
+ maxTokens: 2000,
49
+ temperature: 0.3, // Lower temperature for more deterministic results
50
+ });
51
+ // Parse LLM response
52
+ const issues = this.parseValidationResponse(response.content);
53
+ const suggestions = this.extractSuggestions(issues);
54
+ // Determine if passed
55
+ const hasErrors = issues.some((i) => i.severity === "error");
56
+ const hasWarnings = issues.some((i) => i.severity === "warning");
57
+ const summary = this.createSummary(issues, filePath);
58
+ return {
59
+ file: filePath,
60
+ passed: !hasErrors && !hasWarnings,
61
+ issues,
62
+ suggestions,
63
+ summary,
64
+ };
65
+ }
66
+ catch (error) {
67
+ // Fallback to basic validation if LLM fails
68
+ return this.createFallbackResult(filePath, content, error);
69
+ }
70
+ }
71
+ /**
72
+ * Create validation prompt
73
+ */
74
+ createValidationPrompt(filePath, content) {
75
+ const fileName = filePath.split("/").pop() || "";
76
+ const fileExtension = fileName.split(".").pop() || "";
77
+ const prompt = `Analyze the following ${fileExtension} file and identify any issues:
78
+
79
+ File: ${fileName}
80
+ Path: ${filePath}
81
+
82
+ \`\`\`$${fileExtension}
83
+ ${this.truncateContent(content)}
84
+ \`\`\`
85
+
86
+ Please provide:
87
+ 1. Any syntax errors or type errors
88
+ 2. Any logical errors or bugs
89
+ 3. Code quality issues (naming, complexity, etc.)
90
+ 4. Security concerns
91
+ 5. Performance concerns
92
+ 6. Suggested fixes for issues found
93
+
94
+ Format your response as JSON:
95
+ \`\`\`json
96
+ {
97
+ "issues": [
98
+ {
99
+ "severity": "error" | "warning" | "info",
100
+ "line": number,
101
+ "message": string,
102
+ "code": string,
103
+ "suggestedFix": string
104
+ }
105
+ ],
106
+ "suggestions": ["string", "string"]
107
+ }
108
+ \`\`\`
109
+
110
+ If no issues are found, respond with:
111
+ \`\`\`json
112
+ {
113
+ "issues": [],
114
+ "suggestions": ["File looks good"]
115
+ }
116
+ \`\`\``;
117
+ return prompt;
118
+ }
119
+ /**
120
+ * Truncate content to fit within context limits
121
+ */
122
+ truncateContent(content, maxLength = 8000) {
123
+ if (content.length <= maxLength) {
124
+ return content;
125
+ }
126
+ // Return first part with indicator
127
+ return `${content.substring(0, maxLength)}\n\n... (content truncated)`;
128
+ }
129
+ /**
130
+ * Parse validation response from LLM
131
+ */
132
+ parseValidationResponse(response) {
133
+ try {
134
+ // Try to extract JSON from response
135
+ const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/);
136
+ if (jsonMatch?.[1]) {
137
+ const parsed = JSON.parse(jsonMatch[1]);
138
+ return parsed.issues ?? [];
139
+ }
140
+ // Try to parse entire response as JSON
141
+ const parsed = JSON.parse(response);
142
+ return parsed.issues ?? [];
143
+ }
144
+ catch {
145
+ // If parsing fails, return empty issues
146
+ return [];
147
+ }
148
+ }
149
+ /**
150
+ * Extract suggestions from issues
151
+ */
152
+ extractSuggestions(issues) {
153
+ const suggestions = [];
154
+ for (const issue of issues) {
155
+ if (issue.suggestedFix) {
156
+ suggestions.push(issue.suggestedFix);
157
+ }
158
+ }
159
+ // Add general suggestions if needed
160
+ if (issues.length === 0) {
161
+ suggestions.push("No issues found in the file");
162
+ }
163
+ return suggestions;
164
+ }
165
+ /**
166
+ * Create validation summary
167
+ */
168
+ createSummary(issues, filePath) {
169
+ const errorCount = issues.filter((i) => i.severity === "error").length;
170
+ const warningCount = issues.filter((i) => i.severity === "warning").length;
171
+ const infoCount = issues.filter((i) => i.severity === "info").length;
172
+ const fileName = filePath.split("/").pop() || "";
173
+ if (errorCount === 0 && warningCount === 0 && infoCount === 0) {
174
+ return `${fileName}: No issues found`;
175
+ }
176
+ const parts = [`${fileName}:`];
177
+ if (errorCount > 0) {
178
+ parts.push(`${errorCount} error${errorCount > 1 ? "s" : ""}`);
179
+ }
180
+ if (warningCount > 0) {
181
+ parts.push(`${warningCount} warning${warningCount > 1 ? "s" : ""}`);
182
+ }
183
+ if (infoCount > 0) {
184
+ parts.push(`${infoCount} info`);
185
+ }
186
+ return parts.join(" ");
187
+ }
188
+ /**
189
+ * Create fallback result when LLM fails
190
+ */
191
+ createFallbackResult(filePath, content, error) {
192
+ const fileName = filePath.split("/").pop() || "";
193
+ // Basic validation checks
194
+ const issues = [];
195
+ if (content.trim().length === 0) {
196
+ issues.push({
197
+ severity: "error",
198
+ message: "File is empty",
199
+ code: "EMPTY_FILE",
200
+ });
201
+ }
202
+ if (content.length > 100000) {
203
+ issues.push({
204
+ severity: "warning",
205
+ message: "File is very large, may affect validation",
206
+ code: "LARGE_FILE",
207
+ });
208
+ }
209
+ return {
210
+ file: filePath,
211
+ passed: issues.length === 0,
212
+ issues,
213
+ suggestions: [
214
+ `Validation error: ${error.message}`,
215
+ "AI validation unavailable - showing basic checks only",
216
+ ],
217
+ summary: `${fileName}: Basic validation only (${issues.length} issue${issues.length > 1 ? "s" : ""})`,
218
+ };
219
+ }
220
+ /**
221
+ * Format validation result for display
222
+ */
223
+ formatResult(result) {
224
+ const lines = [];
225
+ lines.push(`\n${"=".repeat(60)}`);
226
+ lines.push(`File: ${result.file}`);
227
+ lines.push(`Status: ${result.passed ? "✓ PASSED" : "✗ FAILED"}`);
228
+ lines.push("=".repeat(60));
229
+ lines.push("");
230
+ if (result.issues.length > 0) {
231
+ lines.push("Issues:");
232
+ lines.push("");
233
+ for (const issue of result.issues.slice(0, this.options.maxIssues || 10)) {
234
+ const icon = issue.severity === "error"
235
+ ? "✗"
236
+ : issue.severity === "warning"
237
+ ? "⚠"
238
+ : "ℹ";
239
+ lines.push(` ${icon} ${issue.message}`);
240
+ if (issue.line) {
241
+ lines.push(` Line: ${issue.line}`);
242
+ }
243
+ if (issue.code) {
244
+ lines.push(` Code: ${issue.code}`);
245
+ }
246
+ if (issue.suggestedFix) {
247
+ lines.push(` Fix: ${issue.suggestedFix}`);
248
+ }
249
+ lines.push("");
250
+ }
251
+ if (result.issues.length > (this.options.maxIssues || 10)) {
252
+ const remaining = result.issues.length - (this.options.maxIssues || 10);
253
+ lines.push(` ... and ${remaining} more issue${remaining > 1 ? "s" : ""} (truncated)`);
254
+ lines.push("");
255
+ }
256
+ }
257
+ if (result.suggestions.length > 0) {
258
+ lines.push("Suggestions:");
259
+ lines.push("");
260
+ for (const suggestion of result.suggestions) {
261
+ lines.push(` • ${suggestion}`);
262
+ }
263
+ lines.push("");
264
+ }
265
+ lines.push(`Summary: ${result.summary}`);
266
+ lines.push("");
267
+ return lines.join("\n");
268
+ }
269
+ /**
270
+ * Format multiple validation results
271
+ */
272
+ formatResults(results) {
273
+ const lines = [];
274
+ lines.push(`\n${"=".repeat(80)}`);
275
+ lines.push("Validation Report");
276
+ lines.push("=".repeat(80));
277
+ const passedCount = results.filter((r) => r.passed).length;
278
+ const failedCount = results.filter((r) => !r.passed).length;
279
+ const totalIssues = results.reduce((sum, r) => sum + r.issues.length, 0);
280
+ lines.push(`Files: ${results.length}`);
281
+ lines.push(`Passed: ${passedCount}`);
282
+ lines.push(`Failed: ${failedCount}`);
283
+ lines.push(`Total Issues: ${totalIssues}`);
284
+ lines.push("=".repeat(80));
285
+ lines.push("");
286
+ for (const result of results) {
287
+ lines.push(this.formatResult(result));
288
+ }
289
+ return lines.join("\n");
290
+ }
291
+ }
package/dist/lib/git.js CHANGED
@@ -100,8 +100,10 @@ export function verifyBranch(story) {
100
100
  console.log("Pulling latest changes...");
101
101
  execaSync("git", ["pull"], { stdio: "inherit" });
102
102
  }
103
- catch {
104
- // Ignore pull errors (e.g. no upstream)
103
+ catch (error) {
104
+ // Warn but proceed - branch may be outdated or have no upstream
105
+ console.warn(`Warning: git pull failed - ${error instanceof Error ? error.message : String(error)}`);
106
+ console.warn("Branch may be outdated. Consider pulling manually before merging.");
105
107
  }
106
108
  execaSync("git", ["checkout", "-b", expected], { stdio: "inherit" });
107
109
  console.log("✓ Branch created and checked out");
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Log Parser
3
+ * Extracts errors and diagnostic information from build/test logs
4
+ */
5
+ export interface ParsedError {
6
+ /**
7
+ * File path (relative or absolute)
8
+ */
9
+ file: string;
10
+ /**
11
+ * Line number where error occurred
12
+ */
13
+ line: number;
14
+ /**
15
+ * Column number where error occurred
16
+ */
17
+ column: number;
18
+ /**
19
+ * Error message
20
+ */
21
+ message: string;
22
+ /**
23
+ * Error code or type (e.g., TS2322, E404)
24
+ */
25
+ code: string;
26
+ /**
27
+ * Error severity (error, warning, info)
28
+ */
29
+ severity: "error" | "warning" | "info";
30
+ /**
31
+ * Context lines around the error
32
+ */
33
+ context?: string[];
34
+ /**
35
+ * Raw log line
36
+ */
37
+ raw: string;
38
+ }
39
+ export interface LogParseResult {
40
+ /**
41
+ * Parsed errors
42
+ */
43
+ errors: ParsedError[];
44
+ /**
45
+ * Warning count
46
+ */
47
+ warningCount: number;
48
+ /**
49
+ * Error count
50
+ */
51
+ errorCount: number;
52
+ /**
53
+ * Success indicator (no errors found)
54
+ */
55
+ success: boolean;
56
+ }
57
+ /**
58
+ * Log Parser class
59
+ * Parses build/test logs to extract errors and diagnostics
60
+ */
61
+ export declare class LogParser {
62
+ private patterns;
63
+ /**
64
+ * Parse log string
65
+ */
66
+ parse(logContent: string): LogParseResult;
67
+ /**
68
+ * Parse log file
69
+ */
70
+ parseFile(filePath: string): Promise<LogParseResult>;
71
+ /**
72
+ * Create error from regex match
73
+ */
74
+ private createErrorFromMatch;
75
+ /**
76
+ * Group errors by file
77
+ */
78
+ groupErrorsByFile(errors: ParsedError[]): Map<string, ParsedError[]>;
79
+ /**
80
+ * Filter errors by severity
81
+ */
82
+ filterBySeverity(errors: ParsedError[], severity: "error" | "warning" | "info"): ParsedError[];
83
+ /**
84
+ * Filter errors by file
85
+ */
86
+ filterByFile(errors: ParsedError[], filePattern: string): ParsedError[];
87
+ /**
88
+ * Format error for display
89
+ */
90
+ formatError(error: ParsedError): string;
91
+ }