ai-sdlc 0.2.0 → 0.3.0

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 (87) hide show
  1. package/dist/agents/implementation.d.ts +30 -1
  2. package/dist/agents/implementation.d.ts.map +1 -1
  3. package/dist/agents/implementation.js +172 -17
  4. package/dist/agents/implementation.js.map +1 -1
  5. package/dist/agents/index.d.ts +2 -0
  6. package/dist/agents/index.d.ts.map +1 -1
  7. package/dist/agents/index.js +2 -0
  8. package/dist/agents/index.js.map +1 -1
  9. package/dist/agents/orchestrator.d.ts +61 -0
  10. package/dist/agents/orchestrator.d.ts.map +1 -0
  11. package/dist/agents/orchestrator.js +443 -0
  12. package/dist/agents/orchestrator.js.map +1 -0
  13. package/dist/agents/planning.d.ts +1 -1
  14. package/dist/agents/planning.d.ts.map +1 -1
  15. package/dist/agents/planning.js +33 -1
  16. package/dist/agents/planning.js.map +1 -1
  17. package/dist/agents/review.d.ts +37 -1
  18. package/dist/agents/review.d.ts.map +1 -1
  19. package/dist/agents/review.js +319 -44
  20. package/dist/agents/review.js.map +1 -1
  21. package/dist/agents/rework.d.ts.map +1 -1
  22. package/dist/agents/rework.js +3 -1
  23. package/dist/agents/rework.js.map +1 -1
  24. package/dist/agents/single-task.d.ts +41 -0
  25. package/dist/agents/single-task.d.ts.map +1 -0
  26. package/dist/agents/single-task.js +357 -0
  27. package/dist/agents/single-task.js.map +1 -0
  28. package/dist/agents/verification.d.ts.map +1 -1
  29. package/dist/agents/verification.js +26 -12
  30. package/dist/agents/verification.js.map +1 -1
  31. package/dist/cli/commands.d.ts +7 -0
  32. package/dist/cli/commands.d.ts.map +1 -1
  33. package/dist/cli/commands.js +560 -48
  34. package/dist/cli/commands.js.map +1 -1
  35. package/dist/cli/daemon.d.ts.map +1 -1
  36. package/dist/cli/daemon.js +5 -0
  37. package/dist/cli/daemon.js.map +1 -1
  38. package/dist/cli/runner.d.ts.map +1 -1
  39. package/dist/cli/runner.js +20 -9
  40. package/dist/cli/runner.js.map +1 -1
  41. package/dist/core/client.d.ts +19 -1
  42. package/dist/core/client.d.ts.map +1 -1
  43. package/dist/core/client.js +191 -5
  44. package/dist/core/client.js.map +1 -1
  45. package/dist/core/config.d.ts +9 -1
  46. package/dist/core/config.d.ts.map +1 -1
  47. package/dist/core/config.js +51 -2
  48. package/dist/core/config.js.map +1 -1
  49. package/dist/core/index.d.ts +2 -0
  50. package/dist/core/index.d.ts.map +1 -1
  51. package/dist/core/index.js +2 -0
  52. package/dist/core/index.js.map +1 -1
  53. package/dist/core/llm-utils.d.ts +103 -0
  54. package/dist/core/llm-utils.d.ts.map +1 -0
  55. package/dist/core/llm-utils.js +368 -0
  56. package/dist/core/llm-utils.js.map +1 -0
  57. package/dist/core/process-manager.d.ts +15 -0
  58. package/dist/core/process-manager.d.ts.map +1 -0
  59. package/dist/core/process-manager.js +132 -0
  60. package/dist/core/process-manager.js.map +1 -0
  61. package/dist/core/story.d.ts +35 -1
  62. package/dist/core/story.d.ts.map +1 -1
  63. package/dist/core/story.js +107 -1
  64. package/dist/core/story.js.map +1 -1
  65. package/dist/core/task-parser.d.ts +59 -0
  66. package/dist/core/task-parser.d.ts.map +1 -0
  67. package/dist/core/task-parser.js +235 -0
  68. package/dist/core/task-parser.js.map +1 -0
  69. package/dist/core/task-progress.d.ts +92 -0
  70. package/dist/core/task-progress.d.ts.map +1 -0
  71. package/dist/core/task-progress.js +280 -0
  72. package/dist/core/task-progress.js.map +1 -0
  73. package/dist/core/worktree.d.ts +111 -2
  74. package/dist/core/worktree.d.ts.map +1 -1
  75. package/dist/core/worktree.js +310 -2
  76. package/dist/core/worktree.js.map +1 -1
  77. package/dist/index.js +10 -0
  78. package/dist/index.js.map +1 -1
  79. package/dist/services/error-classifier.d.ts +119 -0
  80. package/dist/services/error-classifier.d.ts.map +1 -0
  81. package/dist/services/error-classifier.js +182 -0
  82. package/dist/services/error-classifier.js.map +1 -0
  83. package/dist/types/index.d.ts +230 -0
  84. package/dist/types/index.d.ts.map +1 -1
  85. package/dist/types/index.js.map +1 -1
  86. package/package.json +3 -2
  87. package/templates/story.md +5 -0
@@ -0,0 +1,235 @@
1
+ import { getLogger } from './logger.js';
2
+ /**
3
+ * Extracts structured tasks from implementation plan markdown content.
4
+ * Returns empty array if no tasks section found (logs warning).
5
+ * Skips malformed tasks with warnings, continues parsing.
6
+ *
7
+ * @param content - Markdown content containing implementation tasks
8
+ * @returns Array of parsed implementation tasks
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const content = `
13
+ * ## Implementation Tasks
14
+ * - [ ] **T1**: Create auth service
15
+ * - Files: \`src/auth.ts\`
16
+ * - Dependencies: none
17
+ * `;
18
+ * const tasks = parseImplementationTasks(content);
19
+ * // => [{ id: 'T1', description: 'Create auth service', ... }]
20
+ * ```
21
+ */
22
+ export function parseImplementationTasks(content) {
23
+ const logger = getLogger();
24
+ const tasks = [];
25
+ // Find the Implementation Tasks section
26
+ const sectionMatch = content.match(/##\s+Implementation\s+Tasks/i);
27
+ if (!sectionMatch) {
28
+ logger.warn('task-parser', 'No Implementation Tasks section found in content');
29
+ return [];
30
+ }
31
+ // Extract content after the Implementation Tasks header
32
+ const startIndex = sectionMatch.index + sectionMatch[0].length;
33
+ const remainingContent = content.substring(startIndex);
34
+ // Split into lines for processing
35
+ const lines = remainingContent.split('\n');
36
+ let currentTask = null;
37
+ for (let i = 0; i < lines.length; i++) {
38
+ const line = lines[i];
39
+ // Stop if we hit another h2 header
40
+ if (line.match(/^##\s+/)) {
41
+ break;
42
+ }
43
+ // Match task line: - [ ] or - [x] followed by **T{n}**: description
44
+ const taskMatch = line.match(/^-\s+\[([ x])\]\s+\*\*T(\d+)\*\*:\s*(.+)$/i);
45
+ if (taskMatch) {
46
+ // Save previous task if exists
47
+ if (currentTask) {
48
+ tasks.push(currentTask);
49
+ }
50
+ const [, checkbox, taskNum, description] = taskMatch;
51
+ const status = checkbox.toLowerCase() === 'x' ? 'completed' : 'pending';
52
+ currentTask = {
53
+ id: `T${taskNum}`,
54
+ description: description.trim(),
55
+ status,
56
+ };
57
+ continue;
58
+ }
59
+ // Match metadata lines (indented with - Field: value)
60
+ if (currentTask) {
61
+ // Match metadata with flexible indentation (spaces or tabs)
62
+ const metadataMatch = line.match(/^\s+-\s+(files|dependencies):\s*(.*)$/i);
63
+ if (metadataMatch) {
64
+ const [, fieldName, value] = metadataMatch;
65
+ const field = fieldName.toLowerCase();
66
+ const trimmedValue = value.trim();
67
+ if (field === 'files') {
68
+ if (trimmedValue) {
69
+ // Split by comma, trim, remove backticks
70
+ currentTask.files = trimmedValue
71
+ .split(',')
72
+ .map(f => f.trim().replace(/`/g, ''))
73
+ .filter(f => f.length > 0);
74
+ if (currentTask.files.length === 0) {
75
+ currentTask.files = undefined;
76
+ }
77
+ }
78
+ }
79
+ else if (field === 'dependencies') {
80
+ if (trimmedValue && trimmedValue.toLowerCase() !== 'none') {
81
+ // Split by comma and trim
82
+ currentTask.dependencies = trimmedValue
83
+ .split(',')
84
+ .map(d => d.trim())
85
+ .filter(d => d.length > 0);
86
+ }
87
+ else {
88
+ // "none" or empty means no dependencies
89
+ currentTask.dependencies = [];
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+ // Don't forget the last task
96
+ if (currentTask) {
97
+ tasks.push(currentTask);
98
+ }
99
+ logger.debug('task-parser', `Parsed ${tasks.length} tasks from content`);
100
+ return tasks;
101
+ }
102
+ /**
103
+ * Converts task objects back to markdown format.
104
+ * Useful for updating plan files after task status changes.
105
+ *
106
+ * @param tasks - Array of implementation tasks to format
107
+ * @returns Markdown string representing the tasks
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const tasks = [
112
+ * { id: 'T1', description: 'Create service', status: 'pending', files: ['src/service.ts'] }
113
+ * ];
114
+ * const markdown = formatImplementationTasks(tasks);
115
+ * // => "## Implementation Tasks\n\n- [ ] **T1**: Create service\n - Files: `src/service.ts`"
116
+ * ```
117
+ */
118
+ export function formatImplementationTasks(tasks) {
119
+ const lines = ['## Implementation Tasks', ''];
120
+ for (const task of tasks) {
121
+ // Map status to checkbox
122
+ const checkbox = task.status === 'completed' ? '[x]' : '[ ]';
123
+ // Task line
124
+ lines.push(`- ${checkbox} **${task.id}**: ${task.description}`);
125
+ // Files metadata (if present)
126
+ if (task.files !== undefined) {
127
+ const filesStr = task.files.map(f => `\`${f}\``).join(', ');
128
+ lines.push(` - Files: ${filesStr}`);
129
+ }
130
+ // Dependencies metadata (if present)
131
+ if (task.dependencies !== undefined) {
132
+ const depsStr = task.dependencies.length === 0 ? 'none' : task.dependencies.join(', ');
133
+ lines.push(` - Dependencies: ${depsStr}`);
134
+ }
135
+ // Blank line between tasks
136
+ lines.push('');
137
+ }
138
+ return lines.join('\n');
139
+ }
140
+ /**
141
+ * Validates task format and dependencies.
142
+ * Checks for circular dependencies and missing references.
143
+ *
144
+ * @param content - Markdown content containing implementation tasks
145
+ * @returns Validation result with errors and warnings
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const result = validateTaskFormat(content);
150
+ * if (!result.valid) {
151
+ * console.error('Validation errors:', result.errors);
152
+ * }
153
+ * if (result.warnings.length > 0) {
154
+ * console.warn('Validation warnings:', result.warnings);
155
+ * }
156
+ * ```
157
+ */
158
+ export function validateTaskFormat(content) {
159
+ const tasks = parseImplementationTasks(content);
160
+ const errors = [];
161
+ const warnings = [];
162
+ // Build a set of all task IDs for reference checking
163
+ const taskIds = new Set(tasks.map(t => t.id));
164
+ // Check for missing dependency references
165
+ for (const task of tasks) {
166
+ if (task.dependencies) {
167
+ for (const depId of task.dependencies) {
168
+ if (!taskIds.has(depId)) {
169
+ warnings.push(`Task ${task.id} depends on ${depId}, which does not exist`);
170
+ }
171
+ }
172
+ }
173
+ }
174
+ // Check for circular dependencies using DFS
175
+ const circularErrors = detectCircularDependencies(tasks);
176
+ errors.push(...circularErrors);
177
+ return {
178
+ valid: errors.length === 0,
179
+ errors,
180
+ warnings,
181
+ };
182
+ }
183
+ /**
184
+ * Detects circular dependencies in the task graph using depth-first search.
185
+ * Returns an array of error messages describing any circular dependencies found.
186
+ *
187
+ * Algorithm: O(V + E) where V = number of tasks, E = number of dependency edges
188
+ *
189
+ * @param tasks - Array of tasks to check
190
+ * @returns Array of error messages (empty if no circular dependencies)
191
+ */
192
+ function detectCircularDependencies(tasks) {
193
+ const errors = [];
194
+ // Build adjacency list: task ID -> array of task IDs it depends on
195
+ const graph = new Map();
196
+ for (const task of tasks) {
197
+ graph.set(task.id, task.dependencies || []);
198
+ }
199
+ // Track visited nodes and recursion stack
200
+ const visited = new Set();
201
+ const recStack = new Set();
202
+ function dfs(taskId, path) {
203
+ if (recStack.has(taskId)) {
204
+ // Found a cycle - build error message
205
+ const cycleStart = path.indexOf(taskId);
206
+ const cycle = [...path.slice(cycleStart), taskId];
207
+ errors.push(`Circular dependency detected: ${cycle.join(' → ')}`);
208
+ return true;
209
+ }
210
+ if (visited.has(taskId)) {
211
+ return false; // Already processed this node
212
+ }
213
+ visited.add(taskId);
214
+ recStack.add(taskId);
215
+ const newPath = [...path, taskId];
216
+ const dependencies = graph.get(taskId) || [];
217
+ for (const depId of dependencies) {
218
+ if (dfs(depId, newPath)) {
219
+ // Propagate cycle detection up (but only report once)
220
+ recStack.delete(taskId);
221
+ return false; // Don't report multiple times
222
+ }
223
+ }
224
+ recStack.delete(taskId);
225
+ return false;
226
+ }
227
+ // Check each task as potential starting point
228
+ for (const task of tasks) {
229
+ if (!visited.has(task.id)) {
230
+ dfs(task.id, []);
231
+ }
232
+ }
233
+ return errors;
234
+ }
235
+ //# sourceMappingURL=task-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-parser.js","sourceRoot":"","sources":["../../src/core/task-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Task progress tracking for resumable implementations
3
+ *
4
+ * Persists task-level progress in story files as markdown tables,
5
+ * enabling orchestrator to resume from last completed task after interruptions.
6
+ */
7
+ import { TaskProgress, TaskStatus } from '../types/index.js';
8
+ /**
9
+ * Parse progress table from markdown content
10
+ *
11
+ * Expected format:
12
+ * ## Task Progress
13
+ *
14
+ * | Task | Status | Started | Completed |
15
+ * |------|--------|---------|-----------|
16
+ * | T1 | completed | 2026-01-16T10:00:00Z | 2026-01-16T10:05:00Z |
17
+ * | T2 | in_progress | 2026-01-16T10:05:30Z | - |
18
+ *
19
+ * @param content - Story file markdown content
20
+ * @returns Array of TaskProgress objects (empty if section missing or corrupted)
21
+ */
22
+ export declare function parseProgressTable(content: string): TaskProgress[];
23
+ /**
24
+ * Generate markdown table from TaskProgress array
25
+ *
26
+ * @param progress - Array of task progress entries
27
+ * @returns Markdown table string
28
+ */
29
+ export declare function generateProgressTable(progress: TaskProgress[]): string;
30
+ /**
31
+ * Read story file content
32
+ *
33
+ * @param storyPath - Absolute path to story.md file
34
+ * @returns Story file content
35
+ * @throws Error if file doesn't exist or can't be read
36
+ */
37
+ export declare function readStoryFile(storyPath: string): Promise<string>;
38
+ /**
39
+ * Write story file content atomically with retry logic
40
+ *
41
+ * @param storyPath - Absolute path to story.md file
42
+ * @param content - New story content
43
+ * @throws Error after all retries exhausted
44
+ */
45
+ export declare function writeStoryFile(storyPath: string, content: string): Promise<void>;
46
+ /**
47
+ * Get all task progress entries from story file
48
+ *
49
+ * @param storyPath - Absolute path to story.md file
50
+ * @returns Array of TaskProgress objects (empty if section missing)
51
+ */
52
+ export declare function getTaskProgress(storyPath: string): Promise<TaskProgress[]>;
53
+ /**
54
+ * Initialize progress tracking for a list of tasks
55
+ *
56
+ * Creates "## Task Progress" section with all tasks in 'pending' status.
57
+ * If section already exists, logs warning and skips initialization.
58
+ *
59
+ * @param storyPath - Absolute path to story.md file
60
+ * @param taskIds - Array of task IDs (e.g., ['T1', 'T2', 'T3'])
61
+ */
62
+ export declare function initializeTaskProgress(storyPath: string, taskIds: string[]): Promise<void>;
63
+ /**
64
+ * Update a specific task's status and timestamps
65
+ *
66
+ * Modifies the task row in the progress table and writes back to disk atomically.
67
+ * Sets timestamps based on status transitions:
68
+ * - 'in_progress': Sets startedAt (if not already set)
69
+ * - 'completed' or 'failed': Sets completedAt
70
+ *
71
+ * @param storyPath - Absolute path to story.md file
72
+ * @param taskId - Task ID to update (e.g., 'T1')
73
+ * @param status - New status
74
+ * @param error - Optional error message (only used with 'failed' status)
75
+ * @throws Error if task not found in progress table
76
+ */
77
+ export declare function updateTaskProgress(storyPath: string, taskId: string, status: TaskStatus, error?: string): Promise<void>;
78
+ /**
79
+ * Get list of task IDs with status 'pending'
80
+ *
81
+ * @param storyPath - Absolute path to story.md file
82
+ * @returns Array of pending task IDs
83
+ */
84
+ export declare function getPendingTasks(storyPath: string): Promise<string[]>;
85
+ /**
86
+ * Get the task ID currently in 'in_progress' status
87
+ *
88
+ * @param storyPath - Absolute path to story.md file
89
+ * @returns Task ID or null if no task is in progress
90
+ */
91
+ export declare function getCurrentTask(storyPath: string): Promise<string | null>;
92
+ //# sourceMappingURL=task-progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-progress.d.ts","sourceRoot":"","sources":["../../src/core/task-progress.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI7D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAiFlE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAetE;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYtE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BtF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAGhF;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAmDf;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAK1E;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAI9E"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Task progress tracking for resumable implementations
3
+ *
4
+ * Persists task-level progress in story files as markdown tables,
5
+ * enabling orchestrator to resume from last completed task after interruptions.
6
+ */
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import writeFileAtomic from 'write-file-atomic';
10
+ const TASK_PROGRESS_SECTION = '## Task Progress';
11
+ /**
12
+ * Parse progress table from markdown content
13
+ *
14
+ * Expected format:
15
+ * ## Task Progress
16
+ *
17
+ * | Task | Status | Started | Completed |
18
+ * |------|--------|---------|-----------|
19
+ * | T1 | completed | 2026-01-16T10:00:00Z | 2026-01-16T10:05:00Z |
20
+ * | T2 | in_progress | 2026-01-16T10:05:30Z | - |
21
+ *
22
+ * @param content - Story file markdown content
23
+ * @returns Array of TaskProgress objects (empty if section missing or corrupted)
24
+ */
25
+ export function parseProgressTable(content) {
26
+ const sectionIndex = content.indexOf(TASK_PROGRESS_SECTION);
27
+ if (sectionIndex === -1) {
28
+ return [];
29
+ }
30
+ // Find the table rows (skip header and separator)
31
+ const afterSection = content.slice(sectionIndex);
32
+ const lines = afterSection.split('\n');
33
+ const taskProgress = [];
34
+ let foundTable = false;
35
+ for (const line of lines) {
36
+ const trimmed = line.trim();
37
+ // Skip section header, empty lines, and markdown table separator
38
+ if (!trimmed || trimmed.startsWith('#') || trimmed.match(/^\|[\s-:|]+\|$/)) {
39
+ continue;
40
+ }
41
+ // Stop at next section
42
+ if (trimmed.startsWith('##') && !trimmed.includes(TASK_PROGRESS_SECTION)) {
43
+ break;
44
+ }
45
+ // Parse table row
46
+ if (trimmed.startsWith('|')) {
47
+ foundTable = true;
48
+ const cells = trimmed
49
+ .split('|')
50
+ .map(cell => cell.trim())
51
+ .filter(cell => cell.length > 0);
52
+ // Skip header row
53
+ if (cells[0] === 'Task' || cells[1] === 'Status') {
54
+ continue;
55
+ }
56
+ // Validate we have at least 4 columns
57
+ if (cells.length < 4) {
58
+ console.warn(`[task-progress] Skipping malformed table row: ${trimmed}`);
59
+ continue;
60
+ }
61
+ const [taskId, statusStr, startedStr, completedStr] = cells;
62
+ // Validate status
63
+ const validStatuses = ['pending', 'in_progress', 'completed', 'failed'];
64
+ if (!validStatuses.includes(statusStr)) {
65
+ console.warn(`[task-progress] Invalid status '${statusStr}' for task ${taskId}, skipping row`);
66
+ continue;
67
+ }
68
+ const progress = {
69
+ taskId,
70
+ status: statusStr,
71
+ };
72
+ // Parse timestamps (handle "-" as missing)
73
+ if (startedStr && startedStr !== '-') {
74
+ progress.startedAt = startedStr;
75
+ }
76
+ if (completedStr && completedStr !== '-') {
77
+ progress.completedAt = completedStr;
78
+ }
79
+ // Handle error column if present (5th column)
80
+ if (cells.length >= 5 && cells[4] && cells[4] !== '-') {
81
+ progress.error = cells[4];
82
+ }
83
+ taskProgress.push(progress);
84
+ }
85
+ }
86
+ if (foundTable && taskProgress.length === 0) {
87
+ console.warn('[task-progress] Found progress table but no valid task rows, table may be corrupted');
88
+ }
89
+ return taskProgress;
90
+ }
91
+ /**
92
+ * Generate markdown table from TaskProgress array
93
+ *
94
+ * @param progress - Array of task progress entries
95
+ * @returns Markdown table string
96
+ */
97
+ export function generateProgressTable(progress) {
98
+ const rows = [];
99
+ // Header
100
+ rows.push('| Task | Status | Started | Completed |');
101
+ rows.push('|------|--------|---------|-----------|');
102
+ // Task rows
103
+ for (const task of progress) {
104
+ const started = task.startedAt || '-';
105
+ const completed = task.completedAt || '-';
106
+ rows.push(`| ${task.taskId} | ${task.status} | ${started} | ${completed} |`);
107
+ }
108
+ return rows.join('\n');
109
+ }
110
+ /**
111
+ * Read story file content
112
+ *
113
+ * @param storyPath - Absolute path to story.md file
114
+ * @returns Story file content
115
+ * @throws Error if file doesn't exist or can't be read
116
+ */
117
+ export async function readStoryFile(storyPath) {
118
+ try {
119
+ return await fs.promises.readFile(storyPath, 'utf-8');
120
+ }
121
+ catch (error) {
122
+ if (error.code === 'ENOENT') {
123
+ throw new Error(`Story file not found: ${path.basename(storyPath)}`);
124
+ }
125
+ if (error.code === 'EACCES' || error.code === 'EPERM') {
126
+ throw new Error(`Permission denied reading story file: ${path.basename(storyPath)}`);
127
+ }
128
+ throw new Error(`Failed to read story file: ${error.message}`);
129
+ }
130
+ }
131
+ /**
132
+ * Write story file content atomically with retry logic
133
+ *
134
+ * @param storyPath - Absolute path to story.md file
135
+ * @param content - New story content
136
+ * @throws Error after all retries exhausted
137
+ */
138
+ export async function writeStoryFile(storyPath, content) {
139
+ const maxRetries = 3;
140
+ const retryDelays = [100, 200, 400]; // Exponential backoff
141
+ // Ensure parent directory exists first (outside retry loop)
142
+ const storyDir = path.dirname(storyPath);
143
+ await fs.promises.mkdir(storyDir, { recursive: true });
144
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
145
+ try {
146
+ // Atomic write
147
+ await writeFileAtomic(storyPath, content, { encoding: 'utf-8' });
148
+ return; // Success
149
+ }
150
+ catch (error) {
151
+ const isLastAttempt = attempt === maxRetries - 1;
152
+ // Don't retry on permission errors - throw immediately
153
+ if (error.code === 'EACCES' || error.code === 'EPERM') {
154
+ throw new Error(`Permission denied writing story file: ${path.basename(storyPath)}`);
155
+ }
156
+ if (isLastAttempt) {
157
+ throw new Error(`Failed to write story file after ${maxRetries} attempts`);
158
+ }
159
+ // Wait before retry
160
+ await new Promise(resolve => setTimeout(resolve, retryDelays[attempt]));
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * Get all task progress entries from story file
166
+ *
167
+ * @param storyPath - Absolute path to story.md file
168
+ * @returns Array of TaskProgress objects (empty if section missing)
169
+ */
170
+ export async function getTaskProgress(storyPath) {
171
+ const content = await readStoryFile(storyPath);
172
+ return parseProgressTable(content);
173
+ }
174
+ /**
175
+ * Initialize progress tracking for a list of tasks
176
+ *
177
+ * Creates "## Task Progress" section with all tasks in 'pending' status.
178
+ * If section already exists, logs warning and skips initialization.
179
+ *
180
+ * @param storyPath - Absolute path to story.md file
181
+ * @param taskIds - Array of task IDs (e.g., ['T1', 'T2', 'T3'])
182
+ */
183
+ export async function initializeTaskProgress(storyPath, taskIds) {
184
+ const content = await readStoryFile(storyPath);
185
+ // Check if progress section already exists
186
+ if (content.includes(TASK_PROGRESS_SECTION)) {
187
+ console.warn('[task-progress] Progress section already exists, skipping initialization');
188
+ return;
189
+ }
190
+ // Create initial progress entries (all pending)
191
+ const progress = taskIds.map(taskId => ({
192
+ taskId,
193
+ status: 'pending',
194
+ }));
195
+ const progressTable = generateProgressTable(progress);
196
+ const progressSection = `\n${TASK_PROGRESS_SECTION}\n\n${progressTable}\n`;
197
+ // Append to end of file
198
+ const newContent = content.trimEnd() + '\n' + progressSection;
199
+ await writeStoryFile(storyPath, newContent);
200
+ }
201
+ /**
202
+ * Update a specific task's status and timestamps
203
+ *
204
+ * Modifies the task row in the progress table and writes back to disk atomically.
205
+ * Sets timestamps based on status transitions:
206
+ * - 'in_progress': Sets startedAt (if not already set)
207
+ * - 'completed' or 'failed': Sets completedAt
208
+ *
209
+ * @param storyPath - Absolute path to story.md file
210
+ * @param taskId - Task ID to update (e.g., 'T1')
211
+ * @param status - New status
212
+ * @param error - Optional error message (only used with 'failed' status)
213
+ * @throws Error if task not found in progress table
214
+ */
215
+ export async function updateTaskProgress(storyPath, taskId, status, error) {
216
+ const content = await readStoryFile(storyPath);
217
+ const progress = parseProgressTable(content);
218
+ // Find task to update
219
+ const taskIndex = progress.findIndex(t => t.taskId === taskId);
220
+ if (taskIndex === -1) {
221
+ throw new Error(`Task ${taskId} not found in progress table`);
222
+ }
223
+ const task = progress[taskIndex];
224
+ const now = new Date().toISOString();
225
+ // Update status
226
+ task.status = status;
227
+ // Set timestamps based on status transition
228
+ if (status === 'in_progress' && !task.startedAt) {
229
+ task.startedAt = now;
230
+ }
231
+ if (status === 'completed' || status === 'failed') {
232
+ task.completedAt = now;
233
+ }
234
+ // Store error message if provided
235
+ if (error) {
236
+ task.error = error;
237
+ }
238
+ // Regenerate table
239
+ const newTable = generateProgressTable(progress);
240
+ // Replace progress section in content
241
+ const sectionIndex = content.indexOf(TASK_PROGRESS_SECTION);
242
+ if (sectionIndex === -1) {
243
+ throw new Error('Progress section disappeared during update, this should not happen');
244
+ }
245
+ // Find next section or end of file
246
+ const afterSection = content.slice(sectionIndex + TASK_PROGRESS_SECTION.length);
247
+ const nextSectionMatch = afterSection.match(/\n## [^#]/);
248
+ const nextSectionOffset = nextSectionMatch
249
+ ? sectionIndex + TASK_PROGRESS_SECTION.length + nextSectionMatch.index
250
+ : content.length;
251
+ // Rebuild content
252
+ const beforeSection = content.slice(0, sectionIndex);
253
+ const afterNextSection = content.slice(nextSectionOffset);
254
+ const newContent = `${beforeSection}${TASK_PROGRESS_SECTION}\n\n${newTable}\n${afterNextSection}`;
255
+ await writeStoryFile(storyPath, newContent);
256
+ }
257
+ /**
258
+ * Get list of task IDs with status 'pending'
259
+ *
260
+ * @param storyPath - Absolute path to story.md file
261
+ * @returns Array of pending task IDs
262
+ */
263
+ export async function getPendingTasks(storyPath) {
264
+ const progress = await getTaskProgress(storyPath);
265
+ return progress
266
+ .filter(task => task.status === 'pending')
267
+ .map(task => task.taskId);
268
+ }
269
+ /**
270
+ * Get the task ID currently in 'in_progress' status
271
+ *
272
+ * @param storyPath - Absolute path to story.md file
273
+ * @returns Task ID or null if no task is in progress
274
+ */
275
+ export async function getCurrentTask(storyPath) {
276
+ const progress = await getTaskProgress(storyPath);
277
+ const currentTask = progress.find(task => task.status === 'in_progress');
278
+ return currentTask ? currentTask.taskId : null;
279
+ }
280
+ //# sourceMappingURL=task-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-progress.js","sourceRoot":"","sources":["../../src/core/task-progress.ts"],"names":[],"mappings":"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"}