speccrew 0.6.62 → 0.6.64

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.
@@ -104,10 +104,11 @@ 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. 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
- <field name="logic_frontend_vue_react" value="Find views/ or pages/ directories. First-level subdirectories under these directories are business modules"/>
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
- <field name="logic_mobile_miniprogram" value="Find first-level subdirectories under pages/ as modules"/>
107
+ <field name="logic_module_scan" value="Read tech-stack-mappings.json for the techStack's module_scan configuration. Use module_scan.root as the scan starting point and module_scan.depth as the grouping level (depth=1 means first-level subdirectories = one module each)"/>
108
+ <field name="logic_backend" value="Find all directories containing *Controller.java or *Controller.kt files under module_scan.root. These are API entry directories. Module name = the business package name of the entry directory. Apply module_scan.depth for grouping level"/>
109
+ <field name="logic_frontend_vue_react" value="Find directories under module_scan.root (e.g., src/views or src/pages). First-level subdirectories under module_scan.root are business modules when depth=1"/>
110
+ <field name="logic_mobile_uniapp" value="Find first-level subdirectories under module_scan.root (e.g., src/pages). Plus top-level pages-* directories (module name = directory name without pages- prefix)"/>
111
+ <field name="logic_mobile_miniprogram" value="Find first-level subdirectories under module_scan.root (e.g., pages) as modules"/>
111
112
  <field name="output" var="identified_entries"/>
112
113
  </block>
113
114
 
@@ -164,9 +165,7 @@ For each platform, generates:
164
165
  - Multiple modules MUST NOT share the same entryDirs value. If multiple business areas share the same directory, they belong to ONE module.
165
166
  - If the generated JSON does not match this format, you MUST regenerate it before proceeding
166
167
  </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>
168
+ <field name="text">Output is strictly the entry-dirs JSON file at the specified output path. Per xml-workflow-spec.md "Strict Block Adherence" rule, no extra files are permitted.</field>
170
169
  </block>
171
170
 
172
171
  <!-- Checkpoint: Persist Generated JSON -->
@@ -246,20 +245,30 @@ For each platform, generates:
246
245
 
247
246
  ### Module Granularity (CRITICAL)
248
247
 
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
248
+ **Core Principle**: modules = directory-level groupings, NOT file-level features
249
+
250
+ **Configuration-Driven Approach**:
251
+ 1. Read `tech-stack-mappings.json` to get the `module_scan` configuration for the detected `techStack`
252
+ 2. Use `module_scan.root` as the scanning starting point (e.g., `src/views` for vue, `controller` for spring)
253
+ 3. Use `module_scan.depth` as the grouping level:
254
+ - `depth=1`: Each first-level subdirectory under `module_scan.root` = ONE module
255
+ - `depth=2`: Each second-level subdirectory = ONE module (e.g., for android)
256
+ 4. Each module represents a distinct source directory containing entry files
257
+
258
+ **NEVER create multiple modules pointing to the SAME entryDirs** — if 10 controller files all reside in the same directory, that is ONE module with that directory as entryDirs, NOT 10 separate modules
259
+
260
+ **Key Rules**:
252
261
  - The downstream `generate-inventory.js` script handles file-level decomposition within each module's entryDirs — that is NOT the job of this skill
253
262
  - Module names should correspond to directory names, not individual file names
254
263
  - Typical module count for a medium project: 3-10 modules (not 30+)
255
264
 
256
- **Correct example** (directory-level):
265
+ **Correct example** (directory-level, vue with module_scan.root="src/views", depth=1):
257
266
  ```json
258
267
  {
259
268
  "modules": [
260
- { "name": "admin", "entryDirs": ["module_admin/controller"] },
261
- { "name": "ai", "entryDirs": ["module_ai/controller"] },
262
- { "name": "bpm", "entryDirs": ["module_bpm/controller"] }
269
+ { "name": "ai", "entryDirs": ["src/views/ai"] },
270
+ { "name": "bpm", "entryDirs": ["src/views/bpm"] },
271
+ { "name": "system", "entryDirs": ["src/views/system"] }
263
272
  ]
264
273
  }
265
274
  ```
@@ -268,9 +277,9 @@ For each platform, generates:
268
277
  ```json
269
278
  {
270
279
  "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"] }
280
+ { "name": "system-user", "entryDirs": ["src/views/system"] },
281
+ { "name": "system-role", "entryDirs": ["src/views/system"] },
282
+ { "name": "system-dept", "entryDirs": ["src/views/system"] }
274
283
  ]
275
284
  }
276
285
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speccrew",
3
- "version": "0.6.62",
3
+ "version": "0.6.64",
4
4
  "description": "Spec-Driven Development toolkit for AI-powered IDEs",
5
5
  "author": "charlesmu99",
6
6
  "repository": {
@@ -18,6 +18,7 @@
18
18
  "extensions": [".tsx", ".ts", ".jsx", ".js"],
19
19
  "exclude_dirs": ["components", "hooks", "lib", "utils", "contexts", "hocs", "views", "pages", "api", "layout", "layouts", "assets", "store", "stores", "router", "routes", "plugins", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
20
20
  "entry_patterns": ["src/pages/**/*.{tsx,jsx}", "src/components/**/*.{tsx,jsx}"],
21
+ "module_scan": { "root": "src/pages", "depth": 1 },
21
22
  "api_call_patterns": ["fetch(", "axios.", "apiClient.", "useQuery", "useMutation"],
22
23
  "state_management": ["useState", "useReducer", "Redux", "Zustand", "MobX"],
23
24
  "routing": ["react-router", "next/router"],
@@ -27,6 +28,7 @@
27
28
  "extensions": [".vue", ".ts", ".js"],
28
29
  "exclude_dirs": ["components", "composables", "hooks", "utils", "mixins", "directives", "views", "pages", "api", "layout", "layouts", "assets", "store", "stores", "router", "routes", "plugins", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
29
30
  "entry_patterns": ["src/views/**/*.vue", "src/components/**/*.vue", "pages/**/*.vue"],
31
+ "module_scan": { "root": "src/views", "depth": 1 },
30
32
  "api_call_patterns": ["axios.", "fetch(", "$http", "useFetch"],
31
33
  "state_management": ["Pinia", "Vuex", "ref", "reactive", "computed"],
32
34
  "routing": ["vue-router"],
@@ -36,6 +38,7 @@
36
38
  "extensions": [".ts", ".html", ".scss", ".css"],
37
39
  "exclude_dirs": ["components", "directives", "pipes", "guards", "interceptors", "services", "views", "pages", "api", "layout", "layouts", "assets", "store", "stores", "router", "routes", "plugins", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
38
40
  "entry_patterns": ["src/app/components/**/*.ts", "src/app/pages/**/*.ts"],
41
+ "module_scan": { "root": "src/app", "depth": 1 },
39
42
  "api_call_patterns": ["HttpClient", "http.get", "http.post"],
40
43
  "state_management": ["RxJS", "NgRx", "BehaviorSubject", "Observable"],
41
44
  "routing": ["@angular/router"],
@@ -45,6 +48,7 @@
45
48
  "extensions": [".tsx", ".ts", ".jsx", ".js"],
46
49
  "exclude_dirs": ["components", "hooks", "lib", "utils", "contexts", "api", "views", "pages", "layout", "layouts", "assets", "store", "stores", "router", "routes", "plugins", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
47
50
  "entry_patterns": ["app/**/*.{tsx,jsx}", "pages/**/*.{tsx,jsx}"],
51
+ "module_scan": { "root": "app", "depth": 1 },
48
52
  "api_call_patterns": ["fetch(", "axios.", "useSWR", "React Query"],
49
53
  "state_management": ["useState", "Zustand", "Redux", "Context API"],
50
54
  "routing": ["file-system routing", "next/navigation"],
@@ -54,6 +58,7 @@
54
58
  "extensions": [".vue", ".ts", ".js"],
55
59
  "exclude_dirs": ["components", "composables", "utils", "plugins", "middleware", "views", "pages", "api", "layout", "layouts", "assets", "store", "stores", "router", "routes", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
56
60
  "entry_patterns": ["pages/**/*.vue", "components/**/*.vue"],
61
+ "module_scan": { "root": "pages", "depth": 1 },
57
62
  "api_call_patterns": ["$fetch", "useFetch", "axios."],
58
63
  "state_management": ["Pinia", "useState", "composables"],
59
64
  "routing": ["file-system routing", "vue-router"],
@@ -63,6 +68,7 @@
63
68
  "extensions": [".svelte", ".ts", ".js"],
64
69
  "exclude_dirs": ["components", "lib", "utils", "stores", "actions", "views", "pages", "api", "layout", "layouts", "assets", "store", "router", "routes", "plugins", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
65
70
  "entry_patterns": ["src/**/*.svelte", "routes/**/*.svelte"],
71
+ "module_scan": { "root": "src/routes", "depth": 1 },
66
72
  "api_call_patterns": ["fetch(", "axios."],
67
73
  "state_management": ["writable", "readable", "derived", "Svelte Store"],
68
74
  "routing": ["svelte-routing", "file-system routing"],
@@ -74,6 +80,7 @@
74
80
  "extensions": [".dart"],
75
81
  "exclude_dirs": ["widgets", "components", "utils", "helpers", "models", "services"],
76
82
  "entry_patterns": ["lib/**/*.dart", "lib/pages/**/*.dart", "lib/screens/**/*.dart"],
83
+ "module_scan": { "root": "lib/pages", "depth": 1 },
77
84
  "api_call_patterns": ["http.", "dio.", "Dio()", "get(", "post("],
78
85
  "state_management": ["Provider", "Riverpod", "Bloc", "GetX", "MobX"],
79
86
  "routing": ["Navigator", "GoRouter", "Get.to"],
@@ -83,6 +90,7 @@
83
90
  "extensions": [".tsx", ".ts", ".jsx", ".js"],
84
91
  "exclude_dirs": ["components", "hooks", "utils", "contexts", "navigations", "views", "pages", "api", "screens", "assets", "store", "stores", "router", "routes", "plugins", "styles", "types", "typings", "locales", "i18n", "lang", "config", "configs"],
85
92
  "entry_patterns": ["src/screens/**/*.{tsx,jsx}", "src/components/**/*.{tsx,jsx}"],
93
+ "module_scan": { "root": "src/screens", "depth": 1 },
86
94
  "api_call_patterns": ["fetch(", "axios.", "apiClient."],
87
95
  "state_management": ["useState", "Redux", "MobX", "Zustand", "Recoil"],
88
96
  "routing": ["react-navigation", "expo-router"],
@@ -94,6 +102,7 @@
94
102
  "exclude_file_suffixes": [],
95
103
  "strip_module_prefixes": ["pages-"],
96
104
  "entry_patterns": ["pages/**/*.vue", "components/**/*.vue"],
105
+ "module_scan": { "root": "src/pages", "depth": 1 },
97
106
  "api_call_patterns": ["uni.request", "uni.uploadFile", "uni.downloadFile"],
98
107
  "state_management": ["Vuex", "Pinia", "globalData"],
99
108
  "routing": ["pages.json", "uni.navigateTo"],
@@ -102,6 +111,7 @@
102
111
  "android": {
103
112
  "extensions": [".kt", ".java", ".xml"],
104
113
  "entry_patterns": ["app/src/main/java/**/*.kt", "app/src/main/java/**/*.java"],
114
+ "module_scan": { "root": "app/src/main/java", "depth": 2 },
105
115
  "api_call_patterns": ["Retrofit", "OkHttp", "HttpURLConnection"],
106
116
  "state_management": ["ViewModel", "LiveData", "StateFlow", "Compose State"],
107
117
  "routing": ["Intent", "Navigation Component", "Jetpack Navigation"],
@@ -110,6 +120,7 @@
110
120
  "ios": {
111
121
  "extensions": [".swift", ".m", ".h", ".storyboard"],
112
122
  "entry_patterns": ["**/*.swift", "ViewControllers/**/*.swift"],
123
+ "module_scan": { "root": "ViewControllers", "depth": 1 },
113
124
  "api_call_patterns": ["URLSession", "Alamofire", "AF.request"],
114
125
  "state_management": ["@State", "@ObservedObject", "@StateObject", "Combine"],
115
126
  "routing": ["NavigationView", "TabView", "UIStoryboardSegue"],
@@ -121,6 +132,7 @@
121
132
  "exclude_file_suffixes": [],
122
133
  "strip_module_prefixes": ["pages-"],
123
134
  "entry_patterns": ["pages/**/*.js", "pages/**/*.ts", "components/**/*.js"],
135
+ "module_scan": { "root": "pages", "depth": 1 },
124
136
  "api_call_patterns": ["wx.request", "wx.uploadFile", "wx.downloadFile"],
125
137
  "state_management": ["Page data", "globalData", "MobX", "Westore"],
126
138
  "routing": ["app.json pages", "wx.navigateTo", "wx.redirectTo"],
@@ -134,6 +146,7 @@
134
146
  "exclude_file_suffixes": ["VO", "DTO", "DO", "Entity", "Convert", "Converter"],
135
147
  "exclude_file_names": ["package-info"],
136
148
  "entry_patterns": ["**/*Controller.java", "**/*Controller.kt", "**/*Service.java"],
149
+ "module_scan": { "root": "controller", "depth": 1 },
137
150
  "api_patterns": {
138
151
  "controller": ["@Controller", "@RestController", "@RequestMapping"],
139
152
  "methods": ["@GetMapping", "@PostMapping", "@PutMapping", "@DeleteMapping", "@PatchMapping"],
@@ -148,6 +161,7 @@
148
161
  "exclude_dirs": ["services", "repositories", "entities", "dtos", "guards", "interceptors", "middleware", "pipes", "filters", "decorators", "utils", "helpers"],
149
162
  "exclude_file_suffixes": [],
150
163
  "entry_patterns": ["**/*.controller.ts", "**/*.service.ts", "**/*.module.ts"],
164
+ "module_scan": { "root": "src/modules", "depth": 1 },
151
165
  "api_patterns": {
152
166
  "controller": ["@Controller"],
153
167
  "methods": ["@Get", "@Post", "@Put", "@Delete", "@Patch", "@Query", "@Param", "@Body"],
@@ -162,6 +176,7 @@
162
176
  "exclude_dirs": ["services", "models", "middleware", "utils", "helpers", "validators", "schemas"],
163
177
  "exclude_file_suffixes": [],
164
178
  "entry_patterns": ["routes/**/*.js", "controllers/**/*.js", "**/*.routes.ts"],
179
+ "module_scan": { "root": "routes", "depth": 1 },
165
180
  "api_patterns": {
166
181
  "router": ["router.get", "router.post", "router.put", "router.delete", "router.patch"],
167
182
  "app": ["app.get", "app.post", "app.use"],
@@ -176,6 +191,7 @@
176
191
  "exclude_dirs": ["services", "models", "schemas", "plugins", "hooks", "utils", "helpers"],
177
192
  "exclude_file_suffixes": [],
178
193
  "entry_patterns": ["routes/**/*.js", "**/*.routes.ts"],
194
+ "module_scan": { "root": "routes", "depth": 1 },
179
195
  "api_patterns": {
180
196
  "routes": ["fastify.get", "fastify.post", "fastify.route"],
181
197
  "schema": ["schema:", "body:", "querystring:", "params:"]
@@ -189,6 +205,7 @@
189
205
  "exclude_dirs": ["models", "serializers", "forms", "utils", "helpers", "middleware", "templatetags"],
190
206
  "exclude_file_suffixes": [],
191
207
  "entry_patterns": ["views.py", "**/views/*.py", "api/*.py"],
208
+ "module_scan": { "root": "", "depth": 1 },
192
209
  "api_patterns": {
193
210
  "views": ["def.*request", "class.*APIView", "@api_view"],
194
211
  "decorators": ["@require_http_methods", "@csrf_exempt", "@permission_classes"]
@@ -202,6 +219,7 @@
202
219
  "exclude_dirs": ["models", "schemas", "services", "repositories", "utils", "helpers", "dependencies", "middleware"],
203
220
  "exclude_file_suffixes": [],
204
221
  "entry_patterns": ["main.py", "routers/*.py", "api/*.py"],
222
+ "module_scan": { "root": "controller", "depth": 1 },
205
223
  "api_patterns": {
206
224
  "routes": ["@app.get", "@app.post", "@app.put", "@app.delete", "@router.get"],
207
225
  "dependencies": ["Depends", "Query", "Path", "Body"]
@@ -215,6 +233,7 @@
215
233
  "exclude_dirs": ["service", "services", "repository", "repositories", "model", "models", "dto", "dtos", "middleware", "utils", "helpers"],
216
234
  "exclude_file_suffixes": [],
217
235
  "entry_patterns": ["**/*.go", "handlers/*.go", "controllers/*.go"],
236
+ "module_scan": { "root": "handlers", "depth": 1 },
218
237
  "api_patterns": {
219
238
  "router": ["gin.Router", "echo.Echo", "mux.Router", "http.HandleFunc"],
220
239
  "handlers": ["gin.HandlerFunc", "echo.HandlerFunc", "func.*http.ResponseWriter"]
@@ -228,6 +247,7 @@
228
247
  "exclude_dirs": ["service", "services", "repository", "repositories", "model", "models", "dto", "dtos", "middleware", "utils", "helpers", "schema", "migrations"],
229
248
  "exclude_file_suffixes": [],
230
249
  "entry_patterns": ["src/**/*.rs", "handlers/*.rs", "routes/*.rs"],
250
+ "module_scan": { "root": "src/handlers", "depth": 1 },
231
251
  "api_patterns": {
232
252
  "frameworks": ["actix-web", "axum", "rocket", "warp"],
233
253
  "handlers": ["#[get]", "#[post]", "async fn", "HttpResponse"]
@@ -241,6 +261,7 @@
241
261
  "electron": {
242
262
  "extensions": [".ts", ".tsx", ".js", ".jsx", ".html"],
243
263
  "entry_patterns": ["src/main.ts", "src/renderer/**/*.tsx", "src/preload.ts"],
264
+ "module_scan": { "root": "src/renderer", "depth": 1 },
244
265
  "ipc_patterns": ["ipcMain", "ipcRenderer", "contextBridge"],
245
266
  "state_management": ["Redux", "Zustand", "Electron Store"],
246
267
  "component_patterns": ["React", "Vue", "Angular in renderer"]
@@ -248,6 +269,7 @@
248
269
  "tauri": {
249
270
  "extensions": [".rs", ".ts", ".tsx", ".vue"],
250
271
  "entry_patterns": ["src-tauri/src/main.rs", "src/**/*.ts", "src/**/*.vue"],
272
+ "module_scan": { "root": "src", "depth": 1 },
251
273
  "ipc_patterns": ["invoke", "listen", "emit", "#[tauri::command]"],
252
274
  "state_management": ["Pinia", "Redux", "Tauri Store"],
253
275
  "component_patterns": ["Frontend framework components", "Rust commands"]
@@ -255,18 +277,21 @@
255
277
  "wpf": {
256
278
  "extensions": [".cs", ".xaml"],
257
279
  "entry_patterns": ["**/*.xaml.cs", "ViewModels/**/*.cs", "Views/**/*.xaml"],
280
+ "module_scan": { "root": "Views", "depth": 1 },
258
281
  "patterns": ["INotifyPropertyChanged", "ICommand", "MVVM"],
259
282
  "state_management": ["MVVM", "ObservableObject", "RelayCommand"]
260
283
  },
261
284
  "winforms": {
262
285
  "extensions": [".cs", ".vb"],
263
286
  "entry_patterns": ["**/*.cs", "Forms/**/*.cs"],
287
+ "module_scan": { "root": "Forms", "depth": 1 },
264
288
  "patterns": ["Form class", "Event handlers", "Control bindings"],
265
289
  "state_management": ["DataBinding", "INotifyPropertyChanged"]
266
290
  },
267
291
  "qt": {
268
292
  "extensions": [".cpp", ".h", ".ui", ".py"],
269
293
  "entry_patterns": ["src/**/*.cpp", "widgets/**/*.cpp", "*.ui"],
294
+ "module_scan": { "root": "src", "depth": 1 },
270
295
  "patterns": ["Q_OBJECT", "signals:", "slots:", "connect("],
271
296
  "state_management": ["Qt Property System", "QAbstractItemModel"]
272
297
  }
@@ -482,6 +482,19 @@ Team Leader executes:
482
482
  7. **`rule level="forbidden"`** = immediate stop if violated
483
483
  8. **Input/Output blocks** define the contract — respect required parameters
484
484
 
485
+ ### Strict Block Adherence
486
+
487
+ When executing an XML workflow, the Agent MUST strictly follow the block sequence defined in the workflow:
488
+
489
+ 1. **Only perform actions defined by blocks** — Every action the Agent takes must correspond to a specific block in the workflow. The Agent MUST NOT perform any actions not defined by the blocks.
490
+ 2. **Prohibited extra actions** include but are not limited to:
491
+ - Generating files not specified in block output paths (e.g. summary reports, analysis documents, logs)
492
+ - Running scripts or commands not defined in any block
493
+ - Creating intermediate/temporary files outside of block definitions
494
+ - Adding "bonus" analysis steps or documentation beyond what blocks require
495
+ 3. **Output scope** — The workflow's output is strictly limited to what is defined in `output` blocks or block-level output fields (`<field name="output">`). Any file or artifact not traceable to a block definition is considered an error.
496
+ 4. **When in doubt, don't do it** — If an action is not explicitly defined in any block, the Agent must skip it, even if it seems "helpful".
497
+
485
498
  ### Block Execution Announcement Protocol
486
499
 
487
500
  Before executing each `<block>`, the agent MUST announce the block being executed. The announcement format is: