speccrew 0.1.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 (153) hide show
  1. package/.speccrew/agents/speccrew-feature-designer.md +142 -0
  2. package/.speccrew/agents/speccrew-product-manager.md +61 -0
  3. package/.speccrew/agents/speccrew-system-designer.md +200 -0
  4. package/.speccrew/agents/speccrew-system-developer.md +238 -0
  5. package/.speccrew/agents/speccrew-task-worker.md +80 -0
  6. package/.speccrew/agents/speccrew-team-leader.md +92 -0
  7. package/.speccrew/agents/speccrew-test-manager.md +313 -0
  8. package/.speccrew/skills/speccrew-create-agents/SKILL.md +98 -0
  9. package/.speccrew/skills/speccrew-create-agents/templates/agents/designer-agent.md +54 -0
  10. package/.speccrew/skills/speccrew-create-agents/templates/agents/dev-agent.md +79 -0
  11. package/.speccrew/skills/speccrew-create-agents/templates/agents/test-agent.md +80 -0
  12. package/.speccrew/skills/speccrew-dev-backend/SKILL.md +205 -0
  13. package/.speccrew/skills/speccrew-dev-backend/templates/TASK-RECORD-TEMPLATE.md +118 -0
  14. package/.speccrew/skills/speccrew-dev-desktop/SKILL.md +258 -0
  15. package/.speccrew/skills/speccrew-dev-desktop/templates/TASK-RECORD-TEMPLATE.md +161 -0
  16. package/.speccrew/skills/speccrew-dev-frontend/SKILL.md +202 -0
  17. package/.speccrew/skills/speccrew-dev-frontend/templates/TASK-RECORD-TEMPLATE.md +115 -0
  18. package/.speccrew/skills/speccrew-dev-mobile/SKILL.md +200 -0
  19. package/.speccrew/skills/speccrew-dev-mobile/templates/TASK-RECORD-TEMPLATE.md +125 -0
  20. package/.speccrew/skills/speccrew-fd-api-contract/SKILL.md +73 -0
  21. package/.speccrew/skills/speccrew-fd-api-contract/templates/API-CONTRACT-TEMPLATE.md +96 -0
  22. package/.speccrew/skills/speccrew-fd-feature-design/SKILL.md +395 -0
  23. package/.speccrew/skills/speccrew-fd-feature-design/templates/FEATURE-SPEC-TEMPLATE.md +387 -0
  24. package/.speccrew/skills/speccrew-get-timestamp/SKILL.md +80 -0
  25. package/.speccrew/skills/speccrew-get-timestamp/scripts/get-timestamp.js +35 -0
  26. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/SKILL.md +1116 -0
  27. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-FASTAPI.md +462 -0
  28. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-JAVA.md +480 -0
  29. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-NET.md +464 -0
  30. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE.md +480 -0
  31. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/MODULE-OVERVIEW-TEMPLATE.md +367 -0
  32. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/SKILL.md +667 -0
  33. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/STATUS-FORMATS.md +74 -0
  34. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/batch-orchestrator.js +176 -0
  35. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-next-batch.js +150 -0
  36. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-pending-features.js +106 -0
  37. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/mark-stale.js +249 -0
  38. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/process-batch-results.js +848 -0
  39. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/update-feature-status.js +226 -0
  40. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/SKILL.md +264 -0
  41. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/examples/features.json +34 -0
  42. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js +867 -0
  43. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/test-inventory.js +26 -0
  44. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/SKILL.md +165 -0
  45. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/apply-module-mapping.js +208 -0
  46. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/extract-module-summary.js +180 -0
  47. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/reindex-modules.js +358 -0
  48. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/SKILL.md +1055 -0
  49. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-DESKTOP.md +303 -0
  50. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-ELECTRON.md +327 -0
  51. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MINIAPP.md +292 -0
  52. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MOBILE.md +281 -0
  53. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI.md +324 -0
  54. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/SKILL.md +270 -0
  55. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/COMPONENT-PATTERN-TEMPLATE.md +33 -0
  56. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/LAYOUT-PATTERN-TEMPLATE.md +33 -0
  57. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/PAGE-TYPE-TEMPLATE.md +33 -0
  58. package/.speccrew/skills/speccrew-knowledge-graph-query/SKILL.md +229 -0
  59. package/.speccrew/skills/speccrew-knowledge-graph-query/scripts/graph-query.js +549 -0
  60. package/.speccrew/skills/speccrew-knowledge-graph-write/SKILL.md +181 -0
  61. package/.speccrew/skills/speccrew-knowledge-graph-write/scripts/graph-write.js +651 -0
  62. package/.speccrew/skills/speccrew-knowledge-module-summarize/SKILL.md +305 -0
  63. package/.speccrew/skills/speccrew-knowledge-module-summarize/templates/MODULE-OVERVIEW-TEMPLATE.md +400 -0
  64. package/.speccrew/skills/speccrew-knowledge-system-summarize/SKILL.md +351 -0
  65. package/.speccrew/skills/speccrew-knowledge-system-summarize/templates/SYSTEM-OVERVIEW-TEMPLATE.md +294 -0
  66. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/SKILL.md +683 -0
  67. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/STATUS-FORMATS.md +550 -0
  68. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/templates/techs-manifest-EXAMPLE.json +35 -0
  69. package/.speccrew/skills/speccrew-knowledge-techs-generate/SKILL.md +1087 -0
  70. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/ARCHITECTURE-TEMPLATE.md +240 -0
  71. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COLOR-SYSTEM-TEMPLATE.md +68 -0
  72. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COMPONENT-LIBRARY-TEMPLATE.md +86 -0
  73. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-BUILD-TEMPLATE.md +466 -0
  74. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DATA-TEMPLATE.md +432 -0
  75. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DESIGN-TEMPLATE.md +1209 -0
  76. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DEV-TEMPLATE.md +1433 -0
  77. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-SYSTEM-TEST-TEMPLATE.md +1052 -0
  78. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-UNIT-TEST-TEMPLATE.md +946 -0
  79. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/INDEX-TEMPLATE.md +29 -0
  80. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-LAYOUTS-TEMPLATE.md +69 -0
  81. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +74 -0
  82. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/TECH-STACK-TEMPLATE.md +232 -0
  83. package/.speccrew/skills/speccrew-knowledge-techs-generate-conventions/SKILL.md +628 -0
  84. package/.speccrew/skills/speccrew-knowledge-techs-generate-ui-style/SKILL.md +392 -0
  85. package/.speccrew/skills/speccrew-knowledge-techs-index/SKILL.md +489 -0
  86. package/.speccrew/skills/speccrew-knowledge-techs-index/templates/INDEX-TEMPLATE.md +243 -0
  87. package/.speccrew/skills/speccrew-knowledge-techs-init/SKILL.md +269 -0
  88. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/SKILL.md +562 -0
  89. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/BUSINESS-COMPONENTS-TEMPLATE.md +171 -0
  90. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMMON-COMPONENTS-TEMPLATE.md +177 -0
  91. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-INDIVIDUAL-TEMPLATE.md +80 -0
  92. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-LIBRARY-TEMPLATE.md +118 -0
  93. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-INDIVIDUAL-TEMPLATE.md +97 -0
  94. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-PATTERNS-TEMPLATE.md +208 -0
  95. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/NAVIGATION-PATTERNS-TEMPLATE.md +157 -0
  96. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-INDIVIDUAL-TEMPLATE.md +123 -0
  97. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +58 -0
  98. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/SPACING-TEMPLATE.md +119 -0
  99. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/STYLE-SYSTEM-TEMPLATE.md +117 -0
  100. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/TYPOGRAPHY-TEMPLATE.md +107 -0
  101. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/UI-STYLE-GUIDE-TEMPLATE.md +171 -0
  102. package/.speccrew/skills/speccrew-pm-requirement-analysis/SKILL.md +434 -0
  103. package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/BIZS-MODELING-TEMPLATE.md +332 -0
  104. package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/PRD-TEMPLATE.md +200 -0
  105. package/.speccrew/skills/speccrew-pm-requirement-assess/SKILL.md +195 -0
  106. package/.speccrew/skills/speccrew-project-diagnosis/SKILL.md +208 -0
  107. package/.speccrew/skills/speccrew-project-diagnosis/templates/DIAGNOSIS-REPORT-TEMPLATE.md +202 -0
  108. package/.speccrew/skills/speccrew-sd-backend/SKILL.md +188 -0
  109. package/.speccrew/skills/speccrew-sd-backend/templates/INDEX-TEMPLATE.md +85 -0
  110. package/.speccrew/skills/speccrew-sd-backend/templates/SD-BACKEND-TEMPLATE.md +269 -0
  111. package/.speccrew/skills/speccrew-sd-desktop/SKILL.md +192 -0
  112. package/.speccrew/skills/speccrew-sd-desktop/templates/INDEX-TEMPLATE.md +271 -0
  113. package/.speccrew/skills/speccrew-sd-desktop/templates/SD-DESKTOP-TEMPLATE.md +673 -0
  114. package/.speccrew/skills/speccrew-sd-frontend/SKILL.md +176 -0
  115. package/.speccrew/skills/speccrew-sd-frontend/templates/INDEX-TEMPLATE.md +184 -0
  116. package/.speccrew/skills/speccrew-sd-frontend/templates/SD-FRONTEND-TEMPLATE.md +382 -0
  117. package/.speccrew/skills/speccrew-sd-mobile/SKILL.md +189 -0
  118. package/.speccrew/skills/speccrew-sd-mobile/templates/INDEX-TEMPLATE.md +219 -0
  119. package/.speccrew/skills/speccrew-sd-mobile/templates/SD-MOBILE-TEMPLATE.md +534 -0
  120. package/.speccrew/skills/speccrew-test-case-design/SKILL.md +284 -0
  121. package/.speccrew/skills/speccrew-test-case-design/templates/TEST-CASE-DESIGN-TEMPLATE.md +263 -0
  122. package/.speccrew/skills/speccrew-test-code-gen/SKILL.md +313 -0
  123. package/.speccrew/skills/speccrew-test-code-gen/templates/TEST-CODE-PLAN-TEMPLATE.md +180 -0
  124. package/.speccrew/skills/speccrew-test-execute/SKILL.md +283 -0
  125. package/.speccrew/skills/speccrew-test-execute/templates/BUG-REPORT-TEMPLATE.md +50 -0
  126. package/.speccrew/skills/speccrew-test-execute/templates/TEST-REPORT-TEMPLATE.md +57 -0
  127. package/.speccrew/skills/speccrew-workflow-diagnose/SKILL.md +155 -0
  128. package/LICENSE +21 -0
  129. package/README.ar.md +318 -0
  130. package/README.en.md +318 -0
  131. package/README.es.md +318 -0
  132. package/README.md +340 -0
  133. package/bin/cli.js +62 -0
  134. package/lib/commands/doctor.js +138 -0
  135. package/lib/commands/init.js +231 -0
  136. package/lib/commands/list.js +114 -0
  137. package/lib/commands/uninstall.js +117 -0
  138. package/lib/commands/update.js +351 -0
  139. package/lib/ide-adapters.js +73 -0
  140. package/lib/utils.js +104 -0
  141. package/package.json +28 -0
  142. package/workspace-template/docs/configs/document-templates.json +667 -0
  143. package/workspace-template/docs/configs/platform-mapping.json +194 -0
  144. package/workspace-template/docs/configs/tech-stack-mappings.json +313 -0
  145. package/workspace-template/docs/configs/validation-rules.json +87 -0
  146. package/workspace-template/docs/rules/mermaid-rule.md +114 -0
  147. package/workspace-template/docs/solutions/Agent/346/212/200/350/203/275/345/256/232/344/271/211+/351/234/200/346/261/202/346/226/207/346/241/243+UML/344/275/277/347/224/250/346/250/241/346/235/277/357/274/210ISA-95/345/205/255/346/256/265/345/274/217/350/236/215/345/220/210/347/211/210/357/274/211.md +586 -0
  148. package/workspace-template/docs/solutions/agent-knowledge-map.md +238 -0
  149. package/workspace-template/docs/solutions/bizs-knowledge-pipeline.md +678 -0
  150. package/workspace-template/docs/solutions/harness.md +410 -0
  151. package/workspace-template/docs/solutions/knowledge-incremental-sync-spec.md +943 -0
  152. package/workspace-template/docs/solutions/techs-knowledge-pipeline.md +803 -0
  153. package/workspace-template/docs/solutions/workspace-structure.md +318 -0
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Mark features as stale (pending re-analysis) for specified paths.
5
+ *
6
+ * Scans all features-*.json files in the SyncStatePath directory and marks
7
+ * features as stale when their sourcePath matches one of the provided paths.
8
+ * Matching supports exact path match or directory prefix match (when a
9
+ * directory path is provided, all features under that directory are marked).
10
+ *
11
+ * Resets the following fields for matched features:
12
+ * - analyzed = false
13
+ * - status = "pending" (if the field exists)
14
+ * - startedAt = null
15
+ * - completedAt = null
16
+ * - analysisNotes = null
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+
22
+ // Parse command line arguments
23
+ function parseArgs() {
24
+ const args = process.argv.slice(2);
25
+ const result = {
26
+ syncStatePath: null,
27
+ paths: []
28
+ };
29
+
30
+ for (let i = 0; i < args.length; i++) {
31
+ const arg = args[i];
32
+ switch (arg) {
33
+ case '--syncStatePath':
34
+ case '-SyncStatePath':
35
+ result.syncStatePath = args[++i];
36
+ break;
37
+ case '--paths':
38
+ case '-Paths':
39
+ // Support comma-separated paths or multiple --paths arguments
40
+ const pathsValue = args[++i];
41
+ if (pathsValue) {
42
+ result.paths.push(...pathsValue.split(',').map(p => p.trim()).filter(p => p));
43
+ }
44
+ break;
45
+ }
46
+ }
47
+
48
+ return result;
49
+ }
50
+
51
+ // Helper function to safely set property on object
52
+ function setFeatureProperty(obj, propertyName, value) {
53
+ obj[propertyName] = value;
54
+ }
55
+
56
+ // Helper function to safely remove property from object
57
+ function removeFeatureProperty(obj, propertyName) {
58
+ if (propertyName in obj) {
59
+ delete obj[propertyName];
60
+ }
61
+ }
62
+
63
+ // Helper function to normalize path for comparison
64
+ // - Convert backslashes to forward slashes
65
+ // - Remove trailing slashes
66
+ // - Convert to lowercase for case-insensitive comparison (Windows)
67
+ function normalizePath(inputPath) {
68
+ if (!inputPath) {
69
+ return '';
70
+ }
71
+ let normalized = inputPath.replace(/\\/g, '/');
72
+ normalized = normalized.replace(/\/$/, '');
73
+ return normalized.toLowerCase();
74
+ }
75
+
76
+ function main() {
77
+ try {
78
+ const args = parseArgs();
79
+
80
+ if (!args.syncStatePath) {
81
+ console.error('Error: --syncStatePath is required');
82
+ process.exit(1);
83
+ }
84
+
85
+ if (args.paths.length === 0) {
86
+ console.error('Error: --paths is required');
87
+ process.exit(1);
88
+ }
89
+
90
+ // Validate SyncStatePath exists
91
+ const resolvedSyncStatePath = path.resolve(args.syncStatePath);
92
+ if (!fs.existsSync(resolvedSyncStatePath)) {
93
+ console.error(`SyncStatePath not found: ${args.syncStatePath}`);
94
+ process.exit(1);
95
+ }
96
+
97
+ // Normalize input paths for matching
98
+ const normalizedInputPaths = args.paths.map(p => normalizePath(p));
99
+
100
+ // Find all features-*.json files
101
+ const featureFiles = fs.readdirSync(resolvedSyncStatePath).filter(f => {
102
+ return f.startsWith('features-') && f.endsWith('.json') && fs.statSync(path.join(resolvedSyncStatePath, f)).isFile();
103
+ });
104
+
105
+ if (featureFiles.length === 0) {
106
+ // No feature files found, output empty result
107
+ const result = {
108
+ totalAffected: 0,
109
+ features: []
110
+ };
111
+ console.log(JSON.stringify(result, null, 2));
112
+ process.exit(0);
113
+ }
114
+
115
+ const affectedFeatures = [];
116
+
117
+ for (const fileName of featureFiles) {
118
+ const filePath = path.join(resolvedSyncStatePath, fileName);
119
+ const lockPath = `${filePath}.lock`;
120
+ const maxRetries = 30;
121
+ let retryCount = 0;
122
+ let lockAcquired = false;
123
+
124
+ // Acquire file lock
125
+ while (!lockAcquired && retryCount < maxRetries) {
126
+ try {
127
+ // Try to create lock file exclusively
128
+ const fd = fs.openSync(lockPath, 'wx');
129
+ fs.closeSync(fd);
130
+ lockAcquired = true;
131
+ } catch (error) {
132
+ retryCount++;
133
+ if (retryCount >= maxRetries) {
134
+ const errorMsg = `Failed to acquire file lock for '${fileName}' after ${maxRetries} attempts (waited ${maxRetries} seconds). The file may be locked by another process.`;
135
+ console.warn(errorMsg);
136
+ // Continue to next file instead of exiting
137
+ break;
138
+ }
139
+ if (retryCount % 5 === 0) {
140
+ console.warn(`Waiting for file lock on '${fileName}'... (attempt ${retryCount} of ${maxRetries})`);
141
+ }
142
+ // Wait 1 second before retry
143
+ const start = Date.now();
144
+ while (Date.now() - start < 1000) {
145
+ // Busy wait
146
+ }
147
+ }
148
+ }
149
+
150
+ // Skip this file if lock could not be acquired
151
+ if (!lockAcquired) {
152
+ continue;
153
+ }
154
+
155
+ try {
156
+ // Read the JSON file
157
+ const rawContent = fs.readFileSync(filePath, 'utf8');
158
+ const content = JSON.parse(rawContent);
159
+ let fileModified = false;
160
+
161
+ if (content.features && Array.isArray(content.features)) {
162
+ for (let i = 0; i < content.features.length; i++) {
163
+ const feature = content.features[i];
164
+ const featureSourcePath = feature.sourcePath;
165
+
166
+ if (!featureSourcePath) {
167
+ continue;
168
+ }
169
+
170
+ const normalizedFeaturePath = normalizePath(featureSourcePath);
171
+
172
+ // Check if any input path matches this feature
173
+ let matched = false;
174
+ for (const inputPath of normalizedInputPaths) {
175
+ // Exact match or directory prefix match
176
+ if (normalizedFeaturePath === inputPath) {
177
+ matched = true;
178
+ break;
179
+ }
180
+ // Directory prefix match: input path is a directory and feature path starts with it
181
+ if (normalizedFeaturePath.startsWith(`${inputPath}/`)) {
182
+ matched = true;
183
+ break;
184
+ }
185
+ }
186
+
187
+ if (matched) {
188
+ // Reset fields
189
+ setFeatureProperty(feature, 'analyzed', false);
190
+
191
+ // Only set status if the field already exists
192
+ if ('status' in feature) {
193
+ setFeatureProperty(feature, 'status', 'pending');
194
+ }
195
+
196
+ // Clear timestamp fields
197
+ removeFeatureProperty(feature, 'startedAt');
198
+ removeFeatureProperty(feature, 'completedAt');
199
+ removeFeatureProperty(feature, 'analysisNotes');
200
+
201
+ content.features[i] = feature;
202
+ fileModified = true;
203
+
204
+ // Add to affected list
205
+ affectedFeatures.push({
206
+ sourcePath: featureSourcePath,
207
+ module: feature.module,
208
+ sourceFile: fileName
209
+ });
210
+ }
211
+ }
212
+ }
213
+
214
+ // Update counters and write back if modified
215
+ if (fileModified) {
216
+ content.analyzedCount = content.features.filter(f => f.analyzed === true).length;
217
+ content.pendingCount = content.features.filter(f => f.analyzed === false).length;
218
+
219
+ // Atomic write: temp file + rename
220
+ const tempFile = `${filePath}.tmp`;
221
+ fs.writeFileSync(tempFile, JSON.stringify(content, null, 2), 'utf8');
222
+ fs.renameSync(tempFile, filePath);
223
+ }
224
+ } finally {
225
+ // Release lock - remove lock file
226
+ try {
227
+ if (fs.existsSync(lockPath)) {
228
+ fs.unlinkSync(lockPath);
229
+ }
230
+ } catch (e) {
231
+ // Ignore cleanup errors
232
+ }
233
+ }
234
+ }
235
+
236
+ // Output result as JSON
237
+ const result = {
238
+ totalAffected: affectedFeatures.length,
239
+ features: affectedFeatures
240
+ };
241
+
242
+ console.log(JSON.stringify(result, null, 2));
243
+ } catch (error) {
244
+ console.error(`Error: ${error.message}`);
245
+ process.exit(1);
246
+ }
247
+ }
248
+
249
+ main();