speccrew 0.6.59 → 0.6.62
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.
|
@@ -330,11 +330,31 @@ Continue with knowledge base generation?
|
|
|
330
330
|
</block>
|
|
331
331
|
|
|
332
332
|
<block type="loop" id="S1b-L1" over="${platforms}" as="platform" parallel="true" max-concurrency="${max_concurrent_workers}" desc="Generate Feature inventory for each platform IN PARALLEL">
|
|
333
|
-
<!-- Step 1:
|
|
334
|
-
<block type="task" id="S1b-B1" action="
|
|
335
|
-
<field name="
|
|
336
|
-
<field name="
|
|
337
|
-
|
|
333
|
+
<!-- Step 1: Dispatch Worker to generate feature inventory -->
|
|
334
|
+
<block type="task" id="S1b-B1" action="dispatch-to-worker" status="pending" desc="Dispatch Worker to generate feature inventory">
|
|
335
|
+
<field name="worker">speccrew-knowledge-bizs-init-features-xml</field>
|
|
336
|
+
<field name="instructions">
|
|
337
|
+
Generate feature inventory for the specified platform by analyzing entry directories.
|
|
338
|
+
|
|
339
|
+
Requirements:
|
|
340
|
+
- Read entry-dirs JSON file to get module entry directories
|
|
341
|
+
- Scan source files in each entry directory
|
|
342
|
+
- Generate features JSON with feature metadata
|
|
343
|
+
- Output to features-{platformId}.json in sync_state_bizs_dir
|
|
344
|
+
</field>
|
|
345
|
+
<field name="context">{
|
|
346
|
+
"platformId": "${platform.platformId}",
|
|
347
|
+
"platformName": "${platform.platformName}",
|
|
348
|
+
"platformType": "${platform.platformType}",
|
|
349
|
+
"platformSubtype": "${platform.platformSubtype}",
|
|
350
|
+
"sourcePath": "${platform.sourcePath}",
|
|
351
|
+
"techIdentifier": "${platform.techIdentifier}",
|
|
352
|
+
"entryDirsFile": "${sync_state_bizs_dir}/entry-dirs-${platform.platformId}.json",
|
|
353
|
+
"outputDir": "${sync_state_bizs_dir}",
|
|
354
|
+
"workspace_path": "${workspace_path}",
|
|
355
|
+
"sync_state_bizs_dir": "${sync_state_bizs_dir}",
|
|
356
|
+
"language": "${language}"
|
|
357
|
+
}</field>
|
|
338
358
|
<field name="output" var="features_${platform.platformId}"/>
|
|
339
359
|
</block>
|
|
340
360
|
|
|
@@ -104,7 +104,7 @@ For each platform, generates:
|
|
|
104
104
|
<field name="platform_type" value="${platform.platformType}"/>
|
|
105
105
|
<field name="platform_subtype" value="${platform.platformSubtype}"/>
|
|
106
106
|
<field name="tech_stack" value="${platform.techStack}"/>
|
|
107
|
-
<field name="logic_backend" value="Find all directories containing *Controller.java or *Controller.kt files. These are API entry directories. Module name = the business package name of the entry directory"/>
|
|
107
|
+
<field name="logic_backend" value="Find all directories containing *Controller.java or *Controller.kt files. These are API entry directories. Module name = the business package name of the entry directory. CRITICAL: Group by DIRECTORY, not by individual controller files. If multiple controllers reside in the same directory, that is ONE module with that directory as entryDirs"/>
|
|
108
108
|
<field name="logic_frontend_vue_react" value="Find views/ or pages/ directories. First-level subdirectories under these directories are business modules"/>
|
|
109
109
|
<field name="logic_mobile_uniapp" value="Find first-level subdirectories under pages/. Plus top-level pages-* directories (module name = directory name without pages- prefix)"/>
|
|
110
110
|
<field name="logic_mobile_miniprogram" value="Find first-level subdirectories under pages/ as modules"/>
|
|
@@ -152,6 +152,23 @@ For each platform, generates:
|
|
|
152
152
|
<field name="output" var="generated_json_path"/>
|
|
153
153
|
</block>
|
|
154
154
|
|
|
155
|
+
<!-- Rule: Output JSON Format Validation -->
|
|
156
|
+
<block type="rule" id="R-FORMAT" scope="mandatory" desc="Output JSON format validation">
|
|
157
|
+
<field name="content">
|
|
158
|
+
The generated entry-dirs JSON file MUST strictly follow this structure:
|
|
159
|
+
- Root object MUST contain "modules" field (array type)
|
|
160
|
+
- Root object MUST NOT contain "businessModules", "subModules", or "components" fields
|
|
161
|
+
- Each module in "modules" array MUST have exactly two fields: "name" (string) and "entryDirs" (array of strings)
|
|
162
|
+
- For platforms with hierarchical directory structure (e.g. frontend views/system/user/), flatten into individual modules
|
|
163
|
+
- Module names should use hyphen-separated composite names for sub-modules (e.g. "system-user", "system-role")
|
|
164
|
+
- Multiple modules MUST NOT share the same entryDirs value. If multiple business areas share the same directory, they belong to ONE module.
|
|
165
|
+
- If the generated JSON does not match this format, you MUST regenerate it before proceeding
|
|
166
|
+
</field>
|
|
167
|
+
<field name="text">The ONLY output file from this skill is the entry-dirs JSON file specified in the output path.</field>
|
|
168
|
+
<field name="text">DO NOT generate any additional files such as reports (.md), logs, or summaries.</field>
|
|
169
|
+
<field name="text">Any extra files beyond the entry-dirs JSON are considered errors.</field>
|
|
170
|
+
</block>
|
|
171
|
+
|
|
155
172
|
<!-- Checkpoint: Persist Generated JSON -->
|
|
156
173
|
<block type="checkpoint" id="CP1" name="entry-dirs-generated" desc="Verify entry-dirs JSON was generated">
|
|
157
174
|
<field name="file" value="${sync_state_bizs_dir}/entry-dirs-${platform.platformId}.json"/>
|
|
@@ -227,6 +244,45 @@ For each platform, generates:
|
|
|
227
244
|
}
|
|
228
245
|
```
|
|
229
246
|
|
|
247
|
+
### Module Granularity (CRITICAL)
|
|
248
|
+
|
|
249
|
+
- **modules = directory-level groupings**, NOT file-level features
|
|
250
|
+
- Each module represents a distinct source directory (or set of directories) containing entry files
|
|
251
|
+
- **NEVER create multiple modules pointing to the SAME entryDirs** — if 10 controller files all reside in `module_admin/controller/`, that is ONE module named `admin` with entryDirs `["module_admin/controller"]`, NOT 10 separate modules
|
|
252
|
+
- The downstream `generate-inventory.js` script handles file-level decomposition within each module's entryDirs — that is NOT the job of this skill
|
|
253
|
+
- Module names should correspond to directory names, not individual file names
|
|
254
|
+
- Typical module count for a medium project: 3-10 modules (not 30+)
|
|
255
|
+
|
|
256
|
+
**Correct example** (directory-level):
|
|
257
|
+
```json
|
|
258
|
+
{
|
|
259
|
+
"modules": [
|
|
260
|
+
{ "name": "admin", "entryDirs": ["module_admin/controller"] },
|
|
261
|
+
{ "name": "ai", "entryDirs": ["module_ai/controller"] },
|
|
262
|
+
{ "name": "bpm", "entryDirs": ["module_bpm/controller"] }
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**WRONG example** (file-level — FORBIDDEN):
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"modules": [
|
|
271
|
+
{ "name": "system-user", "entryDirs": ["module_admin/controller"] },
|
|
272
|
+
{ "name": "system-config", "entryDirs": ["module_admin/controller"] },
|
|
273
|
+
{ "name": "system-dept", "entryDirs": ["module_admin/controller"] }
|
|
274
|
+
]
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Format Constraints
|
|
279
|
+
|
|
280
|
+
- **MUST use `modules` array** — never use `businessModules`, `components`, or any alternative field name
|
|
281
|
+
- **MUST flatten hierarchy** — if a platform has sub-modules (e.g. frontend `system/user`, `system/role`), each sub-module must be a separate top-level module entry in the `modules` array
|
|
282
|
+
- 例如:`system` 有 `user` 和 `role` 子目录 → 生成 `{ "name": "system-user", "entryDirs": ["src/views/system/user"] }` 和 `{ "name": "system-role", "entryDirs": ["src/views/system/role"] }`
|
|
283
|
+
- **Forbidden fields**: `businessModules`, `subModules`, `components`, `hasSubModules` — 这些都不被下游脚本支持
|
|
284
|
+
- **Each module's entryDirs** must point to directories containing actual entry files (e.g. .vue, .py, .java), not parent wrapper directories
|
|
285
|
+
|
|
230
286
|
### Field Definitions
|
|
231
287
|
|
|
232
288
|
- `platformId`: Platform identifier (e.g., `backend-ai`, `web-vue`, `mobile-uniapp`)
|
package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js
CHANGED
|
@@ -647,8 +647,24 @@ function main() {
|
|
|
647
647
|
console.error('Error: entryDirsFile missing required field "sourcePath"');
|
|
648
648
|
process.exit(1);
|
|
649
649
|
}
|
|
650
|
+
// Check for common format mistakes
|
|
651
|
+
if (entryDirsData.businessModules && Array.isArray(entryDirsData.businessModules)) {
|
|
652
|
+
console.error('Error: entryDirsFile uses unsupported "businessModules" format.');
|
|
653
|
+
console.error('Expected: { "modules": [ { "name": "...", "entryDirs": ["..."] } ] }');
|
|
654
|
+
console.error('Received: { "businessModules": [...] }');
|
|
655
|
+
console.error('');
|
|
656
|
+
console.error('Fix: The entry-dirs JSON must use a flat "modules" array.');
|
|
657
|
+
console.error('Each module should have "name" (string) and "entryDirs" (array of strings).');
|
|
658
|
+
console.error('Sub-modules must be flattened into top-level entries.');
|
|
659
|
+
console.error('Re-run the identify-entries skill to regenerate with correct format.');
|
|
660
|
+
process.exit(1);
|
|
661
|
+
}
|
|
662
|
+
|
|
650
663
|
if (!entryDirsData.modules || !Array.isArray(entryDirsData.modules)) {
|
|
651
|
-
console.error('Error: entryDirsFile missing required field "modules" array');
|
|
664
|
+
console.error('Error: entryDirsFile missing required field "modules" array.');
|
|
665
|
+
console.error('Expected format: { "platformId": "...", "modules": [ { "name": "...", "entryDirs": ["..."] } ] }');
|
|
666
|
+
const foundKeys = Object.keys(entryDirsData).join(', ');
|
|
667
|
+
console.error(`Found top-level keys: ${foundKeys}`);
|
|
652
668
|
process.exit(1);
|
|
653
669
|
}
|
|
654
670
|
|