speccrew 0.6.10 → 0.6.12
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.
- package/.speccrew/agents/speccrew-product-manager.md +36 -30
- package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js +7 -7
- package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/apply-module-mapping.js +1 -1
- package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/reindex-modules.js +38 -38
- package/.speccrew/skills/speccrew-pm-module-initializer/SKILL.md +83 -39
- package/lib/commands/doctor.js +7 -7
- package/lib/commands/init.js +35 -35
- package/lib/commands/list.js +8 -8
- package/lib/commands/uninstall.js +20 -20
- package/lib/commands/update.js +41 -41
- package/lib/ide-adapters.js +47 -47
- package/lib/utils.js +12 -12
- package/package.json +1 -1
- package/workspace-template/scripts/update-progress.js +148 -147
|
@@ -93,33 +93,14 @@ Use Glob to search `{iterations_dir}/*/WORKFLOW-PROGRESS.json`
|
|
|
93
93
|
- If `01_prd.status` is `confirmed`, check resume state (Step 0.2)
|
|
94
94
|
3. **If WORKFLOW-PROGRESS.json does not exist**:
|
|
95
95
|
- **MUST use script to initialize:**
|
|
96
|
+
|
|
97
|
+
> 🛑 **FORBIDDEN**: DO NOT manually create WORKFLOW-PROGRESS.json via Write/Edit tools. ALL initialization MUST be done via `update-progress.js` script.
|
|
98
|
+
|
|
96
99
|
```bash
|
|
97
100
|
node "{update_progress_script}" update-workflow \
|
|
98
|
-
--file {iterations_dir}/{
|
|
101
|
+
--file "{iterations_dir}/{iteration_name}/WORKFLOW-PROGRESS.json" \
|
|
99
102
|
--stage 01_prd --status in_progress
|
|
100
103
|
```
|
|
101
|
-
- **Fallback** (ONLY if script file does not exist):
|
|
102
|
-
Create manually with the following structure:
|
|
103
|
-
```json
|
|
104
|
-
{
|
|
105
|
-
"iteration": "{iteration-name}",
|
|
106
|
-
"current_stage": "01_prd",
|
|
107
|
-
"stages": {
|
|
108
|
-
"01_prd": {
|
|
109
|
-
"status": "in_progress",
|
|
110
|
-
"started_at": "<current-timestamp>",
|
|
111
|
-
"completed_at": null,
|
|
112
|
-
"confirmed_at": null,
|
|
113
|
-
"outputs": []
|
|
114
|
-
},
|
|
115
|
-
"02_feature_design": { "status": "pending" },
|
|
116
|
-
"03_system_design": { "status": "pending" },
|
|
117
|
-
"04_development": { "status": "pending" },
|
|
118
|
-
"05_deployment": { "status": "pending" },
|
|
119
|
-
"06_system_test": { "status": "pending" }
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
104
|
|
|
124
105
|
## Phase 0.2: Check Resume State (Checkpoint Recovery)
|
|
125
106
|
|
|
@@ -221,6 +202,7 @@ After IDE detection, compute and store all absolute paths as workflow context va
|
|
|
221
202
|
|
|
222
203
|
| Variable | Derivation | Example |
|
|
223
204
|
|----------|-----------|---------|
|
|
205
|
+
| `source_path` | Project source root (from `.speccrewrc` config or user provided) | `d:/dev/litemes` |
|
|
224
206
|
| `workspace_path` | Project root + `/speccrew-workspace` | `d:/dev/litemes/speccrew-workspace` |
|
|
225
207
|
| `sync_state_bizs_dir` | `{workspace_path}/knowledges/base/sync-state/knowledge-bizs` | `d:/dev/litemes/speccrew-workspace/knowledges/base/sync-state/knowledge-bizs` |
|
|
226
208
|
| `iterations_dir` | `{workspace_path}/iterations` | `d:/dev/litemes/speccrew-workspace/iterations` |
|
|
@@ -448,18 +430,31 @@ No knowledge base exists. A lightweight feature inventory scan is triggered to d
|
|
|
448
430
|
```
|
|
449
431
|
|
|
450
432
|
**Agent Tool Invocation for Path B Step 2 (Module Initializer)**:
|
|
433
|
+
|
|
434
|
+
> 🛑 **MANDATORY**: You MUST dispatch a separate Worker for EACH module in matched_modules.
|
|
435
|
+
> Each Worker handles ONE module on ONE platform.
|
|
436
|
+
|
|
437
|
+
For each module in matched_modules:
|
|
451
438
|
```
|
|
452
439
|
Use the Agent tool to invoke speccrew-task-worker:
|
|
453
440
|
- agent: speccrew-task-worker
|
|
454
|
-
- task: Execute speccrew-pm-module-initializer skill
|
|
441
|
+
- task: Execute speccrew-pm-module-initializer skill for module "{module.module_name}" on platform "{module.platform_id}"
|
|
455
442
|
- context:
|
|
456
443
|
skill: speccrew-pm-module-initializer
|
|
444
|
+
source_path: {source_path}
|
|
445
|
+
module_name: {module.module_name}
|
|
446
|
+
platform_id: {module.platform_id}
|
|
447
|
+
platform_type: {module.platform_type}
|
|
448
|
+
features_file: {sync_state_bizs_dir}/features-{module.platform_id}.json
|
|
449
|
+
output_path: {workspace_path}/knowledges
|
|
450
|
+
completed_dir: {sync_state_bizs_dir}/completed
|
|
451
|
+
sourceFile: features-{module.platform_id}.json
|
|
452
|
+
language: {detected user language}
|
|
457
453
|
workspace_path: {workspace_path}
|
|
458
|
-
matched_modules: <modules from matcher result>
|
|
459
|
-
sync_state_bizs_dir: {sync_state_bizs_dir}
|
|
460
|
-
ide_skills_dir: {ide_skills_dir}
|
|
461
454
|
```
|
|
462
455
|
|
|
456
|
+
Wait for ALL module-initializer Workers to complete before proceeding to Phase 2.
|
|
457
|
+
|
|
463
458
|
4. **IF feature inventory fails**:
|
|
464
459
|
- Report to user: "Project structure scan encountered issues: [specific error]. Continuing without knowledge base context."
|
|
465
460
|
- Log the error details for debugging
|
|
@@ -657,6 +652,9 @@ Clarification File: {iteration_path}/01.product-requirement/.clarification-summa
|
|
|
657
652
|
|
|
658
653
|
- **IF user confirms** (explicit "确认" or "OK"):
|
|
659
654
|
1. Update checkpoint to record user confirmation:
|
|
655
|
+
|
|
656
|
+
> 🛑 **FORBIDDEN**: DO NOT manually edit .checkpoints.json via Write/Edit tools. ALL checkpoint updates MUST be done via `update-progress.js` script.
|
|
657
|
+
|
|
660
658
|
```bash
|
|
661
659
|
node "{update_progress_script}" write-checkpoint \
|
|
662
660
|
--file {iteration_path}/01.product-requirement/.checkpoints.json \
|
|
@@ -1289,10 +1287,14 @@ After presenting the documents above, you MUST stop and ask:
|
|
|
1289
1287
|
> - If NO → Return to Phase 6.2 and wait for confirmation
|
|
1290
1288
|
> - If YES → Proceed with the steps below
|
|
1291
1289
|
|
|
1290
|
+
> 🛑 **FORBIDDEN**: DO NOT manually edit WORKFLOW-PROGRESS.json via Write/Edit tools. ALL updates to this file MUST be done via `update-progress.js` script through `run_in_terminal`.
|
|
1291
|
+
|
|
1292
1292
|
**5.3.1 Update Checkpoints**
|
|
1293
1293
|
|
|
1294
1294
|
Now update all checkpoints (user has confirmed):
|
|
1295
1295
|
|
|
1296
|
+
> 🛑 **FORBIDDEN**: DO NOT manually edit .checkpoints.json via Write/Edit tools. ALL checkpoint updates MUST be done via `update-progress.js` script.
|
|
1297
|
+
|
|
1296
1298
|
```bash
|
|
1297
1299
|
# Update verification_checklist checkpoint
|
|
1298
1300
|
node "{update_progress_script}" write-checkpoint \
|
|
@@ -1309,10 +1311,14 @@ node "{update_progress_script}" write-checkpoint \
|
|
|
1309
1311
|
|
|
1310
1312
|
**5.3.2 Update WORKFLOW-PROGRESS.json**
|
|
1311
1313
|
|
|
1314
|
+
**Update workflow status to completed:**
|
|
1315
|
+
```bash
|
|
1316
|
+
node "{update_progress_script}" update-workflow --file "{iterations_dir}/{iteration_name}/WORKFLOW-PROGRESS.json" --stage 01_prd --status completed
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
**Update workflow status to confirmed (after user confirms):**
|
|
1312
1320
|
```bash
|
|
1313
|
-
node "{update_progress_script}" update-workflow
|
|
1314
|
-
--file {iterations_dir}/{iteration}/WORKFLOW-PROGRESS.json \
|
|
1315
|
-
--stage 01_prd --status completed
|
|
1321
|
+
node "{update_progress_script}" update-workflow --file "{iterations_dir}/{iteration_name}/WORKFLOW-PROGRESS.json" --stage 01_prd --status confirmed
|
|
1316
1322
|
```
|
|
1317
1323
|
|
|
1318
1324
|
**5.3.3 Update PRD Status**
|
package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js
CHANGED
|
@@ -852,21 +852,21 @@ function main() {
|
|
|
852
852
|
}
|
|
853
853
|
}
|
|
854
854
|
|
|
855
|
-
//
|
|
856
|
-
//
|
|
857
|
-
//
|
|
858
|
-
//
|
|
855
|
+
// Use directory path to build unique ID, avoid filename collisions
|
|
856
|
+
// Example: mail/account/index.vue → mail-account-index
|
|
857
|
+
// Example: mail/template/index.vue → mail-template-index
|
|
858
|
+
// Example: dict/index.vue → dict-index (keep compatible when no nesting)
|
|
859
859
|
let dirSegments = file.directory
|
|
860
860
|
? file.directory.replace(/[\/\\]/g, '-').replace(/^-+|-+$/g, '').replace(/-+/g, '-')
|
|
861
861
|
: '';
|
|
862
862
|
|
|
863
|
-
//
|
|
863
|
+
// Top-level files (directory = ".") should not include "."
|
|
864
864
|
if (dirSegments === '.' || dirSegments === './') {
|
|
865
865
|
dirSegments = '';
|
|
866
866
|
}
|
|
867
867
|
|
|
868
|
-
//
|
|
869
|
-
//
|
|
868
|
+
// If dirSegments already contains moduleName prefix, remove to avoid duplication
|
|
869
|
+
// Example: directory='mail/account', moduleName='mail' → dirSegments='account'
|
|
870
870
|
if (moduleName && dirSegments.startsWith(moduleName + '-')) {
|
|
871
871
|
dirSegments = dirSegments.slice(moduleName.length + 1);
|
|
872
872
|
} else if (moduleName && dirSegments === moduleName) {
|
package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/apply-module-mapping.js
CHANGED
|
@@ -142,7 +142,7 @@ function main() {
|
|
|
142
142
|
reclassifiedCount++;
|
|
143
143
|
reclassifiedModules.add(oldModule);
|
|
144
144
|
|
|
145
|
-
// Rebuild documentPath
|
|
145
|
+
// Rebuild documentPath (use fileName instead of feature.id to avoid long filenames)
|
|
146
146
|
const newDocumentPath = `speccrew-workspace/knowledges/bizs/${platformId}/${newModule}/${feature.fileName}.md`;
|
|
147
147
|
|
|
148
148
|
return {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* reindex-modules.js -
|
|
3
|
+
* reindex-modules.js - Deterministic script to re-extract module names from existing features JSON with updated exclude_dirs
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Usage:
|
|
6
6
|
* node reindex-modules.js --featuresFile "path/to/features-backend-system.json" --projectRoot "d:\dev\ruoyi-vue-pro"
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* --platformType "backend" -
|
|
10
|
-
* --techIdentifier "spring" -
|
|
11
|
-
* --excludeDirs "controller,admin,api,service" -
|
|
8
|
+
* Optional parameters:
|
|
9
|
+
* --platformType "backend" - If not provided, read from features JSON's platformType field
|
|
10
|
+
* --techIdentifier "spring" - If not provided, try to infer from features JSON (e.g., techStack array)
|
|
11
|
+
* --excludeDirs "controller,admin,api,service" - If not provided, load from tech-stack-mappings.json
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
|
|
17
|
-
// ===
|
|
17
|
+
// === Utility functions (reused from generate-inventory.js) ===
|
|
18
18
|
|
|
19
19
|
function normalizePath(filePath) {
|
|
20
20
|
if (!filePath) return '';
|
|
@@ -32,7 +32,7 @@ function parseArrayParam(value) {
|
|
|
32
32
|
return trimmed.split(',').map(s => s.trim()).filter(Boolean);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// Java/Kotlin
|
|
35
|
+
// Java/Kotlin standard source path prefixes
|
|
36
36
|
const STANDARD_SOURCE_PREFIXES = [
|
|
37
37
|
'src/main/java',
|
|
38
38
|
'src/main/kotlin',
|
|
@@ -77,7 +77,7 @@ function getModuleName(dirPath, excludeDirs, fallbackModuleName) {
|
|
|
77
77
|
return '_root';
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// ===
|
|
80
|
+
// === Helper functions ===
|
|
81
81
|
|
|
82
82
|
function parseArgs(argv) {
|
|
83
83
|
const args = {};
|
|
@@ -113,10 +113,10 @@ function findProjectRoot(startPath) {
|
|
|
113
113
|
function loadExcludeDirs(projectRoot, platformType, techIdentifier, featuresData) {
|
|
114
114
|
console.log(`Loading exclude_dirs: platformType="${platformType}", techIdentifier="${techIdentifier || '(auto)'}"`);
|
|
115
115
|
|
|
116
|
-
//
|
|
116
|
+
// Try to infer techIdentifier
|
|
117
117
|
if (!techIdentifier) {
|
|
118
118
|
const techStack = featuresData.techStack || [];
|
|
119
|
-
//
|
|
119
|
+
// Common mappings
|
|
120
120
|
const techMap = {
|
|
121
121
|
'spring': 'spring', 'spring-boot': 'spring', 'java': 'spring',
|
|
122
122
|
'vue': 'vue', 'vue3': 'vue', 'vue2': 'vue',
|
|
@@ -147,7 +147,7 @@ function loadExcludeDirs(projectRoot, platformType, techIdentifier, featuresData
|
|
|
147
147
|
// Get fallback dirs for this platformType
|
|
148
148
|
const fallback = FALLBACK_EXCLUDE_DIRS[platformType] || [];
|
|
149
149
|
|
|
150
|
-
//
|
|
150
|
+
// Find tech-stack-mappings.json
|
|
151
151
|
const configPaths = [
|
|
152
152
|
path.join(projectRoot, 'speccrew-workspace', 'docs', 'configs', 'tech-stack-mappings.json'),
|
|
153
153
|
path.join(projectRoot, 'docs', 'configs', 'tech-stack-mappings.json'),
|
|
@@ -207,25 +207,25 @@ function loadExcludeDirs(projectRoot, platformType, techIdentifier, featuresData
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
function extractPlatformId(featuresData) {
|
|
210
|
-
//
|
|
211
|
-
//
|
|
210
|
+
// Extract platformId from first feature's documentPath
|
|
211
|
+
// Format: "speccrew-workspace/knowledges/bizs/{platformId}/..."
|
|
212
212
|
for (const feature of (featuresData.features || [])) {
|
|
213
213
|
if (feature.documentPath) {
|
|
214
214
|
const match = normalizePath(feature.documentPath).match(/knowledges\/bizs\/([^/]+)\//);
|
|
215
215
|
if (match) return match[1];
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
-
//
|
|
218
|
+
// If unable to extract, build from platformType-platformSubtype
|
|
219
219
|
if (featuresData.platformType && featuresData.platformSubtype) {
|
|
220
220
|
return `${featuresData.platformType}-${featuresData.platformSubtype}`;
|
|
221
221
|
}
|
|
222
222
|
return null;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
// ===
|
|
225
|
+
// === Main logic ===
|
|
226
226
|
|
|
227
227
|
function main() {
|
|
228
|
-
// 1.
|
|
228
|
+
// 1. Parse command line arguments
|
|
229
229
|
const args = parseArgs(process.argv.slice(2));
|
|
230
230
|
const featuresFile = args.featuresFile;
|
|
231
231
|
|
|
@@ -234,7 +234,7 @@ function main() {
|
|
|
234
234
|
process.exit(1);
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
// 2.
|
|
237
|
+
// 2. Read features JSON
|
|
238
238
|
let featuresData;
|
|
239
239
|
try {
|
|
240
240
|
featuresData = JSON.parse(fs.readFileSync(featuresFile, 'utf8'));
|
|
@@ -250,16 +250,16 @@ function main() {
|
|
|
250
250
|
const inventorySourcePath = normalizePath(featuresData.sourcePath || '');
|
|
251
251
|
const platformType = args.platformType || featuresData.platformType || '';
|
|
252
252
|
|
|
253
|
-
// 3.
|
|
253
|
+
// 3. Load exclude_dirs
|
|
254
254
|
let excludeDirs = [];
|
|
255
255
|
let stripModulePrefixes = [];
|
|
256
256
|
if (args.excludeDirs) {
|
|
257
257
|
excludeDirs = parseArrayParam(args.excludeDirs);
|
|
258
258
|
} else {
|
|
259
|
-
//
|
|
260
|
-
// 1.
|
|
261
|
-
// 2. features JSON
|
|
262
|
-
// 3. features JSON
|
|
259
|
+
// Load from tech-stack-mappings.json, determine techIdentifier by priority:
|
|
260
|
+
// 1. Command line parameter --techIdentifier
|
|
261
|
+
// 2. techIdentifier in features JSON
|
|
262
|
+
// 3. platformSubtype in features JSON (backward compatibility)
|
|
263
263
|
const techId = args.techIdentifier || featuresData.techIdentifier || featuresData.platformSubtype;
|
|
264
264
|
const config = loadExcludeDirs(projectRoot, platformType, techId, featuresData);
|
|
265
265
|
excludeDirs = config.excludeDirs;
|
|
@@ -274,29 +274,29 @@ function main() {
|
|
|
274
274
|
console.log(`Exclude dirs (${excludeDirs.length}): ${excludeDirs.join(', ')}`);
|
|
275
275
|
console.log(`Total features: ${featuresData.features.length}`);
|
|
276
276
|
|
|
277
|
-
// 4.
|
|
277
|
+
// 4. Recalculate module for each feature
|
|
278
278
|
const modulesBefore = [...new Set(featuresData.features.map(f => f.module))].sort();
|
|
279
279
|
let reclassifiedCount = 0;
|
|
280
280
|
|
|
281
|
-
//
|
|
282
|
-
// platformId
|
|
283
|
-
//
|
|
281
|
+
// Get platformId from features JSON (for rebuilding documentPath)
|
|
282
|
+
// platformId format: "{platformType}-{platformSubtype}"
|
|
283
|
+
// Extract from existing documentPath: "speccrew-workspace/knowledges/bizs/{platformId}/..."
|
|
284
284
|
const platformId = extractPlatformId(featuresData);
|
|
285
285
|
|
|
286
286
|
featuresData.features.forEach(feature => {
|
|
287
|
-
//
|
|
287
|
+
// Calculate feature source file path relative to inventorySourcePath
|
|
288
288
|
let relativePath = normalizePath(feature.sourcePath || '');
|
|
289
289
|
|
|
290
|
-
//
|
|
290
|
+
// If feature.sourcePath is absolute or relative to project root, remove inventorySourcePath prefix
|
|
291
291
|
if (inventorySourcePath && relativePath.startsWith(inventorySourcePath)) {
|
|
292
292
|
relativePath = relativePath.slice(inventorySourcePath.length);
|
|
293
293
|
if (relativePath.startsWith('/')) relativePath = relativePath.slice(1);
|
|
294
294
|
}
|
|
295
|
-
//
|
|
295
|
+
// inventorySourcePath may only partially match
|
|
296
296
|
else if (inventorySourcePath) {
|
|
297
297
|
const invParts = inventorySourcePath.split('/');
|
|
298
298
|
const relParts = relativePath.split('/');
|
|
299
|
-
//
|
|
299
|
+
// Find overlapping part
|
|
300
300
|
let startIdx = 0;
|
|
301
301
|
for (let i = 0; i < relParts.length; i++) {
|
|
302
302
|
if (relParts.slice(i, i + invParts.length).join('/') === inventorySourcePath) {
|
|
@@ -309,14 +309,14 @@ function main() {
|
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
-
//
|
|
312
|
+
// Get directory part (remove filename)
|
|
313
313
|
const dirPath = path.dirname(relativePath).replace(/\\/g, '/');
|
|
314
314
|
|
|
315
|
-
//
|
|
315
|
+
// Re-extract module name using getModuleName
|
|
316
316
|
const fallback = feature.module || '_root';
|
|
317
317
|
let newModule = getModuleName(dirPath, excludeDirs, fallback);
|
|
318
318
|
|
|
319
|
-
//
|
|
319
|
+
// Apply strip_module_prefixes prefix removal
|
|
320
320
|
for (const prefix of stripModulePrefixes) {
|
|
321
321
|
if (newModule.startsWith(prefix)) {
|
|
322
322
|
newModule = newModule.substring(prefix.length);
|
|
@@ -328,21 +328,21 @@ function main() {
|
|
|
328
328
|
reclassifiedCount++;
|
|
329
329
|
feature.module = newModule;
|
|
330
330
|
|
|
331
|
-
//
|
|
331
|
+
// Rebuild documentPath (use fileName instead of feature.id to avoid long filenames)
|
|
332
332
|
if (platformId) {
|
|
333
333
|
feature.documentPath = `speccrew-workspace/knowledges/bizs/${platformId}/${newModule}/${feature.fileName}.md`;
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
});
|
|
337
337
|
|
|
338
|
-
// 5.
|
|
338
|
+
// 5. Update modules array
|
|
339
339
|
const modulesAfter = [...new Set(featuresData.features.map(f => f.module))].sort();
|
|
340
340
|
featuresData.modules = modulesAfter;
|
|
341
341
|
|
|
342
|
-
// 6.
|
|
342
|
+
// 6. Write back to file
|
|
343
343
|
fs.writeFileSync(featuresFile, JSON.stringify(featuresData, null, 2), 'utf8');
|
|
344
344
|
|
|
345
|
-
// 7.
|
|
345
|
+
// 7. Output results
|
|
346
346
|
const result = {
|
|
347
347
|
status: 'success',
|
|
348
348
|
modules_before: modulesBefore,
|
|
@@ -8,11 +8,14 @@ tools: Read, Write, Skill, Bash
|
|
|
8
8
|
|
|
9
9
|
Initialize knowledge base for a single business module by analyzing its features. Dispatches api-analyze or ui-analyze based on platform type, then generates module summary. Used by Worker Agent, invoked by PM Agent for on-demand module initialization.
|
|
10
10
|
|
|
11
|
+
> **Positioning**: Lightweight knowledge base initializer for PM phase, processes only modules matched by PM matcher.
|
|
12
|
+
> Difference from bizs-dispatch: module-initializer processes single modules on-demand, does not generate graph data, output is for PRD authoring reference only.
|
|
13
|
+
|
|
11
14
|
## Language Adaptation
|
|
12
15
|
|
|
13
16
|
**CRITICAL**: Generate all content in the language specified by the `language` parameter.
|
|
14
17
|
|
|
15
|
-
- `language: "zh"` → Generate all content in
|
|
18
|
+
- `language: "zh"` → Generate all content in Chinese
|
|
16
19
|
- `language: "en"` → Generate all content in English
|
|
17
20
|
- Other languages → Use the specified language
|
|
18
21
|
|
|
@@ -29,15 +32,17 @@ Initialize knowledge base for a single business module by analyzing its features
|
|
|
29
32
|
|
|
30
33
|
| Parameter | Type | Required | Description |
|
|
31
34
|
|-----------|------|----------|-------------|
|
|
32
|
-
| `source_path` | string | Yes |
|
|
33
|
-
| `module_name` | string | Yes |
|
|
34
|
-
| `platform_id` | string | Yes |
|
|
35
|
+
| `source_path` | string | Yes | Project source code root path |
|
|
36
|
+
| `module_name` | string | Yes | Module name |
|
|
37
|
+
| `platform_id` | string | Yes | Platform ID (e.g., "web-vue3", "admin-api") |
|
|
35
38
|
| `platform_type` | string | Yes | web / mobile / backend / desktop |
|
|
36
39
|
| `platform_subtype` | string | No | Platform subtype (e.g., "vue", "spring-boot") |
|
|
37
40
|
| `tech_stack` | array | No | Platform tech stack (e.g., ["java", "spring-boot"]) |
|
|
38
|
-
| `features_file` | string | Yes |
|
|
39
|
-
| `output_path` | string | Yes |
|
|
40
|
-
| `
|
|
41
|
+
| `features_file` | string | Yes | Path to the platform's features-{platform}.json file |
|
|
42
|
+
| `output_path` | string | Yes | Knowledge base output root path (e.g., speccrew-workspace/knowledges) |
|
|
43
|
+
| `completed_dir` | string | Yes | Marker file output directory for api-analyze .done.json markers. Value from PM Agent: `{sync_state_bizs_dir}/completed` |
|
|
44
|
+
| `sourceFile` | string | Yes | Features JSON filename (e.g., "features-backend-system.json"), used for api-analyze marking |
|
|
45
|
+
| `language` | string | Yes | Output language (zh / en) |
|
|
41
46
|
|
|
42
47
|
## Output JSON
|
|
43
48
|
|
|
@@ -100,38 +105,67 @@ Based on `platform_type`, select the appropriate analyzer Skill:
|
|
|
100
105
|
|
|
101
106
|
**Output**: "Step 2 Status: ✅ COMPLETED - Selected analyzer: {skill_name}"
|
|
102
107
|
|
|
103
|
-
### Step 3: Analyze Each Pending Feature
|
|
108
|
+
### Step 3: Analyze Each Pending Feature (Sequential)
|
|
104
109
|
|
|
105
110
|
**Step 3 Status: 🔄 IN PROGRESS**
|
|
106
111
|
|
|
107
|
-
For each pending feature,
|
|
112
|
+
For each pending feature from Step 1, call the appropriate analyzer skill.
|
|
113
|
+
|
|
114
|
+
> 🛑 **FORBIDDEN**: DO NOT write custom scripts. You MUST call the analyzer skill directly using the Agent tool or execute it as defined in the skill's SKILL.md.
|
|
108
115
|
|
|
109
|
-
|
|
116
|
+
#### For backend modules (api-analyze):
|
|
110
117
|
|
|
111
|
-
|
|
118
|
+
For each pending feature, invoke the `speccrew-knowledge-bizs-api-analyze` skill with these parameters:
|
|
112
119
|
|
|
113
|
-
|
|
120
|
+
```
|
|
121
|
+
Use Agent tool to invoke speccrew-task-worker:
|
|
122
|
+
- agent: speccrew-task-worker
|
|
123
|
+
- task: Execute speccrew-knowledge-bizs-api-analyze skill
|
|
124
|
+
- context:
|
|
125
|
+
skill: speccrew-knowledge-bizs-api-analyze
|
|
126
|
+
fileName: {feature.fileName}
|
|
127
|
+
sourcePath: {source_path}/{feature.sourcePath}
|
|
128
|
+
documentPath: {output_path}/bizs/{platform_id}/{feature.module}/features
|
|
129
|
+
module: {feature.module}
|
|
130
|
+
analyzed: false
|
|
131
|
+
platform_type: backend
|
|
132
|
+
platform_subtype: {platform_subtype}
|
|
133
|
+
tech_stack: {tech_stack}
|
|
134
|
+
language: {language}
|
|
135
|
+
completed_dir: {completed_dir}
|
|
136
|
+
sourceFile: {sourceFile}
|
|
137
|
+
```
|
|
114
138
|
|
|
115
|
-
|
|
116
|
-
|----------|--------------|
|
|
117
|
-
| `feature` | The complete feature object from features.json |
|
|
118
|
-
| `fileName` | feature's fileName field |
|
|
119
|
-
| `sourcePath` | feature's sourcePath field |
|
|
120
|
-
| `documentPath` | Computed as `{output_path}/bizs/{platform_id}/{module_name}/{fileName}.md` |
|
|
121
|
-
| `module` | module_name |
|
|
122
|
-
| `analyzed` | false |
|
|
123
|
-
| `platform_type` | From input |
|
|
124
|
-
| `platform_subtype` | From input (if available) |
|
|
125
|
-
| `tech_stack` | From input (if available) |
|
|
126
|
-
| `language` | From input |
|
|
127
|
-
| `completed_dir` | `{output_path}/base/sync-state/knowledge-bizs/completed/` |
|
|
128
|
-
| `sourceFile` | Features JSON filename (e.g., "features-web-vue3.json") |
|
|
139
|
+
#### For web/mobile/desktop modules (ui-analyze):
|
|
129
140
|
|
|
130
|
-
|
|
141
|
+
For each pending feature, invoke the `speccrew-knowledge-bizs-ui-analyze` skill with these parameters:
|
|
131
142
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
143
|
+
```
|
|
144
|
+
Use Agent tool to invoke speccrew-task-worker:
|
|
145
|
+
- agent: speccrew-task-worker
|
|
146
|
+
- task: Execute speccrew-knowledge-bizs-ui-analyze skill
|
|
147
|
+
- context:
|
|
148
|
+
skill: speccrew-knowledge-bizs-ui-analyze
|
|
149
|
+
fileName: {feature.fileName}
|
|
150
|
+
sourcePath: {source_path}/{feature.sourcePath}
|
|
151
|
+
documentPath: {output_path}/bizs/{platform_id}/{feature.module}/features
|
|
152
|
+
module: {feature.module}
|
|
153
|
+
analyzed: false
|
|
154
|
+
platform_type: {platform_type}
|
|
155
|
+
platform_subtype: {platform_subtype}
|
|
156
|
+
tech_stack: {tech_stack}
|
|
157
|
+
language: {language}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
> **NOTE**: UI Analyzer does NOT write .done.json marker files (handled by ui-graph skill in bizs-dispatch).
|
|
161
|
+
|
|
162
|
+
#### After each successful analysis:
|
|
163
|
+
Update the feature's `analyzed` field to `true` in the features JSON file.
|
|
164
|
+
|
|
165
|
+
#### Error handling:
|
|
166
|
+
- If an analyzer fails, log the error, increment `features_failed` counter
|
|
167
|
+
- Continue with next feature (do NOT abort the entire module)
|
|
168
|
+
- A module with partial analysis is better than no analysis
|
|
135
169
|
|
|
136
170
|
**Output**: "Step 3 Status: ✅ COMPLETED - Analyzed {success} features, {failed} failed"
|
|
137
171
|
|
|
@@ -139,15 +173,25 @@ Prepare input variables matching the analyzer Skill's Input Variables format:
|
|
|
139
173
|
|
|
140
174
|
**Step 4 Status: 🔄 IN PROGRESS**
|
|
141
175
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
176
|
+
**Pre-check**: Verify that feature documents exist at `{output_path}/bizs/{platform_id}/{module_name}/features/`.
|
|
177
|
+
|
|
178
|
+
IF no feature documents exist AND features_analyzed == 0:
|
|
179
|
+
- Set status to "partial"
|
|
180
|
+
- Skip module-summarize
|
|
181
|
+
- Proceed to Step 5
|
|
182
|
+
|
|
183
|
+
IF feature documents exist:
|
|
184
|
+
Invoke `speccrew-knowledge-module-summarize` skill:
|
|
185
|
+
```
|
|
186
|
+
Use Agent tool to invoke speccrew-task-worker:
|
|
187
|
+
- agent: speccrew-task-worker
|
|
188
|
+
- task: Execute speccrew-knowledge-module-summarize skill
|
|
189
|
+
- context:
|
|
190
|
+
skill: speccrew-knowledge-module-summarize
|
|
191
|
+
module_name: {module_name}
|
|
192
|
+
module_path: {output_path}/bizs/{platform_id}/{module_name}
|
|
193
|
+
language: {language}
|
|
194
|
+
```
|
|
151
195
|
|
|
152
196
|
**Output**: "Step 4 Status: ✅ COMPLETED - Module overview generated at {module_path}/{module_name}-overview.md"
|
|
153
197
|
|
package/lib/commands/doctor.js
CHANGED
|
@@ -8,7 +8,7 @@ function run(projectRoot, args) {
|
|
|
8
8
|
|
|
9
9
|
const results = [];
|
|
10
10
|
|
|
11
|
-
// 1. Node.js
|
|
11
|
+
// 1. Node.js version check
|
|
12
12
|
const nodeVersion = process.version;
|
|
13
13
|
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0], 10);
|
|
14
14
|
if (majorVersion >= 16) {
|
|
@@ -17,7 +17,7 @@ function run(projectRoot, args) {
|
|
|
17
17
|
results.push({ status: 'FAIL', message: `Node.js ${nodeVersion} (< 16.0.0)` });
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// 2. SpecCrew
|
|
20
|
+
// 2. SpecCrew installation status
|
|
21
21
|
const rc = readSpeccrewRC(projectRoot);
|
|
22
22
|
const version = getPackageVersion();
|
|
23
23
|
if (rc) {
|
|
@@ -26,7 +26,7 @@ function run(projectRoot, args) {
|
|
|
26
26
|
results.push({ status: 'WARN', message: 'Not initialized, run speccrew init' });
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
// 3. IDE
|
|
29
|
+
// 3. IDE directory check
|
|
30
30
|
const detectedIDEs = detectIDE(projectRoot);
|
|
31
31
|
if (detectedIDEs.length > 0) {
|
|
32
32
|
const ideNames = detectedIDEs.map(ide => `${ide.name} (${ide.baseDir}/)`).join(', ');
|
|
@@ -35,7 +35,7 @@ function run(projectRoot, args) {
|
|
|
35
35
|
results.push({ status: 'WARN', message: 'No supported IDE detected' });
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// 4. Agents
|
|
38
|
+
// 4. Agents integrity check
|
|
39
39
|
const sourceRoot = getSourceRoot();
|
|
40
40
|
const sourceAgentsDir = path.join(sourceRoot, 'agents');
|
|
41
41
|
let sourceAgentCount = 0;
|
|
@@ -70,7 +70,7 @@ function run(projectRoot, args) {
|
|
|
70
70
|
results.push({ status: 'WARN', message: 'Agents: source not found' });
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
// 5. Skills
|
|
73
|
+
// 5. Skills integrity check
|
|
74
74
|
const sourceSkillsDir = path.join(sourceRoot, 'skills');
|
|
75
75
|
let sourceSkillCount = 0;
|
|
76
76
|
let installedSkillCount = 0;
|
|
@@ -103,7 +103,7 @@ function run(projectRoot, args) {
|
|
|
103
103
|
results.push({ status: 'WARN', message: 'Skills: source not found' });
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
// 6. Workspace
|
|
106
|
+
// 6. Workspace directory check
|
|
107
107
|
const workspaceDir = path.join(projectRoot, 'speccrew-workspace');
|
|
108
108
|
const docsDir = path.join(workspaceDir, 'docs');
|
|
109
109
|
if (fs.existsSync(workspaceDir) && fs.existsSync(docsDir)) {
|
|
@@ -114,7 +114,7 @@ function run(projectRoot, args) {
|
|
|
114
114
|
results.push({ status: 'WARN', message: 'Workspace: speccrew-workspace/ not found' });
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
//
|
|
117
|
+
// Output results
|
|
118
118
|
let passCount = 0;
|
|
119
119
|
let warnCount = 0;
|
|
120
120
|
let failCount = 0;
|