specweave 0.24.6 → 0.24.8

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 (147) hide show
  1. package/CLAUDE.md +64 -0
  2. package/README.md +34 -0
  3. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts +5 -2
  4. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
  5. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +72 -6
  6. package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
  7. package/dist/src/cli/helpers/issue-tracker/github.d.ts +2 -1
  8. package/dist/src/cli/helpers/issue-tracker/github.d.ts.map +1 -1
  9. package/dist/src/cli/helpers/issue-tracker/github.js +4 -3
  10. package/dist/src/cli/helpers/issue-tracker/github.js.map +1 -1
  11. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  12. package/dist/src/cli/helpers/issue-tracker/index.js +26 -9
  13. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  14. package/dist/src/cli/helpers/issue-tracker/types.d.ts +1 -0
  15. package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
  16. package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
  17. package/dist/src/core/repo-structure/git-error-handler.d.ts +37 -0
  18. package/dist/src/core/repo-structure/git-error-handler.d.ts.map +1 -0
  19. package/dist/src/core/repo-structure/git-error-handler.js +214 -0
  20. package/dist/src/core/repo-structure/git-error-handler.js.map +1 -0
  21. package/dist/src/core/repo-structure/git-provider.d.ts +183 -0
  22. package/dist/src/core/repo-structure/git-provider.d.ts.map +1 -0
  23. package/dist/src/core/repo-structure/git-provider.js +57 -0
  24. package/dist/src/core/repo-structure/git-provider.js.map +1 -0
  25. package/dist/src/core/repo-structure/github-validator.d.ts +1 -0
  26. package/dist/src/core/repo-structure/github-validator.d.ts.map +1 -1
  27. package/dist/src/core/repo-structure/github-validator.js +35 -9
  28. package/dist/src/core/repo-structure/github-validator.js.map +1 -1
  29. package/dist/src/core/repo-structure/platform-registry.d.ts +114 -0
  30. package/dist/src/core/repo-structure/platform-registry.d.ts.map +1 -0
  31. package/dist/src/core/repo-structure/platform-registry.js +195 -0
  32. package/dist/src/core/repo-structure/platform-registry.js.map +1 -0
  33. package/dist/src/core/repo-structure/prompt-consolidator.d.ts +30 -0
  34. package/dist/src/core/repo-structure/prompt-consolidator.d.ts.map +1 -1
  35. package/dist/src/core/repo-structure/prompt-consolidator.js +69 -0
  36. package/dist/src/core/repo-structure/prompt-consolidator.js.map +1 -1
  37. package/dist/src/core/repo-structure/providers/bitbucket-provider.d.ts +54 -0
  38. package/dist/src/core/repo-structure/providers/bitbucket-provider.d.ts.map +1 -0
  39. package/dist/src/core/repo-structure/providers/bitbucket-provider.js +104 -0
  40. package/dist/src/core/repo-structure/providers/bitbucket-provider.js.map +1 -0
  41. package/dist/src/core/repo-structure/providers/github-provider.d.ts +53 -0
  42. package/dist/src/core/repo-structure/providers/github-provider.d.ts.map +1 -0
  43. package/dist/src/core/repo-structure/providers/github-provider.js +239 -0
  44. package/dist/src/core/repo-structure/providers/github-provider.js.map +1 -0
  45. package/dist/src/core/repo-structure/providers/gitlab-provider.d.ts +50 -0
  46. package/dist/src/core/repo-structure/providers/gitlab-provider.d.ts.map +1 -0
  47. package/dist/src/core/repo-structure/providers/gitlab-provider.js +97 -0
  48. package/dist/src/core/repo-structure/providers/gitlab-provider.js.map +1 -0
  49. package/dist/src/core/repo-structure/providers/index.d.ts +33 -0
  50. package/dist/src/core/repo-structure/providers/index.d.ts.map +1 -0
  51. package/dist/src/core/repo-structure/providers/index.js +60 -0
  52. package/dist/src/core/repo-structure/providers/index.js.map +1 -0
  53. package/dist/src/core/repo-structure/repo-structure-manager.d.ts +10 -3
  54. package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
  55. package/dist/src/core/repo-structure/repo-structure-manager.js +125 -42
  56. package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
  57. package/dist/src/core/repo-structure/url-generator.d.ts +80 -0
  58. package/dist/src/core/repo-structure/url-generator.d.ts.map +1 -0
  59. package/dist/src/core/repo-structure/url-generator.js +110 -0
  60. package/dist/src/core/repo-structure/url-generator.js.map +1 -0
  61. package/package.json +1 -1
  62. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
  63. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
  64. package/plugins/specweave/agents/pm/AGENT.md.bak +0 -1893
  65. package/plugins/specweave/hooks/docs-changed.sh.backup +0 -79
  66. package/plugins/specweave/hooks/human-input-required.sh.backup +0 -75
  67. package/plugins/specweave/hooks/lib/migrate-increment-work.sh.bak +0 -245
  68. package/plugins/specweave/hooks/lib/sync-spec-content.sh.bak +0 -149
  69. package/plugins/specweave/hooks/lib/validate-spec-status.sh.bak +0 -163
  70. package/plugins/specweave/hooks/post-first-increment.sh.backup +0 -61
  71. package/plugins/specweave/hooks/post-first-increment.sh.bak +0 -61
  72. package/plugins/specweave/hooks/post-increment-change.sh.backup +0 -98
  73. package/plugins/specweave/hooks/post-increment-completion.sh.backup +0 -231
  74. package/plugins/specweave/hooks/post-increment-planning.sh.backup +0 -1048
  75. package/plugins/specweave/hooks/post-increment-status-change.sh.backup +0 -147
  76. package/plugins/specweave/hooks/post-spec-update.sh.backup +0 -158
  77. package/plugins/specweave/hooks/post-spec-update.sh.bak +0 -158
  78. package/plugins/specweave/hooks/post-user-story-complete.sh.backup +0 -179
  79. package/plugins/specweave/hooks/post-user-story-complete.sh.bak +0 -179
  80. package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +0 -83
  81. package/plugins/specweave/hooks/pre-command-deduplication.sh.bak +0 -83
  82. package/plugins/specweave/hooks/pre-implementation.sh.backup +0 -67
  83. package/plugins/specweave/hooks/pre-task-completion.sh.backup +0 -194
  84. package/plugins/specweave/hooks/pre-tool-use.sh.backup +0 -133
  85. package/plugins/specweave/hooks/user-prompt-submit.sh.backup +0 -386
  86. package/plugins/specweave/hooks/user-prompt-submit.sh.bak +0 -386
  87. package/plugins/specweave/lib/hooks/auto-transition.js.bak +0 -50
  88. package/plugins/specweave/lib/hooks/auto-transition.ts.bak +0 -84
  89. package/plugins/specweave/lib/hooks/git-diff-analyzer.d.js.bak +0 -0
  90. package/plugins/specweave/lib/hooks/git-diff-analyzer.d.ts.bak +0 -89
  91. package/plugins/specweave/lib/hooks/git-diff-analyzer.js.bak +0 -142
  92. package/plugins/specweave/lib/hooks/git-diff-analyzer.ts.bak +0 -269
  93. package/plugins/specweave/lib/hooks/invoke-translator-skill.d.js.bak +0 -0
  94. package/plugins/specweave/lib/hooks/invoke-translator-skill.d.ts.bak +0 -60
  95. package/plugins/specweave/lib/hooks/invoke-translator-skill.js.bak +0 -155
  96. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts.bak +0 -264
  97. package/plugins/specweave/lib/hooks/prepare-reflection-context.d.js.bak +0 -0
  98. package/plugins/specweave/lib/hooks/prepare-reflection-context.d.ts.bak +0 -42
  99. package/plugins/specweave/lib/hooks/prepare-reflection-context.js.bak +0 -110
  100. package/plugins/specweave/lib/hooks/prepare-reflection-context.ts.bak +0 -178
  101. package/plugins/specweave/lib/hooks/reflection-config-loader.d.js.bak +0 -0
  102. package/plugins/specweave/lib/hooks/reflection-config-loader.d.ts.bak +0 -45
  103. package/plugins/specweave/lib/hooks/reflection-config-loader.js.bak +0 -92
  104. package/plugins/specweave/lib/hooks/reflection-config-loader.ts.bak +0 -156
  105. package/plugins/specweave/lib/hooks/reflection-parser.d.js.bak +0 -0
  106. package/plugins/specweave/lib/hooks/reflection-parser.d.ts.bak +0 -33
  107. package/plugins/specweave/lib/hooks/reflection-parser.js.bak +0 -301
  108. package/plugins/specweave/lib/hooks/reflection-parser.ts.bak +0 -484
  109. package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.js.bak +0 -0
  110. package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.ts.bak +0 -56
  111. package/plugins/specweave/lib/hooks/reflection-prompt-builder.js.bak +0 -182
  112. package/plugins/specweave/lib/hooks/reflection-prompt-builder.ts.bak +0 -306
  113. package/plugins/specweave/lib/hooks/reflection-storage.d.js.bak +0 -0
  114. package/plugins/specweave/lib/hooks/reflection-storage.d.ts.bak +0 -64
  115. package/plugins/specweave/lib/hooks/reflection-storage.js.bak +0 -231
  116. package/plugins/specweave/lib/hooks/reflection-storage.ts.bak +0 -369
  117. package/plugins/specweave/lib/hooks/run-self-reflection.d.js.bak +0 -0
  118. package/plugins/specweave/lib/hooks/run-self-reflection.d.ts.bak +0 -43
  119. package/plugins/specweave/lib/hooks/run-self-reflection.js.bak +0 -132
  120. package/plugins/specweave/lib/hooks/run-self-reflection.ts.bak +0 -258
  121. package/plugins/specweave/lib/hooks/sync-cache.js.bak +0 -294
  122. package/plugins/specweave/lib/hooks/sync-living-docs.d.js.bak +0 -1
  123. package/plugins/specweave/lib/hooks/sync-living-docs.d.ts.bak +0 -27
  124. package/plugins/specweave/lib/hooks/sync-living-docs.js.bak +0 -339
  125. package/plugins/specweave/lib/hooks/sync-us-tasks.js.bak +0 -476
  126. package/plugins/specweave/lib/hooks/translate-file.d.js.bak +0 -0
  127. package/plugins/specweave/lib/hooks/translate-file.d.ts.bak +0 -59
  128. package/plugins/specweave/lib/hooks/translate-file.js.bak +0 -289
  129. package/plugins/specweave/lib/hooks/translate-file.ts.bak +0 -428
  130. package/plugins/specweave/lib/hooks/translate-living-docs.d.js.bak +0 -0
  131. package/plugins/specweave/lib/hooks/translate-living-docs.d.ts.bak +0 -13
  132. package/plugins/specweave/lib/hooks/translate-living-docs.js.bak +0 -119
  133. package/plugins/specweave/lib/hooks/translate-living-docs.ts.bak +0 -224
  134. package/plugins/specweave/lib/hooks/update-ac-status.js.bak +0 -51
  135. package/plugins/specweave/lib/hooks/update-ac-status.ts.bak +0 -103
  136. package/plugins/specweave/lib/hooks/update-tasks-md.d.js.bak +0 -1
  137. package/plugins/specweave/lib/hooks/update-tasks-md.d.ts.bak +0 -29
  138. package/plugins/specweave/lib/hooks/update-tasks-md.js.bak +0 -296
  139. package/plugins/specweave/lib/hooks/update-tasks-md.ts.bak +0 -489
  140. package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +0 -353
  141. package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +0 -172
  142. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
  143. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +0 -360
  144. package/plugins/specweave-github/hooks/post-task-completion.sh.backup +0 -258
  145. package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +0 -172
  146. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -444
  147. package/plugins/specweave-release/hooks/post-task-completion.sh.backup +0 -110
@@ -1,489 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * SpecWeave Tasks.md Auto-Updater
5
- *
6
- * Automatically updates tasks.md completion status after TodoWrite completes tasks.
7
- *
8
- * Usage:
9
- * node dist/hooks/lib/update-tasks-md.js <incrementId>
10
- *
11
- * Example:
12
- * node dist/hooks/lib/update-tasks-md.js 0006-llm-native-i18n
13
- *
14
- * What it does:
15
- * 1. Reads tasks.md for the given increment
16
- * 2. Finds recently completed tasks from TodoWrite
17
- * 3. Updates "[ ]" to "[x]" for completed tasks
18
- * 4. Updates "Status: ⏳ Pending" to "Status: [x] Completed"
19
- * 5. Recalculates progress percentage
20
- * 6. Writes back to tasks.md
21
- *
22
- * @author SpecWeave Team
23
- * @version 1.0.0
24
- */
25
-
26
- import fs from 'fs-extra';
27
- import path from 'path';
28
-
29
- interface TaskMatch {
30
- taskId: string;
31
- lineNumber: number;
32
- currentStatus: 'pending' | 'in_progress' | 'completed';
33
- }
34
-
35
- interface TaskConsistencyFix {
36
- taskId: string;
37
- lineNumber: number;
38
- action: 'add-complete-marker' | 'remove-complete-marker';
39
- currentLine: string;
40
- }
41
-
42
- /**
43
- * Main function - update tasks.md for given increment
44
- */
45
- async function updateTasksMd(incrementId: string): Promise<void> {
46
- try {
47
- console.log(`\n🔄 Updating tasks.md for increment: ${incrementId}`);
48
-
49
- // 1. Validate increment exists
50
- const incrementDir = path.join(process.cwd(), '.specweave', 'increments', incrementId);
51
- if (!fs.existsSync(incrementDir)) {
52
- console.error(`❌ Increment directory not found: ${incrementDir}`);
53
- process.exit(1);
54
- }
55
-
56
- const tasksPath = path.join(incrementDir, 'tasks.md');
57
- if (!fs.existsSync(tasksPath)) {
58
- console.error(`❌ tasks.md not found: ${tasksPath}`);
59
- process.exit(1);
60
- }
61
-
62
- // 2. Read tasks.md
63
- const originalContent = await fs.readFile(tasksPath, 'utf-8');
64
- const lines = originalContent.split('\n');
65
-
66
- console.log(`📖 Read tasks.md (${lines.length} lines)`);
67
-
68
- // 3. Parse task completion status
69
- const tasks = parseTaskStatus(lines);
70
- console.log(`📋 Found ${tasks.length} tasks`);
71
-
72
- // 4. Get recently completed tasks and consistency fixes
73
- const { completedTasks, fixes } = detectCompletedTasks(lines);
74
-
75
- // 4a. Apply consistency fixes FIRST (if any)
76
- let updatedContent = originalContent;
77
- let autoFixedCount = 0;
78
-
79
- if (fixes.length > 0) {
80
- console.log(`🔧 Auto-fixing ${fixes.length} task consistency issue(s)...`);
81
- updatedContent = applyConsistencyFixes(originalContent, fixes);
82
- autoFixedCount = fixes.length;
83
- console.log('✅ Task consistency auto-fixed');
84
- }
85
-
86
- if (completedTasks.length === 0 && fixes.length === 0) {
87
- console.log('✅ No new task completions or consistency fixes needed');
88
- return;
89
- }
90
-
91
- if (completedTasks.length > 0) {
92
- console.log(`🎯 Detected ${completedTasks.length} completed task(s):`, completedTasks);
93
- }
94
-
95
- // 5. Update task status in content
96
-
97
- for (const taskId of completedTasks) {
98
- updatedContent = markTaskComplete(updatedContent, taskId);
99
- }
100
-
101
- // 6. Recalculate progress
102
- const updatedLines = updatedContent.split('\n');
103
- const totalTasks = countTotalTasks(updatedLines);
104
- const completedCount = countCompletedTasks(updatedLines);
105
- const progress = Math.round((completedCount / totalTasks) * 100);
106
-
107
- console.log(`📊 Progress: ${completedCount}/${totalTasks} (${progress}%)`);
108
-
109
- // 7. Update header with new progress
110
- updatedContent = updateProgressHeader(updatedContent, completedCount, totalTasks, progress);
111
-
112
- // 8. Write back to tasks.md
113
- await fs.writeFile(tasksPath, updatedContent, 'utf-8');
114
-
115
- console.log(`✅ Updated ${tasksPath}`);
116
- if (autoFixedCount > 0) {
117
- console.log(`🔧 Auto-fixed ${autoFixedCount} consistency issue(s)`);
118
- }
119
- console.log(` Completed: ${completedCount}/${totalTasks}`);
120
- console.log(` Progress: ${progress}%\n`);
121
-
122
- } catch (error) {
123
- console.error('❌ Error updating tasks.md:', error);
124
- process.exit(1);
125
- }
126
- }
127
-
128
- /**
129
- * Parse task status from lines
130
- */
131
- function parseTaskStatus(lines: string[]): TaskMatch[] {
132
- const tasks: TaskMatch[] = [];
133
- const taskPattern = /^###\s+(T-?\d+[-A-Z]*):?\s+(.+)/; // Matches "### T-001: Task Name" or "### T-001-DISCIPLINE:"
134
-
135
- lines.forEach((line, index) => {
136
- const match = line.match(taskPattern);
137
- if (match) {
138
- const taskId = match[1];
139
-
140
- // Look ahead for status line
141
- let status: 'pending' | 'in_progress' | 'completed' = 'pending';
142
-
143
- for (let i = index + 1; i < Math.min(index + 5, lines.length); i++) {
144
- const nextLine = lines[i];
145
- if (nextLine.includes('**Status**:')) {
146
- if (nextLine.includes('[x] Completed')) {
147
- status = 'completed';
148
- } else if (nextLine.includes('⏳ Pending') || nextLine.includes('[ ] Pending')) {
149
- status = 'pending';
150
- } else if (nextLine.includes('🔄 In Progress') || nextLine.includes('in_progress')) {
151
- status = 'in_progress';
152
- }
153
- break;
154
- }
155
- }
156
-
157
- tasks.push({
158
- taskId,
159
- lineNumber: index,
160
- currentStatus: status,
161
- });
162
- }
163
- });
164
-
165
- return tasks;
166
- }
167
-
168
- /**
169
- * Detect which tasks are completed (STRICT VALIDATION)
170
- *
171
- * Detection strategies (ALL must be true):
172
- * 1. Task header has "✅ COMPLETE" marker AND
173
- * all implementation checkboxes are marked [x]
174
- * 2. OR: Task header has "Status: [x] Completed" (legacy format)
175
- *
176
- * This prevents inconsistencies where header says COMPLETE but checkboxes
177
- * are unchecked. Both must match for a task to be considered complete.
178
- *
179
- * @see .specweave/increments/0037/reports/ULTRATHINK-COMPLETE-MARKER-VS-CHECKBOXES.md
180
- */
181
- function detectCompletedTasks(lines: string[]): { completedTasks: string[]; fixes: TaskConsistencyFix[] } {
182
- const completedTasks: string[] = [];
183
- const fixes: TaskConsistencyFix[] = [];
184
- const warnings: string[] = [];
185
- const taskPattern = /^###\s+(T-\d+[-A-Z]*):?\s+(.+)/;
186
-
187
- for (let i = 0; i < lines.length; i++) {
188
- const line = lines[i];
189
- const taskMatch = line.match(taskPattern);
190
-
191
- if (!taskMatch) continue;
192
-
193
- const taskId = taskMatch[1];
194
- const taskTitle = taskMatch[2];
195
- const hasCompleteMarker = taskTitle.includes('✅ COMPLETE');
196
-
197
- // Get implementation section
198
- const taskEndIndex = findNextTaskStart(lines, i + 1);
199
- const implementationSection = findImplementationSection(lines, i, taskEndIndex);
200
-
201
- let allCheckboxesComplete = false;
202
- if (implementationSection) {
203
- allCheckboxesComplete = checkAllCheckboxesComplete(implementationSection);
204
- }
205
-
206
- // STRICT VALIDATION: Require BOTH header AND checkboxes to match
207
- if (hasCompleteMarker && implementationSection) {
208
- if (allCheckboxesComplete) {
209
- // ✅ CONSISTENT: Header says COMPLETE and all checkboxes checked
210
- if (!completedTasks.includes(taskId)) {
211
- completedTasks.push(taskId);
212
- }
213
- } else {
214
- // ⚠️ INCONSISTENT: Header says COMPLETE but checkboxes incomplete - AUTO-FIX
215
- fixes.push({
216
- taskId,
217
- lineNumber: i,
218
- action: 'remove-complete-marker',
219
- currentLine: line
220
- });
221
- warnings.push(`${taskId}: Header has ✅ COMPLETE but not all checkboxes checked`);
222
- }
223
- continue;
224
- }
225
-
226
- // If no implementation section, remove COMPLETE marker (can't verify)
227
- if (hasCompleteMarker && !implementationSection) {
228
- fixes.push({
229
- taskId,
230
- lineNumber: i,
231
- action: 'remove-complete-marker',
232
- currentLine: line
233
- });
234
- warnings.push(`${taskId}: Header has ✅ COMPLETE but no implementation section to verify`);
235
- continue;
236
- }
237
-
238
- // Warn if checkboxes all complete but header missing marker - AUTO-FIX
239
- if (!hasCompleteMarker && implementationSection && allCheckboxesComplete) {
240
- fixes.push({
241
- taskId,
242
- lineNumber: i,
243
- action: 'add-complete-marker',
244
- currentLine: line
245
- });
246
- warnings.push(`${taskId}: All checkboxes checked but header missing ✅ COMPLETE`);
247
- // Still count as complete (checkboxes are source of truth for work done)
248
- if (!completedTasks.includes(taskId)) {
249
- completedTasks.push(taskId);
250
- }
251
- continue;
252
- }
253
-
254
- // Strategy 2: Check for "Status: [x] Completed" (legacy format)
255
- for (let j = i + 1; j < Math.min(i + 10, taskEndIndex); j++) {
256
- const statusLine = lines[j];
257
- if (statusLine.includes('**Status**:') && statusLine.includes('[x] Completed')) {
258
- if (!completedTasks.includes(taskId)) {
259
- completedTasks.push(taskId);
260
- }
261
- break;
262
- }
263
- }
264
- }
265
-
266
- // Report warnings if any
267
- if (warnings.length > 0) {
268
- console.warn('\n⚠️ Task Consistency Warnings:');
269
- warnings.forEach(w => console.warn(` ${w}`));
270
- console.warn('');
271
- }
272
-
273
- return { completedTasks, fixes };
274
- }
275
-
276
- /**
277
- * Apply task consistency fixes to content
278
- */
279
- function applyConsistencyFixes(content: string, fixes: TaskConsistencyFix[]): string {
280
- const lines = content.split('\n');
281
-
282
- // Apply fixes (process in reverse order to preserve line numbers)
283
- for (const fix of fixes.reverse()) {
284
- const line = lines[fix.lineNumber];
285
-
286
- if (fix.action === 'remove-complete-marker') {
287
- // Remove ✅ COMPLETE from header
288
- const fixed = line.replace(/\s*✅\s*COMPLETE\s*/g, '');
289
- lines[fix.lineNumber] = fixed;
290
- } else if (fix.action === 'add-complete-marker') {
291
- // Add ✅ COMPLETE to header (before any trailing spaces)
292
- const fixed = line.trim() + ' ✅ COMPLETE';
293
- lines[fix.lineNumber] = fixed;
294
- }
295
- }
296
-
297
- return lines.join('\n');
298
- }
299
-
300
- /**
301
- * Find the next task header start index
302
- */
303
- function findNextTaskStart(lines: string[], startIndex: number): number {
304
- const taskPattern = /^###\s+T-\d+/;
305
-
306
- for (let i = startIndex; i < lines.length; i++) {
307
- if (taskPattern.test(lines[i])) {
308
- return i;
309
- }
310
- }
311
-
312
- return lines.length;
313
- }
314
-
315
- /**
316
- * Find the Implementation section within a task
317
- */
318
- function findImplementationSection(lines: string[], taskStartIndex: number, taskEndIndex: number): string[] | null {
319
- let inImplementation = false;
320
- const implementationLines: string[] = [];
321
-
322
- for (let i = taskStartIndex; i < taskEndIndex; i++) {
323
- const line = lines[i];
324
-
325
- if (line.includes('**Implementation**:')) {
326
- inImplementation = true;
327
- continue;
328
- }
329
-
330
- if (inImplementation) {
331
- // Stop at next section header (**, ---, or ###)
332
- if (line.trim().startsWith('**') && !line.startsWith('- [')) {
333
- break;
334
- }
335
- if (line.trim().startsWith('---')) {
336
- break;
337
- }
338
- if (line.trim().startsWith('###')) {
339
- break;
340
- }
341
-
342
- implementationLines.push(line);
343
- }
344
- }
345
-
346
- return implementationLines.length > 0 ? implementationLines : null;
347
- }
348
-
349
- /**
350
- * Check if all checkboxes in implementation section are complete
351
- */
352
- function checkAllCheckboxesComplete(implementationLines: string[]): boolean {
353
- const checkboxes = implementationLines.filter(line => line.includes('- ['));
354
-
355
- if (checkboxes.length === 0) {
356
- return false; // No checkboxes = can't determine completion
357
- }
358
-
359
- // All checkboxes must be [x], none can be [ ]
360
- const allComplete = checkboxes.every(line => line.includes('- [x]'));
361
- const noneIncomplete = checkboxes.every(line => !line.includes('- [ ]'));
362
-
363
- return allComplete && noneIncomplete;
364
- }
365
-
366
- /**
367
- * Mark a specific task as complete
368
- */
369
- function markTaskComplete(content: string, taskId: string): string {
370
- let updated = content;
371
-
372
- // Pattern: "**Status**: [ ] Pending" or "**Status**: ⏳ Pending"
373
- const statusPattern = new RegExp(
374
- `(###\\s+${taskId.replace(/[-]/g, '\\-')}[^\\n]*[\\s\\S]*?\\*\\*Status\\*\\*:)\\s*\\[?\\s*\\]?\\s*⏳?\\s*Pending`,
375
- 'i'
376
- );
377
-
378
- updated = updated.replace(statusPattern, '$1 [x] Completed');
379
-
380
- return updated;
381
- }
382
-
383
- /**
384
- * Count total tasks
385
- */
386
- function countTotalTasks(lines: string[]): number {
387
- let count = 0;
388
- const taskPattern = /^###\s+(T-?\d+[-A-Z]*):?\s+/;
389
-
390
- for (const line of lines) {
391
- if (taskPattern.test(line)) {
392
- count++;
393
- }
394
- }
395
-
396
- return count;
397
- }
398
-
399
- /**
400
- * Count completed tasks
401
- *
402
- * Recognizes multiple completion indicators:
403
- * 1. "✅ COMPLETE" marker in task header
404
- * 2. "**Status**: [x] Completed" line
405
- * 3. All implementation checkboxes marked [x]
406
- */
407
- function countCompletedTasks(lines: string[]): number {
408
- let count = 0;
409
- const taskPattern = /^###\s+(T-?\d+[-A-Z]*):?\s+(.+)/;
410
-
411
- for (let i = 0; i < lines.length; i++) {
412
- const line = lines[i];
413
- const taskMatch = line.match(taskPattern);
414
-
415
- if (taskMatch) {
416
- const taskTitle = taskMatch[2];
417
-
418
- // Strategy 1: Check for ✅ COMPLETE marker in header
419
- if (taskTitle.includes('✅ COMPLETE')) {
420
- count++;
421
- continue;
422
- }
423
-
424
- // Strategy 2: Check for Status: [x] Completed
425
- let found = false;
426
- for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
427
- const nextLine = lines[j];
428
- if (nextLine.includes('**Status**:') && nextLine.includes('[x] Completed')) {
429
- count++;
430
- found = true;
431
- break;
432
- }
433
- }
434
-
435
- if (found) continue;
436
-
437
- // Strategy 3: Check if all implementation checkboxes are [x]
438
- const taskEndIndex = findNextTaskStart(lines, i + 1);
439
- const implementationSection = findImplementationSection(lines, i, taskEndIndex);
440
-
441
- if (implementationSection) {
442
- const allCheckboxesComplete = checkAllCheckboxesComplete(implementationSection);
443
- if (allCheckboxesComplete) {
444
- count++;
445
- }
446
- }
447
- }
448
- }
449
-
450
- return count;
451
- }
452
-
453
- /**
454
- * Update progress header
455
- */
456
- function updateProgressHeader(content: string, completed: number, total: number, progress: number): string {
457
- let updated = content;
458
-
459
- // Update "**Completed**: X"
460
- updated = updated.replace(/\*\*Completed\*\*:\s*\d+/, `**Completed**: ${completed}`);
461
-
462
- // Update "**Progress**: X%"
463
- updated = updated.replace(/\*\*Progress\*\*:\s*\d+%/, `**Progress**: ${progress}%`);
464
-
465
- // Update "**Total Tasks**: X"
466
- updated = updated.replace(/\*\*Total Tasks\*\*:\s*\d+/, `**Total Tasks**: ${total}`);
467
-
468
- return updated;
469
- }
470
-
471
- // CLI entry point
472
- const isMainModule = import.meta.url === `file://${process.argv[1]}`;
473
-
474
- if (isMainModule) {
475
- const incrementId = process.argv[2];
476
-
477
- if (!incrementId) {
478
- console.error('❌ Usage: update-tasks-md <incrementId>');
479
- console.error(' Example: update-tasks-md 0006-llm-native-i18n');
480
- process.exit(1);
481
- }
482
-
483
- updateTasksMd(incrementId).catch((error) => {
484
- console.error('❌ Fatal error:', error);
485
- process.exit(1);
486
- });
487
- }
488
-
489
- export { updateTasksMd };