claude-devloop 1.0.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 (90) hide show
  1. package/README.md +340 -0
  2. package/dist/cli.d.ts +4 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +90 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/config.d.ts +9 -0
  7. package/dist/commands/config.d.ts.map +1 -0
  8. package/dist/commands/config.js +80 -0
  9. package/dist/commands/config.js.map +1 -0
  10. package/dist/commands/continue.d.ts +11 -0
  11. package/dist/commands/continue.d.ts.map +1 -0
  12. package/dist/commands/continue.js +167 -0
  13. package/dist/commands/continue.js.map +1 -0
  14. package/dist/commands/feature.d.ts +7 -0
  15. package/dist/commands/feature.d.ts.map +1 -0
  16. package/dist/commands/feature.js +123 -0
  17. package/dist/commands/feature.js.map +1 -0
  18. package/dist/commands/init.d.ts +8 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/init.js +401 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/run.d.ts +12 -0
  23. package/dist/commands/run.d.ts.map +1 -0
  24. package/dist/commands/run.js +82 -0
  25. package/dist/commands/run.js.map +1 -0
  26. package/dist/commands/shared.d.ts +22 -0
  27. package/dist/commands/shared.d.ts.map +1 -0
  28. package/dist/commands/shared.js +32 -0
  29. package/dist/commands/shared.js.map +1 -0
  30. package/dist/commands/status.d.ts +8 -0
  31. package/dist/commands/status.d.ts.map +1 -0
  32. package/dist/commands/status.js +305 -0
  33. package/dist/commands/status.js.map +1 -0
  34. package/dist/commands/workspace.d.ts +2 -0
  35. package/dist/commands/workspace.d.ts.map +1 -0
  36. package/dist/commands/workspace.js +19 -0
  37. package/dist/commands/workspace.js.map +1 -0
  38. package/dist/constants.d.ts +21 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +21 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/core/claude.d.ts +20 -0
  43. package/dist/core/claude.d.ts.map +1 -0
  44. package/dist/core/claude.js +401 -0
  45. package/dist/core/claude.js.map +1 -0
  46. package/dist/core/commit-format.d.ts +22 -0
  47. package/dist/core/commit-format.d.ts.map +1 -0
  48. package/dist/core/commit-format.js +148 -0
  49. package/dist/core/commit-format.js.map +1 -0
  50. package/dist/core/config.d.ts +30 -0
  51. package/dist/core/config.d.ts.map +1 -0
  52. package/dist/core/config.js +130 -0
  53. package/dist/core/config.js.map +1 -0
  54. package/dist/core/feature-session.d.ts +8 -0
  55. package/dist/core/feature-session.d.ts.map +1 -0
  56. package/dist/core/feature-session.js +58 -0
  57. package/dist/core/feature-session.js.map +1 -0
  58. package/dist/core/git.d.ts +81 -0
  59. package/dist/core/git.d.ts.map +1 -0
  60. package/dist/core/git.js +475 -0
  61. package/dist/core/git.js.map +1 -0
  62. package/dist/core/loop.d.ts +3 -0
  63. package/dist/core/loop.d.ts.map +1 -0
  64. package/dist/core/loop.js +469 -0
  65. package/dist/core/loop.js.map +1 -0
  66. package/dist/core/session.d.ts +7 -0
  67. package/dist/core/session.d.ts.map +1 -0
  68. package/dist/core/session.js +57 -0
  69. package/dist/core/session.js.map +1 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +4 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/parser/progress.d.ts +7 -0
  75. package/dist/parser/progress.d.ts.map +1 -0
  76. package/dist/parser/progress.js +132 -0
  77. package/dist/parser/progress.js.map +1 -0
  78. package/dist/parser/requirements.d.ts +6 -0
  79. package/dist/parser/requirements.d.ts.map +1 -0
  80. package/dist/parser/requirements.js +126 -0
  81. package/dist/parser/requirements.js.map +1 -0
  82. package/dist/types/feature.d.ts +15 -0
  83. package/dist/types/feature.d.ts.map +1 -0
  84. package/dist/types/feature.js +2 -0
  85. package/dist/types/feature.js.map +1 -0
  86. package/dist/types/index.d.ts +78 -0
  87. package/dist/types/index.d.ts.map +1 -0
  88. package/dist/types/index.js +3 -0
  89. package/dist/types/index.js.map +1 -0
  90. package/package.json +40 -0
@@ -0,0 +1,469 @@
1
+ import ora from 'ora';
2
+ import chalk from 'chalk';
3
+ import { parseRequirements, getNextTask } from '../parser/requirements.js';
4
+ import { readProgress, appendIteration } from '../parser/progress.js';
5
+ import { invokeClaudeAutomated, buildTaskPrompt, isApiError } from './claude.js';
6
+ import { createSession, updateSessionPhase, updateSessionIteration } from './session.js';
7
+ import { createFeatureSession, updateFeatureSessionIteration } from './feature-session.js';
8
+ import { commitIteration, commitInterruptedWork, ensureGitRepo, getUncommittedChanges } from './git.js';
9
+ // Graceful shutdown state
10
+ let stopRequested = false;
11
+ let forceStopRequested = false;
12
+ // Terminal title management
13
+ let originalTitle = null;
14
+ function setTerminalTitle(title) {
15
+ // Save original title on first call
16
+ if (originalTitle === null) {
17
+ originalTitle = 'Terminal'; // Default fallback
18
+ }
19
+ // ANSI escape sequence to set terminal title (works on most terminals)
20
+ process.stdout.write(`\x1b]0;${title}\x07`);
21
+ }
22
+ function restoreTerminalTitle() {
23
+ if (originalTitle !== null) {
24
+ process.stdout.write(`\x1b]0;${originalTitle}\x07`);
25
+ }
26
+ }
27
+ // Elapsed time tracker for spinner
28
+ function formatElapsed(startTime) {
29
+ const elapsed = Math.floor((Date.now() - startTime) / 1000);
30
+ const mins = Math.floor(elapsed / 60);
31
+ const secs = elapsed % 60;
32
+ if (mins > 0) {
33
+ return `${mins}m ${secs}s`;
34
+ }
35
+ return `${secs}s`;
36
+ }
37
+ // Start a spinner with elapsed time updates
38
+ function startTimedSpinner(spinner, baseText, startTime, verbose, terminalTitle) {
39
+ const state = {
40
+ baseText,
41
+ currentActivity: null,
42
+ startTime,
43
+ interval: null
44
+ };
45
+ if (verbose) {
46
+ console.log(chalk.cyan(baseText));
47
+ return state;
48
+ }
49
+ spinner.start(chalk.cyan(`${baseText} (0s)`));
50
+ // Update spinner text and terminal title with elapsed time every second
51
+ // Re-setting terminal title periodically ensures it stays visible even if
52
+ // child processes (like Claude CLI) try to set their own title
53
+ state.interval = setInterval(() => {
54
+ const elapsed = formatElapsed(startTime);
55
+ const activityText = state.currentActivity
56
+ ? `${state.baseText} - ${state.currentActivity} (${elapsed})`
57
+ : `${state.baseText} (${elapsed})`;
58
+ spinner.text = chalk.cyan(activityText);
59
+ if (terminalTitle) {
60
+ setTerminalTitle(terminalTitle);
61
+ }
62
+ }, 1000);
63
+ return state;
64
+ }
65
+ // Update spinner with current activity
66
+ function updateSpinnerActivity(state, activity) {
67
+ state.currentActivity = activity;
68
+ }
69
+ function setupGracefulShutdown() {
70
+ const handler = () => {
71
+ if (forceStopRequested) {
72
+ // Third Ctrl+C - force exit
73
+ console.log(chalk.red('\n\nForce stopping...'));
74
+ process.exit(1);
75
+ }
76
+ else if (stopRequested) {
77
+ // Second Ctrl+C - warn about force stop
78
+ forceStopRequested = true;
79
+ console.log(chalk.yellow('\nPress Ctrl+C again to force stop immediately.'));
80
+ }
81
+ else {
82
+ // First Ctrl+C - request graceful stop
83
+ stopRequested = true;
84
+ console.log(chalk.yellow('\n\nGraceful stop requested - will stop after current task completes.'));
85
+ console.log(chalk.gray('Press Ctrl+C again to force stop (may leave work incomplete).'));
86
+ }
87
+ };
88
+ process.on('SIGINT', handler);
89
+ // Return cleanup function
90
+ return () => {
91
+ process.removeListener('SIGINT', handler);
92
+ stopRequested = false;
93
+ forceStopRequested = false;
94
+ };
95
+ }
96
+ export async function runLoop(config) {
97
+ const spinner = ora();
98
+ const cleanupShutdownHandler = setupGracefulShutdown();
99
+ // Set initial terminal title
100
+ const featurePrefix = config.featureName ? `[${config.featureName}] ` : '';
101
+ setTerminalTitle(`DevLoop: ${featurePrefix}Starting...`);
102
+ console.log(chalk.blue.bold(`\n=== DevLoop Starting ${config.featureName ? `(Feature: ${config.featureName})` : ''} ===\n`));
103
+ console.log(chalk.gray('Tip: Press Ctrl+C to stop after the current task completes.'));
104
+ console.log(chalk.gray(`Workspace: ${config.workspacePath}`));
105
+ if (config.featureName) {
106
+ console.log(chalk.gray(`Feature: ${config.featureName}`));
107
+ }
108
+ console.log(chalk.gray(`Requirements: ${config.requirementsPath}`));
109
+ console.log(chalk.gray(`Progress: ${config.progressPath}`));
110
+ console.log(chalk.gray(`Max iterations: ${config.maxIterations}`));
111
+ if (config.tokenLimit) {
112
+ console.log(chalk.gray(`Token limit: ${config.tokenLimit.toLocaleString()} (per session)`));
113
+ }
114
+ if (config.costLimit) {
115
+ console.log(chalk.gray(`Cost limit: $${config.costLimit.toFixed(2)} (per session)`));
116
+ }
117
+ console.log(chalk.green(`Workspace restriction: ENABLED (--add-dir)`));
118
+ if (config.dryRun) {
119
+ console.log(chalk.yellow('DRY RUN MODE - No changes will be made'));
120
+ }
121
+ console.log();
122
+ // Ensure git repo is set up for version control
123
+ const gitSetup = await ensureGitRepo(config.workspacePath, config.verbose);
124
+ if (gitSetup.gitAvailable) {
125
+ if (gitSetup.wasInitialized) {
126
+ console.log(chalk.green('Git: Repository initialized with initial commit'));
127
+ }
128
+ else {
129
+ console.log(chalk.green('Git: Version control enabled'));
130
+ }
131
+ }
132
+ else {
133
+ console.log(chalk.yellow('Git: Not available - changes will not be versioned'));
134
+ }
135
+ // Check for uncommitted changes (potential interrupted work)
136
+ // Ignore .devloop/ changes as these are session files updated at run start
137
+ let hasInterruptedWork = false;
138
+ let interruptedDuringTask = false; // Track if we interrupted mid-task (for end-of-loop messaging)
139
+ if (gitSetup.gitAvailable) {
140
+ const uncommitted = await getUncommittedChanges(config.workspacePath, ['.devloop/']);
141
+ if (uncommitted.hasChanges) {
142
+ hasInterruptedWork = true;
143
+ console.log(chalk.yellow('\nDetected uncommitted changes (possible interrupted work):'));
144
+ for (const file of uncommitted.files.slice(0, 10)) {
145
+ console.log(chalk.gray(` - ${file}`));
146
+ }
147
+ if (uncommitted.files.length > 10) {
148
+ console.log(chalk.gray(` ... and ${uncommitted.files.length - 10} more files`));
149
+ }
150
+ }
151
+ }
152
+ console.log();
153
+ // Create/update session AFTER uncommitted changes check to avoid false positives
154
+ if (config.sessionAction === 'create') {
155
+ await createSession(config.workspacePath, 'run');
156
+ await updateSessionPhase(config.workspacePath, 'run');
157
+ }
158
+ else if (config.sessionAction === 'update') {
159
+ await updateSessionPhase(config.workspacePath, 'run');
160
+ }
161
+ else if (config.sessionAction === 'create-feature' && config.featureName) {
162
+ await createFeatureSession(config.workspacePath, config.featureName, 'run');
163
+ }
164
+ // Load existing progress to determine starting iteration and token usage
165
+ const existingProgress = await readProgress(config.progressPath);
166
+ const startIteration = existingProgress ? existingProgress.iterations.length + 1 : 1;
167
+ // Calculate project totals from previous iterations (for display)
168
+ let projectTokens = { input: 0, output: 0, cacheWrite: 0, cacheRead: 0, total: 0 };
169
+ let projectCost = 0;
170
+ if (existingProgress) {
171
+ for (const iter of existingProgress.iterations) {
172
+ if (iter.tokenUsage) {
173
+ projectTokens.input += iter.tokenUsage.inputTokens;
174
+ projectTokens.output += iter.tokenUsage.outputTokens;
175
+ projectTokens.cacheWrite += iter.tokenUsage.cacheCreationTokens;
176
+ projectTokens.cacheRead += iter.tokenUsage.cacheReadTokens;
177
+ projectTokens.total += iter.tokenUsage.totalTokens;
178
+ projectCost += iter.tokenUsage.costUsd;
179
+ }
180
+ }
181
+ }
182
+ // Track session tokens separately (for limit checking)
183
+ let sessionTokens = { input: 0, output: 0, cacheWrite: 0, cacheRead: 0, total: 0 };
184
+ let sessionCost = 0;
185
+ // Helper to calculate price per million tokens
186
+ const pricePerMillion = (cost, tokens) => {
187
+ if (tokens === 0)
188
+ return '0.00';
189
+ return ((cost / tokens) * 1_000_000).toFixed(2);
190
+ };
191
+ // maxIterations is additional iterations to run, not absolute count
192
+ const endIteration = startIteration + config.maxIterations - 1;
193
+ if (existingProgress && existingProgress.iterations.length > 0) {
194
+ console.log(chalk.yellow(`Resuming from iteration ${startIteration}`));
195
+ console.log(chalk.gray(`Previously completed: ${existingProgress.completed} tasks`));
196
+ console.log(chalk.gray(`Will run up to ${config.maxIterations} more iterations (${startIteration}-${endIteration})`));
197
+ if (projectTokens.total > 0) {
198
+ console.log(chalk.gray(`Project tokens: ${projectTokens.total.toLocaleString()} total`));
199
+ console.log(chalk.gray(` In: ${projectTokens.input.toLocaleString()} | Out: ${projectTokens.output.toLocaleString()} | Cache +${projectTokens.cacheWrite.toLocaleString()}/-${projectTokens.cacheRead.toLocaleString()}`));
200
+ console.log(chalk.gray(`Project cost: $${projectCost.toFixed(4)} (~$${pricePerMillion(projectCost, projectTokens.total)}/M)`));
201
+ }
202
+ console.log();
203
+ }
204
+ for (let i = startIteration; i <= endIteration; i++) {
205
+ // Check for graceful stop request
206
+ if (stopRequested) {
207
+ console.log(chalk.yellow('\nStopping as requested.'));
208
+ break;
209
+ }
210
+ // Check token limit before starting iteration (session tokens only)
211
+ if (config.tokenLimit && sessionTokens.total >= config.tokenLimit) {
212
+ console.log(chalk.yellow(`\nSession token limit reached: ${sessionTokens.total.toLocaleString()} / ${config.tokenLimit.toLocaleString()}`));
213
+ console.log(chalk.yellow('Stopping to prevent rate limit errors.'));
214
+ break;
215
+ }
216
+ // Check cost limit before starting iteration (session cost only)
217
+ if (config.costLimit && sessionCost >= config.costLimit) {
218
+ console.log(chalk.yellow(`\nSession cost limit reached: $${sessionCost.toFixed(4)} / $${config.costLimit.toFixed(2)}`));
219
+ console.log(chalk.yellow('Stopping to control costs.'));
220
+ break;
221
+ }
222
+ const iterationStart = new Date();
223
+ // Parse requirements fresh each iteration
224
+ spinner.start(chalk.cyan(`Iteration ${i}: Reading requirements...`));
225
+ let requirements;
226
+ try {
227
+ requirements = await parseRequirements(config.requirementsPath);
228
+ }
229
+ catch (error) {
230
+ spinner.fail(chalk.red(`Failed to parse requirements: ${error}`));
231
+ break;
232
+ }
233
+ spinner.stop();
234
+ // Check if all tasks are done
235
+ const pendingTasks = requirements.tasks.filter(t => t.status === 'pending');
236
+ const doneTasks = requirements.tasks.filter(t => t.status === 'done');
237
+ if (pendingTasks.length === 0) {
238
+ setTerminalTitle(`DevLoop: ${featurePrefix}All ${doneTasks.length} tasks complete!`);
239
+ console.log(chalk.green.bold('\n✓ All tasks completed!'));
240
+ console.log(chalk.gray(`Completed ${doneTasks.length} tasks in ${i - 1} iterations.`));
241
+ break;
242
+ }
243
+ // Get next task based on dependencies and priority
244
+ const nextTask = getNextTask(requirements);
245
+ if (!nextTask) {
246
+ console.log(chalk.yellow('\nNo available tasks (all remaining tasks have unmet dependencies)'));
247
+ console.log(chalk.gray('Blocked tasks:'));
248
+ for (const task of pendingTasks) {
249
+ console.log(chalk.gray(` - ${task.id}: depends on ${task.dependencies.join(', ')}`));
250
+ }
251
+ break;
252
+ }
253
+ // Commit interrupted work before starting fresh (only on first iteration)
254
+ if (hasInterruptedWork) {
255
+ console.log(chalk.cyan(`\nCommitting interrupted work (likely from ${nextTask.id})...`));
256
+ const committed = await commitInterruptedWork(config.workspacePath, nextTask.id, nextTask.title, config.verbose);
257
+ if (committed) {
258
+ console.log(chalk.green('Interrupted work committed. Starting fresh.'));
259
+ }
260
+ else {
261
+ // Failed to commit uncommitted changes - stop and let user fix it
262
+ console.log(chalk.red.bold('\n⚠ Failed to commit uncommitted changes'));
263
+ console.log(chalk.red('DevLoop detected uncommitted changes but could not commit them.'));
264
+ console.log(chalk.yellow('\nPlease resolve this manually:'));
265
+ console.log(chalk.gray(' 1. Run "git status" to see the uncommitted changes'));
266
+ console.log(chalk.gray(' 2. Either commit them: git add -A && git commit -m "message"'));
267
+ console.log(chalk.gray(' 3. Or discard them: git checkout -- . && git clean -fd'));
268
+ console.log(chalk.gray(' 4. Then run "devloop continue" to resume\n'));
269
+ break;
270
+ }
271
+ hasInterruptedWork = false; // Only handle once
272
+ }
273
+ // Update terminal title with current task
274
+ const totalTasks = requirements.tasks.length;
275
+ const completedTasks = doneTasks.length;
276
+ setTerminalTitle(`DevLoop: ${featurePrefix}${i}/${config.maxIterations} - ${nextTask.id} (${completedTasks}/${totalTasks} done)`);
277
+ console.log(chalk.cyan(`\nIteration ${i}: ${nextTask.id} - ${nextTask.title}`));
278
+ console.log(chalk.gray(` Priority: ${nextTask.priority}`));
279
+ console.log(chalk.gray(` Description: ${nextTask.description}`));
280
+ console.log(chalk.gray(` Press Ctrl+C to stop after this task completes`));
281
+ if (config.dryRun) {
282
+ console.log(chalk.yellow(` [DRY RUN] Would execute this task`));
283
+ // Record dry run iteration
284
+ const iterationLog = {
285
+ iteration: i,
286
+ timestamp: iterationStart.toISOString(),
287
+ taskCompleted: null,
288
+ summary: `[DRY RUN] Would have executed: ${nextTask.title}`,
289
+ duration: '0s',
290
+ exitStatus: 'partial'
291
+ };
292
+ // Don't actually append to progress in dry run
293
+ continue;
294
+ }
295
+ // Build prompt and invoke Claude with timed spinner
296
+ const taskStartTime = Date.now();
297
+ const currentTitle = `DevLoop: ${i}/${config.maxIterations} - ${nextTask.id} (${completedTasks}/${totalTasks} done)`;
298
+ const spinnerState = startTimedSpinner(spinner, ` Claude working on ${nextTask.id}`, taskStartTime, config.verbose, currentTitle);
299
+ const prompt = buildTaskPrompt(nextTask, config.requirementsPath, config.progressPath, config.workspacePath);
300
+ const result = await invokeClaudeAutomated(prompt, config.workspacePath, {
301
+ verbose: config.verbose,
302
+ onProgress: (activity) => {
303
+ updateSpinnerActivity(spinnerState, activity);
304
+ }
305
+ });
306
+ // Stop the spinner interval
307
+ if (spinnerState.interval) {
308
+ clearInterval(spinnerState.interval);
309
+ }
310
+ // Check if stop was requested during task execution
311
+ // If so, treat as interrupted - do NOT mark as complete even if Claude exited cleanly
312
+ if (stopRequested) {
313
+ if (config.verbose) {
314
+ console.log(chalk.yellow(` ⚠ Task interrupted by user request`));
315
+ }
316
+ else {
317
+ spinner.warn(chalk.yellow(` Task ${nextTask.id} interrupted by user request`));
318
+ }
319
+ const duration = `${Math.round(result.duration / 1000)}s`;
320
+ // Record as interrupted - task was NOT completed
321
+ const iterationLog = {
322
+ iteration: i,
323
+ timestamp: iterationStart.toISOString(),
324
+ taskCompleted: null, // NOT completed
325
+ summary: `Interrupted: ${nextTask.title} (user requested stop)`,
326
+ duration,
327
+ exitStatus: 'interrupted',
328
+ tokenUsage: result.tokenUsage
329
+ };
330
+ await appendIteration(config.progressPath, requirements.tasks.length, iterationLog);
331
+ // Update session iteration count
332
+ if (config.featureName) {
333
+ await updateFeatureSessionIteration(config.workspacePath, config.featureName, i);
334
+ }
335
+ else {
336
+ await updateSessionIteration(config.workspacePath, i);
337
+ }
338
+ // Commit the interrupted state (if any changes were made)
339
+ await commitIteration(config.workspacePath, i, null, // No task completed
340
+ null, false, // Not successful
341
+ config.verbose, config.featureName);
342
+ console.log(chalk.yellow('\nStopping as requested. Task was NOT marked as complete.'));
343
+ console.log(chalk.gray('Run "devloop continue" to resume and retry this task.'));
344
+ interruptedDuringTask = true;
345
+ break;
346
+ }
347
+ // Update token tracking (both session and project)
348
+ if (result.tokenUsage) {
349
+ sessionTokens.input += result.tokenUsage.inputTokens;
350
+ sessionTokens.output += result.tokenUsage.outputTokens;
351
+ sessionTokens.cacheWrite += result.tokenUsage.cacheCreationTokens;
352
+ sessionTokens.cacheRead += result.tokenUsage.cacheReadTokens;
353
+ sessionTokens.total += result.tokenUsage.totalTokens;
354
+ sessionCost += result.tokenUsage.costUsd;
355
+ projectTokens.input += result.tokenUsage.inputTokens;
356
+ projectTokens.output += result.tokenUsage.outputTokens;
357
+ projectTokens.cacheWrite += result.tokenUsage.cacheCreationTokens;
358
+ projectTokens.cacheRead += result.tokenUsage.cacheReadTokens;
359
+ projectTokens.total += result.tokenUsage.totalTokens;
360
+ projectCost += result.tokenUsage.costUsd;
361
+ }
362
+ const duration = `${Math.round(result.duration / 1000)}s`;
363
+ // Record iteration with error details and token usage
364
+ const iterationLog = {
365
+ iteration: i,
366
+ timestamp: iterationStart.toISOString(),
367
+ taskCompleted: result.success ? nextTask.id : null,
368
+ summary: result.success
369
+ ? `Completed ${nextTask.title}`
370
+ : `Failed: ${result.error?.split('\n')[0] || 'Unknown error'}`,
371
+ duration,
372
+ exitStatus: result.success ? 'success' : 'error',
373
+ errorType: result.success ? undefined : result.errorType,
374
+ errorDetail: result.success ? undefined : result.error,
375
+ tokenUsage: result.tokenUsage
376
+ };
377
+ // Update progress file
378
+ await appendIteration(config.progressPath, requirements.tasks.length, iterationLog);
379
+ // Update session (feature or legacy)
380
+ if (config.featureName) {
381
+ await updateFeatureSessionIteration(config.workspacePath, config.featureName, i);
382
+ }
383
+ else {
384
+ await updateSessionIteration(config.workspacePath, i);
385
+ }
386
+ if (result.success) {
387
+ const tokenInfo = result.tokenUsage
388
+ ? ` [${result.tokenUsage.totalTokens.toLocaleString()} tokens]`
389
+ : '';
390
+ if (config.verbose) {
391
+ console.log(chalk.green(` ✓ Completed ${nextTask.id} (${duration})${tokenInfo}`));
392
+ }
393
+ else {
394
+ spinner.succeed(chalk.green(` Completed ${nextTask.id} (${duration})${tokenInfo}`));
395
+ }
396
+ // Show detailed token usage breakdown
397
+ if (result.tokenUsage) {
398
+ const t = result.tokenUsage;
399
+ console.log(chalk.gray(` This iteration: ${t.totalTokens.toLocaleString()} tokens ($${t.costUsd.toFixed(4)}, ~$${pricePerMillion(t.costUsd, t.totalTokens)}/M)`));
400
+ console.log(chalk.gray(` In: ${t.inputTokens.toLocaleString()} | Out: ${t.outputTokens.toLocaleString()} | Cache +${t.cacheCreationTokens.toLocaleString()}/-${t.cacheReadTokens.toLocaleString()}`));
401
+ console.log(chalk.gray(` Session: ${sessionTokens.total.toLocaleString()} tokens ($${sessionCost.toFixed(4)}, ~$${pricePerMillion(sessionCost, sessionTokens.total)}/M)`));
402
+ console.log(chalk.gray(` Project: ${projectTokens.total.toLocaleString()} tokens ($${projectCost.toFixed(4)}, ~$${pricePerMillion(projectCost, projectTokens.total)}/M)`));
403
+ }
404
+ }
405
+ else {
406
+ if (config.verbose) {
407
+ console.log(chalk.red(` ✗ Failed ${nextTask.id} - ${result.error}`));
408
+ }
409
+ else {
410
+ spinner.fail(chalk.red(` Failed ${nextTask.id} - ${result.error}`));
411
+ }
412
+ // Check if this is an API error (not a task failure)
413
+ if (isApiError(result.errorType)) {
414
+ console.log(chalk.red.bold('\n⚠ API Error Detected - Stopping DevLoop\n'));
415
+ console.log(chalk.red(` Error Type: ${result.errorType}`));
416
+ console.log(chalk.red(` Details: ${result.error}`));
417
+ console.log(chalk.yellow('\n This is an API-level error, not a task failure.'));
418
+ console.log(chalk.yellow(' Please resolve the issue before continuing.\n'));
419
+ break;
420
+ }
421
+ // Task failure - continue to next iteration (future attempt may succeed)
422
+ console.log(chalk.yellow(' Continuing to next task...'));
423
+ }
424
+ // Commit iteration changes to git (if available)
425
+ const commitResult = await commitIteration(config.workspacePath, i, result.success ? nextTask.id : null, result.success ? nextTask.title : null, result.success, config.verbose, config.featureName);
426
+ // Stop loop if commit failed due to a hook
427
+ if (commitResult.hookFailure) {
428
+ console.log(chalk.yellow('\nStopping DevLoop due to commit hook failure.'));
429
+ console.log(chalk.gray('Fix the commit message format and run "devloop run" again.'));
430
+ break;
431
+ }
432
+ // Small delay between iterations to avoid rate limiting
433
+ await sleep(1000);
434
+ }
435
+ // Clean up signal handler
436
+ cleanupShutdownHandler();
437
+ // Final summary
438
+ console.log(chalk.blue.bold('\n=== DevLoop Complete ===\n'));
439
+ const finalProgress = await readProgress(config.progressPath);
440
+ if (finalProgress) {
441
+ const successCount = finalProgress.iterations.filter(i => i.exitStatus === 'success').length;
442
+ console.log(chalk.gray(`Total iterations: ${finalProgress.iterations.length}`));
443
+ console.log(chalk.green(`Successful: ${successCount}`));
444
+ console.log(chalk.red(`Failed: ${finalProgress.iterations.length - successCount}`));
445
+ console.log(chalk.gray(`Tasks completed: ${finalProgress.completed}/${finalProgress.totalTasks}`));
446
+ // Set final terminal title
447
+ if (stopRequested) {
448
+ setTerminalTitle(`DevLoop: Stopped (${finalProgress.completed}/${finalProgress.totalTasks} tasks)`);
449
+ }
450
+ else if (finalProgress.completed === finalProgress.totalTasks) {
451
+ setTerminalTitle(`DevLoop: Complete! (${finalProgress.totalTasks} tasks)`);
452
+ }
453
+ else {
454
+ setTerminalTitle(`DevLoop: Done (${finalProgress.completed}/${finalProgress.totalTasks} tasks)`);
455
+ }
456
+ }
457
+ else {
458
+ setTerminalTitle('DevLoop: Complete');
459
+ }
460
+ if (stopRequested && !interruptedDuringTask) {
461
+ // Only show generic message if we stopped between tasks, not mid-task
462
+ // (mid-task interruption already printed detailed messaging)
463
+ console.log(chalk.yellow('\nRun was stopped by user. Use "devloop continue" to resume.'));
464
+ }
465
+ }
466
+ function sleep(ms) {
467
+ return new Promise(resolve => setTimeout(resolve, ms));
468
+ }
469
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/core/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Session, SessionPhase } from '../types/index.js';
2
+ export declare function readSession(workspace: string): Promise<Session | null>;
3
+ export declare function writeSession(workspace: string, session: Session): Promise<void>;
4
+ export declare function createSession(workspace: string, phase: SessionPhase): Promise<Session>;
5
+ export declare function updateSessionPhase(workspace: string, phase: SessionPhase): Promise<void>;
6
+ export declare function updateSessionIteration(workspace: string, iteration: number): Promise<void>;
7
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAkB1D,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAQ5E;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrF;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAS5F;AAED,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9F;AAED,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMhG"}
@@ -0,0 +1,57 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ const DEFAULT_SESSION = {
4
+ phase: 'init',
5
+ sessionId: null,
6
+ lastIteration: 0,
7
+ startedAt: new Date().toISOString()
8
+ };
9
+ async function ensureSessionDir(workspace) {
10
+ const sessionDir = path.join(workspace, '.devloop');
11
+ try {
12
+ await fs.mkdir(sessionDir, { recursive: true });
13
+ }
14
+ catch {
15
+ // Directory already exists
16
+ }
17
+ }
18
+ export async function readSession(workspace) {
19
+ const sessionPath = path.join(workspace, '.devloop', 'session.json');
20
+ try {
21
+ const content = await fs.readFile(sessionPath, 'utf-8');
22
+ return JSON.parse(content);
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ export async function writeSession(workspace, session) {
29
+ await ensureSessionDir(workspace);
30
+ const sessionPath = path.join(workspace, '.devloop', 'session.json');
31
+ await fs.writeFile(sessionPath, JSON.stringify(session, null, 2), 'utf-8');
32
+ }
33
+ export async function createSession(workspace, phase) {
34
+ const session = {
35
+ phase,
36
+ sessionId: null,
37
+ lastIteration: 0,
38
+ startedAt: new Date().toISOString()
39
+ };
40
+ await writeSession(workspace, session);
41
+ return session;
42
+ }
43
+ export async function updateSessionPhase(workspace, phase) {
44
+ const session = await readSession(workspace);
45
+ if (session) {
46
+ session.phase = phase;
47
+ await writeSession(workspace, session);
48
+ }
49
+ }
50
+ export async function updateSessionIteration(workspace, iteration) {
51
+ const session = await readSession(workspace);
52
+ if (session) {
53
+ session.lastIteration = iteration;
54
+ await writeSession(workspace, session);
55
+ }
56
+ }
57
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/core/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,MAAM,eAAe,GAAY;IAC/B,KAAK,EAAE,MAAM;IACb,SAAS,EAAE,IAAI;IACf,aAAa,EAAE,CAAC;IAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;CACpC,CAAC;AAEF,KAAK,UAAU,gBAAgB,CAAC,SAAiB;IAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,SAAiB;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB,EAAE,OAAgB;IACpE,MAAM,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;IACrE,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB,EAAE,KAAmB;IACxE,MAAM,OAAO,GAAY;QACvB,KAAK;QACL,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,CAAC;QAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,MAAM,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,SAAiB,EAAE,KAAmB;IAC7E,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;QACtB,MAAM,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,SAAiB,EAAE,SAAiB;IAC/E,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;QAClC,MAAM,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { program } from './cli.js';
3
+ program.parse(process.argv);
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Progress, IterationLog } from '../types/index.js';
2
+ export declare function readProgress(filePath: string): Promise<Progress | null>;
3
+ export declare function parseProgressContent(content: string): Progress;
4
+ export declare function generateProgressContent(totalTasks: number, completedCount: number, iterations: IterationLog[]): string;
5
+ export declare function writeProgress(filePath: string, progress: Progress): Promise<void>;
6
+ export declare function appendIteration(filePath: string, totalTasks: number, iteration: IterationLog): Promise<void>;
7
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/parser/progress.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAA2C,MAAM,mBAAmB,CAAC;AAEpG,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAO7E;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CA4D9D;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,YAAY,EAAE,GACzB,MAAM,CA6CR;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CASvF;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,IAAI,CAAC,CAqBf"}