claude-autopm 1.18.0 → 1.20.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 (75) hide show
  1. package/README.md +159 -0
  2. package/autopm/.claude/agents/core/mcp-manager.md +1 -1
  3. package/autopm/.claude/commands/pm/context.md +11 -0
  4. package/autopm/.claude/commands/pm/epic-decompose.md +25 -2
  5. package/autopm/.claude/commands/pm/epic-oneshot.md +13 -0
  6. package/autopm/.claude/commands/pm/epic-start.md +19 -0
  7. package/autopm/.claude/commands/pm/epic-sync-modular.md +10 -10
  8. package/autopm/.claude/commands/pm/epic-sync.md +14 -14
  9. package/autopm/.claude/commands/pm/issue-start.md +50 -5
  10. package/autopm/.claude/commands/pm/issue-sync.md +15 -15
  11. package/autopm/.claude/commands/pm/what-next.md +11 -0
  12. package/autopm/.claude/mcp/MCP-REGISTRY.md +1 -1
  13. package/autopm/.claude/scripts/azure/active-work.js +2 -2
  14. package/autopm/.claude/scripts/azure/blocked.js +13 -13
  15. package/autopm/.claude/scripts/azure/daily.js +1 -1
  16. package/autopm/.claude/scripts/azure/dashboard.js +1 -1
  17. package/autopm/.claude/scripts/azure/feature-list.js +2 -2
  18. package/autopm/.claude/scripts/azure/feature-status.js +1 -1
  19. package/autopm/.claude/scripts/azure/next-task.js +1 -1
  20. package/autopm/.claude/scripts/azure/search.js +1 -1
  21. package/autopm/.claude/scripts/azure/setup.js +15 -15
  22. package/autopm/.claude/scripts/azure/sprint-report.js +2 -2
  23. package/autopm/.claude/scripts/azure/sync.js +1 -1
  24. package/autopm/.claude/scripts/azure/us-list.js +1 -1
  25. package/autopm/.claude/scripts/azure/us-status.js +1 -1
  26. package/autopm/.claude/scripts/azure/validate.js +13 -13
  27. package/autopm/.claude/scripts/lib/frontmatter-utils.sh +42 -7
  28. package/autopm/.claude/scripts/lib/logging-utils.sh +20 -16
  29. package/autopm/.claude/scripts/lib/validation-utils.sh +1 -1
  30. package/autopm/.claude/scripts/pm/context.js +338 -0
  31. package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +3 -3
  32. package/autopm/.claude/scripts/pm/lib/README.md +85 -0
  33. package/autopm/.claude/scripts/pm/lib/logger.js +78 -0
  34. package/autopm/.claude/scripts/pm/next.js +25 -1
  35. package/autopm/.claude/scripts/pm/what-next.js +660 -0
  36. package/bin/autopm.js +25 -0
  37. package/package.json +1 -1
  38. package/lib/agentExecutor.js.deprecated +0 -101
  39. package/lib/azure/cache.js +0 -80
  40. package/lib/azure/client.js +0 -77
  41. package/lib/azure/formatter.js +0 -177
  42. package/lib/commandHelpers.js +0 -177
  43. package/lib/context/manager.js +0 -290
  44. package/lib/documentation/manager.js +0 -528
  45. package/lib/github/workflow-manager.js +0 -546
  46. package/lib/helpers/azure-batch-api.js +0 -133
  47. package/lib/helpers/azure-cache-manager.js +0 -287
  48. package/lib/helpers/azure-parallel-processor.js +0 -158
  49. package/lib/helpers/azure-work-item-create.js +0 -278
  50. package/lib/helpers/gh-issue-create.js +0 -250
  51. package/lib/helpers/interactive-prompt.js +0 -336
  52. package/lib/helpers/output-manager.js +0 -335
  53. package/lib/helpers/progress-indicator.js +0 -258
  54. package/lib/performance/benchmarker.js +0 -429
  55. package/lib/pm/epic-decomposer.js +0 -273
  56. package/lib/pm/epic-syncer.js +0 -221
  57. package/lib/prdMetadata.js +0 -270
  58. package/lib/providers/azure/index.js +0 -234
  59. package/lib/providers/factory.js +0 -87
  60. package/lib/providers/github/index.js +0 -204
  61. package/lib/providers/interface.js +0 -73
  62. package/lib/python/scaffold-manager.js +0 -576
  63. package/lib/react/scaffold-manager.js +0 -745
  64. package/lib/regression/analyzer.js +0 -578
  65. package/lib/release/manager.js +0 -324
  66. package/lib/tailwind/manager.js +0 -486
  67. package/lib/traefik/manager.js +0 -484
  68. package/lib/utils/colors.js +0 -126
  69. package/lib/utils/config.js +0 -317
  70. package/lib/utils/filesystem.js +0 -316
  71. package/lib/utils/logger.js +0 -135
  72. package/lib/utils/prompts.js +0 -294
  73. package/lib/utils/shell.js +0 -237
  74. package/lib/validators/email-validator.js +0 -337
  75. package/lib/workflow/manager.js +0 -449
@@ -0,0 +1,338 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { logError } = require('./lib/logger');
4
+
5
+ /**
6
+ * PM Context Script
7
+ * Displays current project context, configuration, and progress
8
+ */
9
+
10
+ // Constants
11
+ const TASK_FILE_PATTERN = /^\d{3}\.md$/;
12
+
13
+ async function context() {
14
+ console.log('');
15
+ console.log('🎯 Project Context');
16
+ console.log('='.repeat(60));
17
+ console.log('');
18
+
19
+ // Project Information
20
+ console.log('📦 Project Information:');
21
+
22
+ // Get project name from package.json or directory name
23
+ let projectName = path.basename(process.cwd());
24
+ try {
25
+ if (fs.existsSync('package.json')) {
26
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
27
+ if (pkg.name) {
28
+ projectName = pkg.name;
29
+ }
30
+ }
31
+ } catch (err) {
32
+ // Use directory name as fallback
33
+ }
34
+ console.log(` Name: ${projectName}`);
35
+ console.log(` Directory: ${process.cwd()}`);
36
+ console.log('');
37
+
38
+ // Configuration
39
+ console.log('⚙️ Configuration:');
40
+ let provider = 'Not configured';
41
+ let githubOwner = '-';
42
+ let githubRepo = '-';
43
+ let azureOrg = '-';
44
+ let azureProject = '-';
45
+
46
+ try {
47
+ if (fs.existsSync('.claude/config.json')) {
48
+ const config = JSON.parse(fs.readFileSync('.claude/config.json', 'utf8'));
49
+ if (config.provider) {
50
+ provider = config.provider.charAt(0).toUpperCase() + config.provider.slice(1);
51
+ }
52
+ if (config.github) {
53
+ githubOwner = config.github.owner || '-';
54
+ githubRepo = config.github.repo || '-';
55
+ }
56
+ if (config.azure) {
57
+ azureOrg = config.azure.organization || '-';
58
+ azureProject = config.azure.project || '-';
59
+ }
60
+ }
61
+ } catch (err) {
62
+ // Config not found
63
+ }
64
+
65
+ console.log(` Provider: ${provider}`);
66
+ if (provider.toLowerCase() === 'github') {
67
+ console.log(` GitHub Owner: ${githubOwner}`);
68
+ console.log(` GitHub Repo: ${githubRepo}`);
69
+ } else if (provider.toLowerCase() === 'azure') {
70
+ console.log(` Azure Org: ${azureOrg}`);
71
+ console.log(` Azure Project: ${azureProject}`);
72
+ }
73
+ console.log('');
74
+
75
+ // Active Team
76
+ console.log('👥 Active Team:');
77
+ let activeTeam = 'Default';
78
+ try {
79
+ if (fs.existsSync('.claude/active_team.txt')) {
80
+ activeTeam = fs.readFileSync('.claude/active_team.txt', 'utf8').trim();
81
+ }
82
+ } catch (err) {
83
+ // No active team
84
+ }
85
+ console.log(` Team: ${activeTeam}`);
86
+ console.log('');
87
+
88
+ // PRDs
89
+ console.log('📄 Product Requirements (PRDs):');
90
+ let prdCount = 0;
91
+ let prdNames = [];
92
+ try {
93
+ if (fs.existsSync('.claude/prds')) {
94
+ const files = fs.readdirSync('.claude/prds')
95
+ .filter(f => f.endsWith('.md') && !f.startsWith('.'));
96
+ prdCount = files.length;
97
+ prdNames = files.map(f => f.replace('.md', ''));
98
+ }
99
+ } catch (err) {
100
+ // No PRDs
101
+ }
102
+
103
+ console.log(` Total: ${prdCount}`);
104
+ if (prdCount > 0) {
105
+ prdNames.slice(0, 5).forEach(name => {
106
+ console.log(` • ${name}`);
107
+ });
108
+ if (prdCount > 5) {
109
+ console.log(` ... and ${prdCount - 5} more`);
110
+ }
111
+ }
112
+ console.log('');
113
+
114
+ // Epics with Progress
115
+ console.log('📚 Epics & Progress:');
116
+ let epicCount = 0;
117
+ let totalTasks = 0;
118
+ let completedTasks = 0;
119
+ let inProgressTasks = 0;
120
+ let pendingTasks = 0;
121
+ let epicDetails = [];
122
+
123
+ try {
124
+ if (fs.existsSync('.claude/epics')) {
125
+ const epicDirs = fs.readdirSync('.claude/epics', { withFileTypes: true })
126
+ .filter(d => d.isDirectory())
127
+ .map(d => d.name);
128
+
129
+ epicCount = epicDirs.length;
130
+
131
+ // Helper to count tasks in a directory and update counters
132
+ function countTasksInDir(dir, counters) {
133
+ try {
134
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
135
+ for (const entry of entries) {
136
+ const fullPath = path.join(dir, entry.name);
137
+ if (entry.isDirectory()) {
138
+ countTasksInDir(fullPath, counters);
139
+ } else if (entry.isFile() && TASK_FILE_PATTERN.test(entry.name)) {
140
+ counters.epicTasks++;
141
+ totalTasks++;
142
+ try {
143
+ const content = fs.readFileSync(fullPath, 'utf8');
144
+ const statusMatch = content.match(/^status:\s*(.+)$/m);
145
+ if (statusMatch) {
146
+ const status = statusMatch[1].trim().toLowerCase();
147
+ if (status === 'completed' || status === 'done' || status === 'closed') {
148
+ counters.epicCompleted++;
149
+ completedTasks++;
150
+ } else if (status === 'in-progress' || status === 'in_progress') {
151
+ counters.epicInProgress++;
152
+ inProgressTasks++;
153
+ } else {
154
+ counters.epicPending++;
155
+ pendingTasks++;
156
+ }
157
+ } else {
158
+ counters.epicPending++;
159
+ pendingTasks++;
160
+ }
161
+ } catch (err) {
162
+ counters.epicPending++;
163
+ pendingTasks++;
164
+ }
165
+ }
166
+ }
167
+ } catch (err) {
168
+ // Directory read error
169
+ }
170
+ }
171
+
172
+ for (const epicDir of epicDirs) {
173
+ const epicPath = path.join('.claude/epics', epicDir);
174
+ // Count tasks in this epic (including subdirectories)
175
+ let counters = {
176
+ epicTasks: 0,
177
+ epicCompleted: 0,
178
+ epicInProgress: 0,
179
+ epicPending: 0
180
+ };
181
+ countTasksInDir(epicPath, counters);
182
+ if (counters.epicTasks > 0) {
183
+ const progress = Math.round((counters.epicCompleted / counters.epicTasks) * 100);
184
+ epicDetails.push({
185
+ name: epicDir,
186
+ tasks: counters.epicTasks,
187
+ completed: counters.epicCompleted,
188
+ inProgress: counters.epicInProgress,
189
+ pending: counters.epicPending,
190
+ progress: progress
191
+ });
192
+ }
193
+ }
194
+ }
195
+ } catch (err) {
196
+ // No epics
197
+ }
198
+
199
+ console.log(` Total Epics: ${epicCount}`);
200
+ console.log(` Total Tasks: ${totalTasks}`);
201
+ console.log(` Completed: ${completedTasks}`);
202
+ console.log(` In Progress: ${inProgressTasks}`);
203
+ console.log(` Pending: ${pendingTasks}`);
204
+ console.log('');
205
+
206
+ if (epicDetails.length > 0) {
207
+ console.log(' Epic Breakdown:');
208
+ epicDetails.slice(0, 5).forEach(epic => {
209
+ const progressBar = createProgressBar(epic.progress, 20);
210
+ console.log(` ${epic.name}`);
211
+ console.log(` ${progressBar} ${epic.progress}% (${epic.completed}/${epic.tasks} tasks)`);
212
+ });
213
+ if (epicDetails.length > 5) {
214
+ console.log(` ... and ${epicDetails.length - 5} more epics`);
215
+ }
216
+ console.log('');
217
+ }
218
+
219
+ // Overall Progress
220
+ if (totalTasks > 0) {
221
+ const overallProgress = Math.round((completedTasks / totalTasks) * 100);
222
+ console.log('📊 Overall Progress:');
223
+ const overallBar = createProgressBar(overallProgress, 40);
224
+ console.log(` ${overallBar} ${overallProgress}%`);
225
+ console.log(` ${completedTasks} / ${totalTasks} tasks completed`);
226
+ console.log('');
227
+ }
228
+
229
+ // Current/Recent Activity
230
+ console.log('🔄 Recent Activity:');
231
+ try {
232
+ // Find most recently modified task file
233
+ let recentTask = null;
234
+ let recentTime = 0;
235
+
236
+ if (fs.existsSync('.claude/epics')) {
237
+ function findRecentTask(dir) {
238
+ let bestTask = null;
239
+ let bestTime = 0;
240
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
241
+
242
+ for (const entry of entries) {
243
+ const fullPath = path.join(dir, entry.name);
244
+
245
+ if (entry.isDirectory()) {
246
+ const subTask = findRecentTask(fullPath);
247
+ if (subTask && subTask.timeMs > bestTime) {
248
+ bestTask = subTask;
249
+ bestTime = subTask.timeMs;
250
+ }
251
+ } else if (entry.isFile() && TASK_FILE_PATTERN.test(entry.name)) {
252
+ const stats = fs.statSync(fullPath);
253
+ if (stats.mtimeMs > bestTime) {
254
+ const content = fs.readFileSync(fullPath, 'utf8');
255
+ const titleMatch = content.match(/^#\s+(.+)$/m);
256
+ const statusMatch = content.match(/^status:\s*(.+)$/m);
257
+ bestTask = {
258
+ path: fullPath,
259
+ title: titleMatch ? titleMatch[1] : entry.name,
260
+ status: statusMatch ? statusMatch[1].trim() : 'pending',
261
+ time: stats.mtime,
262
+ timeMs: stats.mtimeMs
263
+ };
264
+ bestTime = stats.mtimeMs;
265
+ }
266
+ }
267
+ }
268
+ return bestTask;
269
+ }
270
+
271
+ const foundTask = findRecentTask('.claude/epics');
272
+ if (foundTask) {
273
+ recentTask = foundTask;
274
+ recentTime = foundTask.timeMs;
275
+ }
276
+ }
277
+
278
+ if (recentTask) {
279
+ const timeAgo = getTimeAgo(recentTask.time);
280
+ console.log(` Last Modified: ${recentTask.title}`);
281
+ console.log(` Status: ${recentTask.status}`);
282
+ console.log(` Modified: ${timeAgo}`);
283
+ console.log(` File: ${recentTask.path}`);
284
+ } else {
285
+ console.log(' No recent activity');
286
+ }
287
+ } catch (err) {
288
+ console.log(' No recent activity');
289
+ }
290
+
291
+ console.log('');
292
+ console.log('💡 Quick Commands:');
293
+ console.log(' /pm:next # Get next priority task');
294
+ console.log(' /pm:status # Detailed project status');
295
+ console.log(' /pm:standup # Generate standup report');
296
+ console.log(' /pm:search <keyword> # Search PRDs and epics');
297
+ console.log('');
298
+ }
299
+
300
+ // Helper function to create progress bar
301
+ function createProgressBar(percentage, length) {
302
+ const filled = Math.round((percentage / 100) * length);
303
+ const empty = length - filled;
304
+ return '[' + '='.repeat(filled) + '-'.repeat(empty) + ']';
305
+ }
306
+
307
+ // Helper function to get human-readable time ago
308
+ function getTimeAgo(date) {
309
+ const seconds = Math.floor((new Date() - date) / 1000);
310
+
311
+ const intervals = {
312
+ year: 31536000,
313
+ month: 2592000,
314
+ week: 604800,
315
+ day: 86400,
316
+ hour: 3600,
317
+ minute: 60
318
+ };
319
+
320
+ for (const [name, secondsInInterval] of Object.entries(intervals)) {
321
+ const interval = Math.floor(seconds / secondsInInterval);
322
+ if (interval >= 1) {
323
+ return `${interval} ${name}${interval > 1 ? 's' : ''} ago`;
324
+ }
325
+ }
326
+
327
+ return 'just now';
328
+ }
329
+
330
+ // Run if called directly
331
+ if (require.main === module) {
332
+ context().catch(err => {
333
+ logError('Error executing context command', err);
334
+ process.exit(1);
335
+ });
336
+ }
337
+
338
+ module.exports = context;
@@ -6,9 +6,9 @@ set -euo pipefail
6
6
 
7
7
  # Load libraries
8
8
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
- source "${SCRIPT_DIR}/../../lib/logging-utils.sh"
10
- source "${SCRIPT_DIR}/../../lib/frontmatter-utils.sh"
11
- source "${SCRIPT_DIR}/../../lib/datetime-utils.sh"
9
+ source "${SCRIPT_DIR}/../lib/logging-utils.sh"
10
+ source "${SCRIPT_DIR}/../lib/frontmatter-utils.sh"
11
+ source "${SCRIPT_DIR}/../lib/datetime-utils.sh"
12
12
 
13
13
  # Script configuration
14
14
  readonly ISSUE_NUMBER="${1:-}"
@@ -0,0 +1,85 @@
1
+ # PM Scripts Library
2
+
3
+ This directory contains shared utilities for PM command scripts.
4
+
5
+ ## Logger
6
+
7
+ The `logger.js` module provides consistent, colored logging across all PM commands.
8
+
9
+ ### Usage
10
+
11
+ ```javascript
12
+ const { logInfo, logSuccess, logWarning, logError, logDebug } = require('./lib/logger');
13
+
14
+ // Info message (blue ℹ icon)
15
+ logInfo('Processing task...');
16
+
17
+ // Success message (green ✓ icon)
18
+ logSuccess('Task completed successfully');
19
+
20
+ // Warning message (yellow ⚠ icon)
21
+ logWarning('Task may require attention');
22
+
23
+ // Error message (red ❌ icon)
24
+ logError('Failed to process task', error);
25
+ // The error parameter is optional and will display error.message and stack (if DEBUG=1)
26
+
27
+ // Debug message (only shown if DEBUG=1)
28
+ logDebug('Detailed debug information');
29
+ ```
30
+
31
+ ### Environment Variables
32
+
33
+ - `DEBUG=1` - Enable debug logging and full error stack traces
34
+
35
+ ### Color Constants
36
+
37
+ If you need custom formatting, you can import the colors:
38
+
39
+ ```javascript
40
+ const { colors } = require('./lib/logger');
41
+
42
+ console.log(`${colors.blue}Custom message${colors.reset}`);
43
+ ```
44
+
45
+ Available colors:
46
+ - `colors.red`
47
+ - `colors.green`
48
+ - `colors.yellow`
49
+ - `colors.blue`
50
+ - `colors.cyan`
51
+ - `colors.gray`
52
+ - `colors.reset`
53
+
54
+ ## Migration Guide
55
+
56
+ To migrate existing PM scripts to use the logger:
57
+
58
+ 1. Import the logger at the top of your file:
59
+ ```javascript
60
+ const { logError, logWarning, logInfo, logSuccess } = require('./lib/logger');
61
+ ```
62
+
63
+ 2. Replace `console.error()` calls:
64
+ ```javascript
65
+ // Before
66
+ console.error('Error:', err.message);
67
+
68
+ // After
69
+ logError('Error description', err);
70
+ ```
71
+
72
+ 3. Add error handling to promise chains:
73
+ ```javascript
74
+ // Before
75
+ const results = await Promise.all(promises);
76
+
77
+ // After
78
+ const promises = items.map(item =>
79
+ processItem(item).catch(err => {
80
+ logWarning(`Failed to process ${item.name}`, err);
81
+ return defaultValue;
82
+ })
83
+ );
84
+ const results = await Promise.all(promises);
85
+ ```
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Logging utility for PM scripts
3
+ * Provides consistent colored output across all PM commands
4
+ */
5
+
6
+ // ANSI color codes
7
+ const colors = {
8
+ reset: '\x1b[0m',
9
+ red: '\x1b[31m',
10
+ green: '\x1b[32m',
11
+ yellow: '\x1b[33m',
12
+ blue: '\x1b[34m',
13
+ gray: '\x1b[90m',
14
+ cyan: '\x1b[36m'
15
+ };
16
+
17
+ /**
18
+ * Log an info message
19
+ * @param {string} message - The message to log
20
+ */
21
+ function logInfo(message) {
22
+ console.log(`${colors.blue}ℹ${colors.reset} ${message}`);
23
+ }
24
+
25
+ /**
26
+ * Log a success message
27
+ * @param {string} message - The message to log
28
+ */
29
+ function logSuccess(message) {
30
+ console.log(`${colors.green}✓${colors.reset} ${message}`);
31
+ }
32
+
33
+ /**
34
+ * Log a warning message
35
+ * @param {string} message - The message to log
36
+ */
37
+ function logWarning(message) {
38
+ console.warn(`${colors.yellow}⚠${colors.reset} ${message}`);
39
+ }
40
+
41
+ /**
42
+ * Log an error message
43
+ * @param {string} message - The message to log
44
+ * @param {Error} [error] - Optional error object for details
45
+ */
46
+ function logError(message, error) {
47
+ console.error(`${colors.red}❌${colors.reset} ${message}`);
48
+ if (error && error.message) {
49
+ console.error(`${colors.gray} ${error.message}${colors.reset}`);
50
+ }
51
+ if (error && error.stack && process.env.DEBUG) {
52
+ console.error(`${colors.gray}${error.stack}${colors.reset}`);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Log a debug message (only shown if DEBUG env var is set)
58
+ * @param {string} message - The message to log
59
+ */
60
+ function logDebug(message) {
61
+ if (process.env.DEBUG) {
62
+ console.log(`${colors.gray}[DEBUG]${colors.reset} ${message}`);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Export colors for custom formatting
68
+ */
69
+ const logColors = colors;
70
+
71
+ module.exports = {
72
+ logInfo,
73
+ logSuccess,
74
+ logWarning,
75
+ logError,
76
+ logDebug,
77
+ colors: logColors
78
+ };
@@ -1,5 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
+ const { logError } = require('./lib/logger');
3
4
 
4
5
  /**
5
6
  * PM Next Script (Node.js version)
@@ -73,11 +74,34 @@ async function next() {
73
74
  }
74
75
 
75
76
  addMessage('');
77
+
78
+ // Display TDD reminder if tasks are available
79
+ if (result.found > 0) {
80
+ displayTddReminder(addMessage);
81
+ }
82
+
76
83
  addMessage(`📊 Summary: ${result.found} tasks ready to start`);
77
84
 
78
85
  return result;
79
86
  }
80
87
 
88
+ /**
89
+ * Display TDD reminder to ensure test-driven development practices
90
+ * Extracted to maintain single responsibility and improve testability
91
+ * @param {Function} addMessage - Function to add messages to the output
92
+ */
93
+ function displayTddReminder(addMessage) {
94
+ addMessage('⚠️ TDD REMINDER - Before starting work:');
95
+ addMessage('');
96
+ addMessage(' 🚨 ALWAYS follow Test-Driven Development:');
97
+ addMessage(' 1. RED: Write failing test first');
98
+ addMessage(' 2. GREEN: Write minimal code to pass');
99
+ addMessage(' 3. REFACTOR: Clean up while keeping tests green');
100
+ addMessage('');
101
+ addMessage(' See .claude/rules/tdd.enforcement.md for details');
102
+ addMessage('');
103
+ }
104
+
81
105
  // Helper function to find available tasks
82
106
  async function findAvailableTasks() {
83
107
  const availableTasks = [];
@@ -161,7 +185,7 @@ if (require.main === module) {
161
185
  module.exports.next().then(() => {
162
186
  process.exit(0);
163
187
  }).catch(err => {
164
- console.error('Next tasks failed:', err.message);
188
+ logError('Next tasks command failed', err);
165
189
  process.exit(1);
166
190
  });
167
191
  }