speccrew 0.6.68 → 0.7.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 (134) hide show
  1. package/.speccrew/agents/speccrew-task-worker.md +1 -1
  2. package/.speccrew/agents/speccrew-team-leader.md +336 -189
  3. package/.speccrew/skills/speccrew-agentflow-manager/SKILL.md +161 -0
  4. package/.speccrew/skills/speccrew-agentflow-manager/workflow.agentflow.xml +347 -0
  5. package/.speccrew/skills/speccrew-deploy-build/SKILL.md +3 -56
  6. package/.speccrew/skills/speccrew-deploy-build/workflow.agentflow.xml +125 -0
  7. package/.speccrew/skills/speccrew-deploy-migrate/SKILL.md +3 -64
  8. package/.speccrew/skills/speccrew-deploy-migrate/workflow.agentflow.xml +135 -0
  9. package/.speccrew/skills/speccrew-deploy-smoke-test/SKILL.md +4 -156
  10. package/.speccrew/skills/speccrew-deploy-smoke-test/workflow.agentflow.xml +178 -0
  11. package/.speccrew/skills/speccrew-deploy-startup/SKILL.md +3 -135
  12. package/.speccrew/skills/speccrew-deploy-startup/workflow.agentflow.xml +223 -0
  13. package/.speccrew/skills/speccrew-dev-backend/SKILL.md +10 -2
  14. package/.speccrew/skills/speccrew-dev-backend/workflow.agentflow.xml +254 -0
  15. package/.speccrew/skills/speccrew-dev-desktop-electron/SKILL.md +10 -2
  16. package/.speccrew/skills/speccrew-dev-desktop-electron/workflow.agentflow.xml +259 -0
  17. package/.speccrew/skills/speccrew-dev-desktop-tauri/SKILL.md +10 -2
  18. package/.speccrew/skills/speccrew-dev-desktop-tauri/workflow.agentflow.xml +245 -0
  19. package/.speccrew/skills/speccrew-dev-frontend/SKILL.md +10 -2
  20. package/.speccrew/skills/speccrew-dev-frontend/workflow.agentflow.xml +262 -0
  21. package/.speccrew/skills/speccrew-dev-mobile/SKILL.md +10 -2
  22. package/.speccrew/skills/speccrew-dev-mobile/workflow.agentflow.xml +244 -0
  23. package/.speccrew/skills/speccrew-dev-review-backend/SKILL.md +10 -2
  24. package/.speccrew/skills/speccrew-dev-review-backend/workflow.agentflow.xml +251 -0
  25. package/.speccrew/skills/speccrew-dev-review-desktop/SKILL.md +10 -2
  26. package/.speccrew/skills/speccrew-dev-review-desktop/workflow.agentflow.xml +214 -0
  27. package/.speccrew/skills/speccrew-dev-review-frontend/SKILL.md +10 -2
  28. package/.speccrew/skills/speccrew-dev-review-frontend/workflow.agentflow.xml +213 -0
  29. package/.speccrew/skills/speccrew-dev-review-mobile/SKILL.md +10 -2
  30. package/.speccrew/skills/speccrew-dev-review-mobile/workflow.agentflow.xml +214 -0
  31. package/.speccrew/skills/speccrew-fd-api-contract/SKILL.md +7 -1
  32. package/.speccrew/skills/speccrew-fd-api-contract/workflow.agentflow.xml +222 -0
  33. package/.speccrew/skills/speccrew-fd-feature-analyze/SKILL.md +7 -1
  34. package/.speccrew/skills/speccrew-fd-feature-analyze/workflow.agentflow.xml +223 -0
  35. package/.speccrew/skills/speccrew-fd-feature-design/SKILL.md +7 -1
  36. package/.speccrew/skills/speccrew-fd-feature-design/workflow.agentflow.xml +322 -0
  37. package/.speccrew/skills/speccrew-get-timestamp/SKILL.md +3 -39
  38. package/.speccrew/skills/speccrew-get-timestamp/workflow.agentflow.xml +43 -0
  39. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/SKILL.md +57 -508
  40. package/.speccrew/skills/{speccrew-knowledge-bizs-api-analyze-xml/SKILL.md → speccrew-knowledge-bizs-api-analyze/workflow.agentflow.xml} +1 -154
  41. package/.speccrew/skills/speccrew-knowledge-bizs-api-graph/SKILL.md +73 -283
  42. package/.speccrew/skills/{speccrew-knowledge-bizs-api-graph-xml/SKILL.md → speccrew-knowledge-bizs-api-graph/workflow.agentflow.xml} +0 -298
  43. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/SKILL.md +931 -801
  44. package/.speccrew/skills/{speccrew-knowledge-bizs-dispatch-xml/SKILL.md → speccrew-knowledge-bizs-dispatch/workflow.agentflow.xml} +42 -272
  45. package/.speccrew/skills/speccrew-knowledge-bizs-identify-entries/SKILL.md +263 -71
  46. package/.speccrew/skills/{speccrew-knowledge-bizs-identify-entries-xml/SKILL.md → speccrew-knowledge-bizs-identify-entries/workflow.agentflow.xml} +8 -184
  47. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/SKILL.md +200 -181
  48. package/.speccrew/skills/{speccrew-knowledge-bizs-init-features-xml/SKILL.md → speccrew-knowledge-bizs-init-features/workflow.agentflow.xml} +7 -134
  49. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/SKILL.md +5 -89
  50. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/workflow.agentflow.xml +129 -0
  51. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/SKILL.md +454 -326
  52. package/.speccrew/skills/{speccrew-knowledge-bizs-ui-analyze-xml/SKILL.md → speccrew-knowledge-bizs-ui-analyze/workflow.agentflow.xml} +8 -128
  53. package/.speccrew/skills/speccrew-knowledge-bizs-ui-graph/SKILL.md +302 -247
  54. package/.speccrew/skills/{speccrew-knowledge-bizs-ui-graph-xml/SKILL.md → speccrew-knowledge-bizs-ui-graph/workflow.agentflow.xml} +7 -199
  55. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/SKILL.md +267 -156
  56. package/.speccrew/skills/{speccrew-knowledge-bizs-ui-style-extract-xml/SKILL.md → speccrew-knowledge-bizs-ui-style-extract/workflow.agentflow.xml} +7 -151
  57. package/.speccrew/skills/speccrew-knowledge-graph-query/SKILL.md +3 -122
  58. package/.speccrew/skills/speccrew-knowledge-graph-query/workflow.agentflow.xml +106 -0
  59. package/.speccrew/skills/speccrew-knowledge-graph-write/SKILL.md +3 -80
  60. package/.speccrew/skills/speccrew-knowledge-graph-write/workflow.agentflow.xml +152 -0
  61. package/.speccrew/skills/speccrew-knowledge-module-summarize/SKILL.md +371 -265
  62. package/.speccrew/skills/{speccrew-knowledge-module-summarize-xml/SKILL.md → speccrew-knowledge-module-summarize/workflow.agentflow.xml} +7 -197
  63. package/.speccrew/skills/speccrew-knowledge-system-summarize/SKILL.md +45 -333
  64. package/.speccrew/skills/{speccrew-knowledge-system-summarize-xml/SKILL.md → speccrew-knowledge-system-summarize/workflow.agentflow.xml} +0 -177
  65. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/SKILL.md +174 -727
  66. package/.speccrew/skills/{speccrew-knowledge-techs-dispatch-xml/SKILL.md → speccrew-knowledge-techs-dispatch/workflow.agentflow.xml} +10 -351
  67. package/.speccrew/skills/speccrew-knowledge-techs-generate/SKILL.md +20 -150
  68. package/.speccrew/skills/{speccrew-knowledge-techs-generate-xml/SKILL.md → speccrew-knowledge-techs-generate/workflow.agentflow.xml} +0 -169
  69. package/.speccrew/skills/speccrew-knowledge-techs-generate-conventions/SKILL.md +75 -587
  70. package/.speccrew/skills/{speccrew-knowledge-techs-generate-conventions-xml/SKILL.md → speccrew-knowledge-techs-generate-conventions/workflow.agentflow.xml} +0 -153
  71. package/.speccrew/skills/speccrew-knowledge-techs-generate-quality/SKILL.md +463 -297
  72. package/.speccrew/skills/{speccrew-knowledge-techs-generate-quality-xml/SKILL.md → speccrew-knowledge-techs-generate-quality/workflow.agentflow.xml} +0 -164
  73. package/.speccrew/skills/speccrew-knowledge-techs-generate-ui-style/SKILL.md +57 -292
  74. package/.speccrew/skills/{speccrew-knowledge-techs-generate-ui-style-xml/SKILL.md → speccrew-knowledge-techs-generate-ui-style/workflow.agentflow.xml} +2 -193
  75. package/.speccrew/skills/speccrew-knowledge-techs-index/SKILL.md +49 -335
  76. package/.speccrew/skills/{speccrew-knowledge-techs-index-xml/SKILL.md → speccrew-knowledge-techs-index/workflow.agentflow.xml} +0 -167
  77. package/.speccrew/skills/speccrew-knowledge-techs-init/SKILL.md +28 -109
  78. package/.speccrew/skills/{speccrew-knowledge-techs-init-xml/SKILL.md → speccrew-knowledge-techs-init/workflow.agentflow.xml} +0 -189
  79. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/SKILL.md +3 -487
  80. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/workflow.agentflow.xml +278 -0
  81. package/.speccrew/skills/speccrew-pm-knowledge-detector/SKILL.md +3 -71
  82. package/.speccrew/skills/speccrew-pm-knowledge-detector/workflow.agentflow.xml +108 -0
  83. package/.speccrew/skills/speccrew-pm-module-initializer/SKILL.md +3 -107
  84. package/.speccrew/skills/speccrew-pm-module-initializer/workflow.agentflow.xml +139 -0
  85. package/.speccrew/skills/speccrew-pm-module-matcher/SKILL.md +3 -115
  86. package/.speccrew/skills/speccrew-pm-module-matcher/workflow.agentflow.xml +146 -0
  87. package/.speccrew/skills/speccrew-pm-requirement-analysis/SKILL.md +3 -343
  88. package/.speccrew/skills/speccrew-pm-requirement-analysis/workflow.agentflow.xml +174 -0
  89. package/.speccrew/skills/speccrew-pm-requirement-assess/SKILL.md +3 -91
  90. package/.speccrew/skills/speccrew-pm-requirement-assess/workflow.agentflow.xml +173 -0
  91. package/.speccrew/skills/speccrew-pm-requirement-clarify/SKILL.md +3 -224
  92. package/.speccrew/skills/speccrew-pm-requirement-clarify/workflow.agentflow.xml +159 -0
  93. package/.speccrew/skills/speccrew-pm-requirement-model/SKILL.md +3 -275
  94. package/.speccrew/skills/speccrew-pm-requirement-model/workflow.agentflow.xml +210 -0
  95. package/.speccrew/skills/speccrew-pm-requirement-simple/SKILL.md +3 -76
  96. package/.speccrew/skills/speccrew-pm-requirement-simple/workflow.agentflow.xml +120 -0
  97. package/.speccrew/skills/speccrew-pm-sub-prd-generate/SKILL.md +7 -1
  98. package/.speccrew/skills/speccrew-pm-sub-prd-generate/workflow.agentflow.xml +218 -0
  99. package/.speccrew/skills/speccrew-sd-backend/SKILL.md +7 -1
  100. package/.speccrew/skills/speccrew-sd-backend/workflow.agentflow.xml +264 -0
  101. package/.speccrew/skills/speccrew-sd-desktop/SKILL.md +7 -1
  102. package/.speccrew/skills/speccrew-sd-desktop/workflow.agentflow.xml +288 -0
  103. package/.speccrew/skills/speccrew-sd-framework-evaluate/SKILL.md +7 -1
  104. package/.speccrew/skills/speccrew-sd-framework-evaluate/workflow.agentflow.xml +235 -0
  105. package/.speccrew/skills/speccrew-sd-frontend/SKILL.md +7 -1
  106. package/.speccrew/skills/speccrew-sd-frontend/workflow.agentflow.xml +299 -0
  107. package/.speccrew/skills/speccrew-sd-mobile/SKILL.md +7 -1
  108. package/.speccrew/skills/speccrew-sd-mobile/workflow.agentflow.xml +301 -0
  109. package/.speccrew/skills/speccrew-test-case-design/SKILL.md +165 -284
  110. package/.speccrew/skills/speccrew-test-case-design/workflow.agentflow.xml +210 -0
  111. package/.speccrew/skills/speccrew-test-code-gen/SKILL.md +204 -324
  112. package/.speccrew/skills/speccrew-test-code-gen/workflow.agentflow.xml +265 -0
  113. package/.speccrew/skills/speccrew-test-reporter/SKILL.md +205 -184
  114. package/.speccrew/skills/speccrew-test-reporter/workflow.agentflow.xml +284 -0
  115. package/.speccrew/skills/speccrew-test-runner/SKILL.md +242 -241
  116. package/.speccrew/skills/speccrew-test-runner/workflow.agentflow.xml +314 -0
  117. package/bin/cli.js +8 -1
  118. package/lib/commands/validate.js +565 -0
  119. package/package.json +1 -1
  120. package/workspace-template/docs/rules/{xml-workflow-spec.md → agentflow-spec.md} +5 -5
  121. package/workspace-template/scripts/validate-agentflow.js +637 -0
  122. package/.speccrew/agents/speccrew-team-leader-xml.md +0 -480
  123. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/STATUS-FORMATS.md +0 -99
  124. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/batch-orchestrator.js +0 -176
  125. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-next-batch.js +0 -150
  126. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-pending-features.js +0 -106
  127. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/mark-stale.js +0 -249
  128. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/merge-features.js +0 -300
  129. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/process-batch-results.js +0 -915
  130. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/update-feature-status.js +0 -226
  131. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/examples/features.json +0 -34
  132. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js +0 -1071
  133. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/test-inventory.js +0 -26
  134. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/STATUS-FORMATS.md +0 -550
@@ -1,300 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * merge-features.js
4
- *
5
- * Merge incremental feature inventory (*.new.json) with existing features (*.json).
6
- * Identifies added/removed/changed/unchanged features and cleans up artifacts for removed features.
7
- *
8
- * Usage: node merge-features.js --syncStatePath <path> --completedDir <path> --projectRoot <path>
9
- */
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- function parseArgs() {
15
- const args = process.argv.slice(2);
16
- const params = {};
17
- for (let i = 0; i < args.length; i++) {
18
- if (args[i].startsWith('--')) {
19
- const key = args[i].slice(2);
20
- const value = args[i + 1];
21
- if (value !== undefined && !value.startsWith('--')) {
22
- params[key] = value;
23
- i++;
24
- } else {
25
- params[key] = true;
26
- }
27
- }
28
- }
29
- return params;
30
- }
31
-
32
- function normalizePath(p) {
33
- return p ? p.replace(/\\/g, '/') : '';
34
- }
35
-
36
- // Safely delete a file, logging the action
37
- function safeDelete(filePath, cleanedFiles) {
38
- if (fs.existsSync(filePath)) {
39
- try {
40
- fs.unlinkSync(filePath);
41
- cleanedFiles.push(normalizePath(filePath));
42
- return true;
43
- } catch (e) {
44
- console.error(`Warning: Failed to delete ${filePath}: ${e.message}`);
45
- return false;
46
- }
47
- }
48
- return false;
49
- }
50
-
51
- // Compare timestamps: returns true if sourceModified is newer than analysisCompleted
52
- function isNewer(lastModified, completedAt) {
53
- if (!completedAt) return true; // never analyzed → needs analysis
54
- if (!lastModified) return false; // no modification info → assume unchanged
55
-
56
- // lastModified is ISO format: "2026-04-07T12:30:00.000Z"
57
- // completedAt is custom format: "2026-04-07-123000" (from dispatch)
58
- // Normalize completedAt to comparable format
59
- const normalizedCompleted = normalizeCompletedAt(completedAt);
60
-
61
- const modDate = new Date(lastModified);
62
- const compDate = new Date(normalizedCompleted);
63
-
64
- // If either date is invalid, treat as changed (safer)
65
- if (isNaN(modDate.getTime()) || isNaN(compDate.getTime())) {
66
- return true;
67
- }
68
-
69
- return modDate > compDate;
70
- }
71
-
72
- // Normalize completedAt format "2026-04-07-123000" → "2026-04-07T12:30:00"
73
- function normalizeCompletedAt(completedAt) {
74
- if (!completedAt) return null;
75
-
76
- // Try ISO format first
77
- if (completedAt.includes('T')) return completedAt;
78
-
79
- // Handle "YYYY-MM-DD-HHmmss" format
80
- const match = completedAt.match(/^(\d{4}-\d{2}-\d{2})-(\d{2})(\d{2})(\d{2})$/);
81
- if (match) {
82
- return `${match[1]}T${match[2]}:${match[3]}:${match[4]}`;
83
- }
84
-
85
- return completedAt;
86
- }
87
-
88
- function main() {
89
- const params = parseArgs();
90
-
91
- const syncStatePath = params.syncStatePath;
92
- const completedDir = params.completedDir;
93
- const projectRoot = params.projectRoot;
94
-
95
- if (!syncStatePath || !completedDir || !projectRoot) {
96
- console.error('Usage: node merge-features.js --syncStatePath <path> --completedDir <path> --projectRoot <path>');
97
- process.exit(1);
98
- }
99
-
100
- const resolvedSyncState = path.resolve(syncStatePath);
101
- const resolvedCompletedDir = path.resolve(completedDir);
102
- const resolvedProjectRoot = path.resolve(projectRoot);
103
-
104
- // Scan for *.new.json files
105
- if (!fs.existsSync(resolvedSyncState)) {
106
- // Output empty result
107
- console.log(JSON.stringify({ platforms: [], totalAdded: 0, totalRemoved: 0, totalChanged: 0, totalUnchanged: 0 }));
108
- return;
109
- }
110
-
111
- const newFiles = fs.readdirSync(resolvedSyncState)
112
- .filter(f => f.startsWith('features-') && f.endsWith('.new.json'));
113
-
114
- if (newFiles.length === 0) {
115
- // No incremental files found
116
- console.log(JSON.stringify({ platforms: [], totalAdded: 0, totalRemoved: 0, totalChanged: 0, totalUnchanged: 0 }));
117
- return;
118
- }
119
-
120
- const result = {
121
- platforms: [],
122
- totalAdded: 0,
123
- totalRemoved: 0,
124
- totalChanged: 0,
125
- totalUnchanged: 0
126
- };
127
-
128
- for (const newFile of newFiles) {
129
- const newFilePath = path.join(resolvedSyncState, newFile);
130
- // features-backend-bpm.new.json → features-backend-bpm.json
131
- const oldFileName = newFile.replace('.new.json', '.json');
132
- const oldFilePath = path.join(resolvedSyncState, oldFileName);
133
-
134
- // Read new features
135
- let newData;
136
- try {
137
- newData = JSON.parse(fs.readFileSync(newFilePath, 'utf8'));
138
- } catch (e) {
139
- console.error(`Error reading ${newFile}: ${e.message}`);
140
- continue;
141
- }
142
-
143
- // Read old features (if exists)
144
- let oldData = null;
145
- if (fs.existsSync(oldFilePath)) {
146
- try {
147
- oldData = JSON.parse(fs.readFileSync(oldFilePath, 'utf8'));
148
- } catch (e) {
149
- console.error(`Warning: Failed to read ${oldFileName}, treating as fresh: ${e.message}`);
150
- }
151
- }
152
-
153
- // If no old data, just rename new → old (first-time generation)
154
- if (!oldData) {
155
- fs.renameSync(newFilePath, oldFilePath);
156
- const platformResult = {
157
- platformId: newData.platformId || oldFileName.replace('features-', '').replace('.json', ''),
158
- added: newData.features.map(f => f.fileName),
159
- removed: [],
160
- changed: [],
161
- unchanged: [],
162
- cleanedFiles: []
163
- };
164
- result.platforms.push(platformResult);
165
- result.totalAdded += platformResult.added.length;
166
- console.error(`Platform ${platformResult.platformId}: ${platformResult.added.length} features (first run)`);
167
- continue;
168
- }
169
-
170
- // Build old features map by sourcePath
171
- const oldMap = new Map();
172
- for (const feature of (oldData.features || [])) {
173
- oldMap.set(normalizePath(feature.sourcePath), feature);
174
- }
175
-
176
- // Build new features map by sourcePath
177
- const newMap = new Map();
178
- for (const feature of (newData.features || [])) {
179
- newMap.set(normalizePath(feature.sourcePath), feature);
180
- }
181
-
182
- const platformResult = {
183
- platformId: newData.platformId || oldData.platformId || oldFileName.replace('features-', '').replace('.json', ''),
184
- added: [],
185
- removed: [],
186
- changed: [],
187
- unchanged: [],
188
- cleanedFiles: []
189
- };
190
-
191
- // Merged features list
192
- const mergedFeatures = [];
193
-
194
- // Process new features
195
- for (const [sourcePath, newFeature] of newMap) {
196
- const oldFeature = oldMap.get(sourcePath);
197
-
198
- if (!oldFeature) {
199
- // Added: new feature not in old
200
- mergedFeatures.push({
201
- ...newFeature,
202
- analyzed: false,
203
- startedAt: null,
204
- completedAt: null,
205
- analysisNotes: null
206
- });
207
- platformResult.added.push(newFeature.fileName);
208
- } else if (!oldFeature.analyzed || !oldFeature.completedAt) {
209
- // Previously not analyzed → keep as not analyzed, use new metadata
210
- mergedFeatures.push({
211
- ...newFeature,
212
- analyzed: false,
213
- startedAt: oldFeature.startedAt,
214
- completedAt: oldFeature.completedAt,
215
- analysisNotes: oldFeature.analysisNotes
216
- });
217
- platformResult.changed.push(newFeature.fileName);
218
- } else if (isNewer(newFeature.lastModified, oldFeature.completedAt)) {
219
- // Changed: source modified after last analysis
220
- mergedFeatures.push({
221
- ...newFeature,
222
- analyzed: false,
223
- startedAt: null,
224
- completedAt: oldFeature.completedAt, // preserve for reference
225
- analysisNotes: `Source modified since last analysis (was: ${oldFeature.analysisNotes || 'N/A'})`
226
- });
227
- platformResult.changed.push(newFeature.fileName);
228
- } else {
229
- // Unchanged: keep old feature state entirely
230
- mergedFeatures.push({
231
- ...oldFeature,
232
- // Update metadata from new scan (in case id/documentPath changed)
233
- id: newFeature.id,
234
- documentPath: newFeature.documentPath,
235
- lastModified: newFeature.lastModified
236
- });
237
- platformResult.unchanged.push(newFeature.fileName);
238
- }
239
- }
240
-
241
- // Process removed features (in old but not in new)
242
- for (const [sourcePath, oldFeature] of oldMap) {
243
- if (!newMap.has(sourcePath)) {
244
- platformResult.removed.push(oldFeature.fileName);
245
-
246
- // Clean up artifacts
247
- // 1. Delete document .md file
248
- if (oldFeature.documentPath) {
249
- const docAbsPath = path.join(resolvedProjectRoot, oldFeature.documentPath);
250
- safeDelete(docAbsPath, platformResult.cleanedFiles);
251
- }
252
-
253
- // 2. Delete .done.json marker
254
- const donePath = path.join(resolvedCompletedDir, `${oldFeature.fileName}.done.json`);
255
- safeDelete(donePath, platformResult.cleanedFiles);
256
-
257
- // 3. Delete .graph.json marker
258
- const graphPath = path.join(resolvedCompletedDir, `${oldFeature.fileName}.graph.json`);
259
- safeDelete(graphPath, platformResult.cleanedFiles);
260
- }
261
- }
262
-
263
- // Update inventory metadata
264
- const analyzedCount = mergedFeatures.filter(f => f.analyzed).length;
265
- const mergedInventory = {
266
- ...newData,
267
- // Preserve some old metadata
268
- analysisMethod: oldData.analysisMethod || newData.analysisMethod,
269
- // Update counts
270
- totalFiles: mergedFeatures.length,
271
- analyzedCount: analyzedCount,
272
- pendingCount: mergedFeatures.length - analyzedCount,
273
- generatedAt: new Date().toISOString().replace(/[-:]/g, '').slice(0, 15).replace('T', '-'),
274
- features: mergedFeatures
275
- };
276
-
277
- // Also recalculate modules list
278
- const moduleSet = new Set(mergedFeatures.map(f => f.module));
279
- mergedInventory.modules = [...moduleSet].sort();
280
-
281
- // Write back merged features (overwrite old file)
282
- fs.writeFileSync(oldFilePath, JSON.stringify(mergedInventory, null, 2), 'utf8');
283
-
284
- // Delete .new.json file
285
- fs.unlinkSync(newFilePath);
286
-
287
- result.platforms.push(platformResult);
288
- result.totalAdded += platformResult.added.length;
289
- result.totalRemoved += platformResult.removed.length;
290
- result.totalChanged += platformResult.changed.length;
291
- result.totalUnchanged += platformResult.unchanged.length;
292
-
293
- console.error(`Platform ${platformResult.platformId}: +${platformResult.added.length} added, -${platformResult.removed.length} removed, ~${platformResult.changed.length} changed, =${platformResult.unchanged.length} unchanged`);
294
- }
295
-
296
- // Output result as JSON to stdout
297
- console.log(JSON.stringify(result, null, 2));
298
- }
299
-
300
- main();