@anhth2/spec-driven-dev-plugin 0.6.0 → 0.8.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 (86) hide show
  1. package/bin/index.js +285 -11
  2. package/commands/debug.md +233 -11
  3. package/commands/debug.tmpl +170 -6
  4. package/commands/define-product.md +68 -6
  5. package/commands/define-product.tmpl +5 -1
  6. package/commands/fix-bug.md +111 -11
  7. package/commands/fix-bug.tmpl +48 -6
  8. package/commands/generate-bdd.md +86 -9
  9. package/commands/generate-bdd.tmpl +23 -4
  10. package/commands/generate-code.md +146 -19
  11. package/commands/generate-code.tmpl +83 -14
  12. package/commands/generate-design-spec.md +754 -0
  13. package/commands/generate-design-spec.tmpl +399 -0
  14. package/commands/generate-prd.md +91 -7
  15. package/commands/generate-prd.tmpl +28 -2
  16. package/commands/generate-spec-manifest.md +519 -0
  17. package/commands/generate-spec-manifest.tmpl +164 -0
  18. package/commands/generate-tech-docs.md +122 -9
  19. package/commands/generate-tech-docs.tmpl +59 -4
  20. package/commands/generate-tests.md +491 -37
  21. package/commands/generate-tests.tmpl +428 -32
  22. package/commands/refine-prd.md +76 -8
  23. package/commands/refine-prd.tmpl +13 -3
  24. package/commands/review-code.md +94 -6
  25. package/commands/review-code.tmpl +31 -1
  26. package/commands/review-context.md +118 -12
  27. package/commands/review-context.tmpl +55 -7
  28. package/commands/review-tech-docs.md +76 -9
  29. package/commands/review-tech-docs.tmpl +13 -4
  30. package/commands/run-tests.md +196 -18
  31. package/commands/run-tests.tmpl +133 -13
  32. package/commands/setup-ai-first.md +192 -6
  33. package/commands/setup-ai-first.tmpl +136 -5
  34. package/commands/smoke-test.md +228 -22
  35. package/commands/smoke-test.tmpl +165 -17
  36. package/commands/validate-traces.md +77 -8
  37. package/commands/validate-traces.tmpl +14 -3
  38. package/core/FRAMEWORK_VERSION +1 -1
  39. package/core/commands/debug.md +233 -11
  40. package/core/commands/define-product.md +68 -6
  41. package/core/commands/fix-bug.md +111 -11
  42. package/core/commands/generate-bdd.md +86 -9
  43. package/core/commands/generate-code.md +146 -19
  44. package/core/commands/generate-design-spec.md +754 -0
  45. package/core/commands/generate-prd.md +91 -7
  46. package/core/commands/generate-spec-manifest.md +519 -0
  47. package/core/commands/generate-tech-docs.md +122 -9
  48. package/core/commands/generate-tests.md +491 -37
  49. package/core/commands/refine-prd.md +76 -8
  50. package/core/commands/review-code.md +94 -6
  51. package/core/commands/review-context.md +118 -12
  52. package/core/commands/review-tech-docs.md +76 -9
  53. package/core/commands/run-tests.md +196 -18
  54. package/core/commands/setup-ai-first.md +192 -6
  55. package/core/commands/smoke-test.md +228 -22
  56. package/core/commands/validate-traces.md +77 -8
  57. package/core/skills/code/SKILL.md +68 -8
  58. package/core/skills/debug/SKILL.md +72 -10
  59. package/core/skills/design-spec/SKILL.md +450 -0
  60. package/core/skills/discovery/SKILL.md +62 -4
  61. package/core/skills/prd/SKILL.md +12 -8
  62. package/core/skills/setup-ai-first/SKILL.md +5 -3
  63. package/core/skills/spec/SKILL.md +11 -7
  64. package/core/skills/test/SKILL.md +130 -12
  65. package/core/steps/context-loader.md +57 -1
  66. package/core/steps/gate.md +1 -1
  67. package/core/steps/report-footer.md +5 -3
  68. package/core/steps/spawn-agent.md +3 -1
  69. package/core/templates/design-spec.template.md +209 -0
  70. package/core/templates/project-context.yaml +29 -0
  71. package/package.json +1 -1
  72. package/skills/code/SKILL.md +68 -8
  73. package/skills/debug/SKILL.md +72 -10
  74. package/skills/design-spec/SKILL.md +450 -0
  75. package/skills/design-spec/SKILL.tmpl +95 -0
  76. package/skills/discovery/SKILL.md +62 -4
  77. package/skills/prd/SKILL.md +12 -8
  78. package/skills/setup-ai-first/SKILL.md +5 -3
  79. package/skills/spec/SKILL.md +11 -7
  80. package/skills/test/SKILL.md +130 -12
  81. package/steps/context-loader.md +57 -1
  82. package/steps/gate.md +1 -1
  83. package/steps/report-footer.md +5 -3
  84. package/steps/spawn-agent.md +3 -1
  85. package/templates/design-spec.template.md +209 -0
  86. package/templates/project-context.yaml +29 -0
@@ -34,7 +34,7 @@ Display and wait for response:
34
34
  ```
35
35
  ⚙️ MODEL CHECK
36
36
  ──────────────────────────────────────────────────────────────────
37
- Recommended : claude-opus-4-5 (or claude-opus-4)
37
+ Recommended : claude-opus-4 (or latest Opus model)
38
38
  Why needed : Spec analysis, architecture review, code generation
39
39
  require deep reasoning. Smaller models miss edge cases.
40
40
 
@@ -135,6 +135,7 @@ Read `.agent/project-context.yaml`. Extract and store:
135
135
  - `paths.core_entities` → path to core-entities.md
136
136
  - `paths.tech_docs_dir` → technical documentation root
137
137
  - `paths.trace_dir` → trace state directory
138
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
138
139
 
139
140
  If `paths` section is absent, use these defaults:
140
141
  - `specs_dir` = `specs/bdd`
@@ -144,13 +145,46 @@ If `paths` section is absent, use these defaults:
144
145
  - `domain_knowledge_dir` = `specs/domain-knowledge`
145
146
  - `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
146
147
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
147
- - `tech_docs_dir` = `tech-docs`
148
+ - `tech_docs_dir` = `specs/tech-docs`
148
149
  - `trace_dir` = `.trace`
150
+ - `design_spec_dir` = `specs/design-spec`
149
151
 
150
152
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
151
153
 
152
154
  ---
153
155
 
156
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
157
+
158
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
159
+
160
+ If `services` section is present:
161
+
162
+ **1. Detect active domain** (in priority order):
163
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
164
+ - Extract from target file path: segment immediately after `prd_dir` base path
165
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
166
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
167
+
168
+ **2. Route to service** — if active domain matches a key in `services`:
169
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
170
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
171
+ - Store `active_service` = `services.{domain}.path`
172
+ - Store `active_service_module` = `services.{domain}.module`
173
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
174
+
175
+ **3. Fallback** — if domain not detected or no matching service key:
176
+ - Keep default paths from Step 1
177
+ - Set `active_service = unresolved`
178
+
179
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
180
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
181
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
182
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
183
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
184
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
185
+
186
+ ---
187
+
154
188
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
155
189
 
156
190
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -221,6 +255,26 @@ If the file does not exist → skip silently.
221
255
 
222
256
  ---
223
257
 
258
+ ## Step 6.5 — [PLATFORM] Derive active_module and platform_type
259
+
260
+ Using `tech_stack.module` loaded in Step 1, derive and store two variables for use by all downstream commands:
261
+
262
+ ```
263
+ active_module = tech_stack.module (e.g. "java-spring", "react", "flutter")
264
+ ```
265
+
266
+ | `platform_type` | Modules |
267
+ |---|---|
268
+ | `backend` | `java-spring`, `golang`, `dotnet`, `php-laravel`, `context-engineering` |
269
+ | `web-frontend` | `react`, `nextjs`, `vue`, `nuxt`, `angular` |
270
+ | `mobile` | `flutter`, `react-native`, `ios-swiftui`, `android-compose` |
271
+
272
+ If `tech_stack.module` is blank or not recognized → set `platform_type = "unknown"` and flag as ⚠️ in the Step 7 recap.
273
+
274
+ These two variables (`active_module`, `platform_type`) are the canonical source for all branching logic in commands that need platform-specific behavior (generate-tests, debug, fix-bug, smoke-test).
275
+
276
+ ---
277
+
224
278
  ## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
225
279
 
226
280
  After loading all context, synthesize and output a compact summary block.
@@ -231,10 +285,12 @@ Output exactly this block:
231
285
  ```
232
286
  [CTX LOADED]
233
287
  Stack : {language} / {framework} / {database}
288
+ Platform : {active_module} ({platform_type})
234
289
  Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Service → Repository}
235
290
  Ticket : {ticket_prefix}-
236
291
  Dict : {loaded — N canonical terms, M banned terms | missing}
237
292
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
293
+ Service : {active_service} ({active_service_module}) | single-service
238
294
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
239
295
  ```
240
296
 
@@ -428,21 +484,23 @@ Suggest the logical next command based on workflow phase:
428
484
 
429
485
  | Current command | Suggest next |
430
486
  |-------------------------|-----------------------------------------------|
487
+ | /setup-ai-first | `/define-product` to start your first feature |
431
488
  | /define-product | `/generate-prd {product-definition-file}` |
432
489
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
433
490
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
434
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
491
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
492
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
435
493
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
436
494
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
437
495
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
438
496
  | /review-tech-docs | `/generate-code {feature-file}` if APPROVED; fix doc if NEEDS_FIX |
439
- | /generate-code | `/generate-tests {UC-ID}` |
497
+ | /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/generate-tests {UC-ID}` |
440
498
  | /generate-tests | `/run-tests {UC-ID}` |
441
499
  | /run-tests (passing) | `/review-code {UC-ID}` |
442
500
  | /run-tests (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
443
501
  | /review-code | `/smoke-test {UC-ID}` or create PR |
444
502
  | /smoke-test | Create PR and link to ticket |
445
- | /validate-traces | `/generate-code {UC-ID}` for gaps |
503
+ | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
446
504
  | /fix-bug | Create PR and link to ticket |
447
505
  | /debug | `/fix-bug {ticket-id}` if fix needed |
448
506
 
@@ -471,7 +529,7 @@ Next: Open in Review Board → Accept/Modify/Reject each finding
471
529
  ## Resume Mode — Apply Accepted Findings
472
530
 
473
531
  *Triggered when `$ARGUMENTS` contains `--resume`.*
474
- *Example: `/review-tech-docs --resume tech-docs/payment/PAY-UC1-tech-design.md`*
532
+ *Example: `/review-tech-docs --resume {paths.tech_docs_dir}/payment/PAY-UC1-tech-design.md`*
475
533
 
476
534
  ### Phase 1 — Read accepted findings
477
535
 
@@ -494,10 +552,19 @@ Apply in order: critical → major → minor.
494
552
  **T1, T2, T4 findings with `auto_fixable: false`:** require a human-written resolution in the
495
553
  Review Board "Modify" note. Apply exactly what the note says. Do not invent the fix.
496
554
 
497
- ### Phase 3 — Update header + Report
555
+ ### Phase 3 — Update header + TSV + Report
556
+
557
+ Edit the tech-doc file directly:
558
+ 1. Find `@trace.revision:` in the header — increment its integer value by 1.
559
+ 2. Find `@trace.status:` in the header — set its value to `draft`.
560
+
561
+ Write both changes to the file.
562
+
563
+ Then update `{paths.trace_dir}/{UC-ID}.tsv`:
564
+ - Set `tech_doc_revision` column to the new `@trace.revision` integer for all rows of this UC.
565
+ - Set `last_updated` to today's date (`YYYY-MM-DD`) for all rows of this UC.
498
566
 
499
- 1. Increment `@trace.revision` in the tech-doc header by 1.
500
- 2. Update `@trace.status` to `draft` (reset — must be re-approved after changes).
567
+ Print the report after all file writes are complete.
501
568
 
502
569
  ```
503
570
  /review-tech-docs --resume Applied — {target file}
@@ -174,7 +174,7 @@ Next: Open in Review Board → Accept/Modify/Reject each finding
174
174
  ## Resume Mode — Apply Accepted Findings
175
175
 
176
176
  *Triggered when `$ARGUMENTS` contains `--resume`.*
177
- *Example: `/review-tech-docs --resume tech-docs/payment/PAY-UC1-tech-design.md`*
177
+ *Example: `/review-tech-docs --resume {paths.tech_docs_dir}/payment/PAY-UC1-tech-design.md`*
178
178
 
179
179
  ### Phase 1 — Read accepted findings
180
180
 
@@ -197,10 +197,19 @@ Apply in order: critical → major → minor.
197
197
  **T1, T2, T4 findings with `auto_fixable: false`:** require a human-written resolution in the
198
198
  Review Board "Modify" note. Apply exactly what the note says. Do not invent the fix.
199
199
 
200
- ### Phase 3 — Update header + Report
200
+ ### Phase 3 — Update header + TSV + Report
201
201
 
202
- 1. Increment `@trace.revision` in the tech-doc header by 1.
203
- 2. Update `@trace.status` to `draft` (resetmust be re-approved after changes).
202
+ Edit the tech-doc file directly:
203
+ 1. Find `@trace.revision:` in the headerincrement its integer value by 1.
204
+ 2. Find `@trace.status:` in the header — set its value to `draft`.
205
+
206
+ Write both changes to the file.
207
+
208
+ Then update `{paths.trace_dir}/{UC-ID}.tsv`:
209
+ - Set `tech_doc_revision` column to the new `@trace.revision` integer for all rows of this UC.
210
+ - Set `last_updated` to today's date (`YYYY-MM-DD`) for all rows of this UC.
211
+
212
+ Print the report after all file writes are complete.
204
213
 
205
214
  ```
206
215
  /review-tech-docs --resume Applied — {target file}
@@ -31,7 +31,7 @@ Display and wait for response:
31
31
  ```
32
32
  ⚙️ MODEL CHECK
33
33
  ──────────────────────────────────────────────────────────────────
34
- Recommended : claude-opus-4-5 (or claude-opus-4)
34
+ Recommended : claude-opus-4 (or latest Opus model)
35
35
  Why needed : Spec analysis, architecture review, code generation
36
36
  require deep reasoning. Smaller models miss edge cases.
37
37
 
@@ -84,7 +84,7 @@ Wait for explicit "Y" or "N" from the user before continuing.
84
84
  - "N" → stop and ask what the user wants to change.
85
85
 
86
86
 
87
- *Note: For this command, the target in Step 1 is a UC-ID or service name from `$ARGUMENTS`. Context loading provides `conventions.test_command`.*
87
+ *Note: For this command, the target in Step 1 is a UC-ID or service name. Context loading provides `conventions.test_command` and `tech_stack.module`.*
88
88
 
89
89
  ## Context
90
90
  # Context Loader — Load All Project Context
@@ -131,6 +131,7 @@ Read `.agent/project-context.yaml`. Extract and store:
131
131
  - `paths.core_entities` → path to core-entities.md
132
132
  - `paths.tech_docs_dir` → technical documentation root
133
133
  - `paths.trace_dir` → trace state directory
134
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
134
135
 
135
136
  If `paths` section is absent, use these defaults:
136
137
  - `specs_dir` = `specs/bdd`
@@ -140,13 +141,46 @@ If `paths` section is absent, use these defaults:
140
141
  - `domain_knowledge_dir` = `specs/domain-knowledge`
141
142
  - `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
142
143
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
143
- - `tech_docs_dir` = `tech-docs`
144
+ - `tech_docs_dir` = `specs/tech-docs`
144
145
  - `trace_dir` = `.trace`
146
+ - `design_spec_dir` = `specs/design-spec`
145
147
 
146
148
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
147
149
 
148
150
  ---
149
151
 
152
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
153
+
154
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
155
+
156
+ If `services` section is present:
157
+
158
+ **1. Detect active domain** (in priority order):
159
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
160
+ - Extract from target file path: segment immediately after `prd_dir` base path
161
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
162
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
163
+
164
+ **2. Route to service** — if active domain matches a key in `services`:
165
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
166
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
167
+ - Store `active_service` = `services.{domain}.path`
168
+ - Store `active_service_module` = `services.{domain}.module`
169
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
170
+
171
+ **3. Fallback** — if domain not detected or no matching service key:
172
+ - Keep default paths from Step 1
173
+ - Set `active_service = unresolved`
174
+
175
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
176
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
177
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
178
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
179
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
180
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
181
+
182
+ ---
183
+
150
184
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
151
185
 
152
186
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -217,6 +251,26 @@ If the file does not exist → skip silently.
217
251
 
218
252
  ---
219
253
 
254
+ ## Step 6.5 — [PLATFORM] Derive active_module and platform_type
255
+
256
+ Using `tech_stack.module` loaded in Step 1, derive and store two variables for use by all downstream commands:
257
+
258
+ ```
259
+ active_module = tech_stack.module (e.g. "java-spring", "react", "flutter")
260
+ ```
261
+
262
+ | `platform_type` | Modules |
263
+ |---|---|
264
+ | `backend` | `java-spring`, `golang`, `dotnet`, `php-laravel`, `context-engineering` |
265
+ | `web-frontend` | `react`, `nextjs`, `vue`, `nuxt`, `angular` |
266
+ | `mobile` | `flutter`, `react-native`, `ios-swiftui`, `android-compose` |
267
+
268
+ If `tech_stack.module` is blank or not recognized → set `platform_type = "unknown"` and flag as ⚠️ in the Step 7 recap.
269
+
270
+ These two variables (`active_module`, `platform_type`) are the canonical source for all branching logic in commands that need platform-specific behavior (generate-tests, debug, fix-bug, smoke-test).
271
+
272
+ ---
273
+
220
274
  ## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
221
275
 
222
276
  After loading all context, synthesize and output a compact summary block.
@@ -227,10 +281,12 @@ Output exactly this block:
227
281
  ```
228
282
  [CTX LOADED]
229
283
  Stack : {language} / {framework} / {database}
284
+ Platform : {active_module} ({platform_type})
230
285
  Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Service → Repository}
231
286
  Ticket : {ticket_prefix}-
232
287
  Dict : {loaded — N canonical terms, M banned terms | missing}
233
288
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
289
+ Service : {active_service} ({active_service_module}) | single-service
234
290
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
235
291
  ```
236
292
 
@@ -252,25 +308,142 @@ After completing all steps, you have loaded:
252
308
  Proceed to the next step of the calling command.
253
309
 
254
310
 
311
+ ---
312
+
313
+ ## Service Detection
314
+
315
+ Read `active_module` from context (resolved in context-loader Step 1).
316
+ Use it to select the correct run command and error analysis table below.
317
+
255
318
  ---
256
319
 
257
320
  ## Run
321
+
322
+ ### If `platform_type = backend`
323
+
324
+ ```bash
325
+ # Run all tests for this UC
326
+ {conventions.test_command}
327
+
328
+ # Scoped to specific class (faster feedback)
329
+ # java-spring:
330
+ mvn test -Dtest={ClassName}
331
+ # golang:
332
+ go test ./... -run Test{FunctionName}
333
+ # dotnet:
334
+ dotnet test --filter "FullyQualifiedName~{ClassName}"
335
+ # php-laravel:
336
+ php artisan test --filter {ClassName}
337
+ # context-engineering (pytest):
338
+ pytest tests/{domain}/{test_file}.py -v
339
+ pytest tests/{domain}/{test_file}.py::{TestClass}::{test_method} -v
340
+ pytest tests/ --cov={source_dir} --cov-report=term-missing
341
+ ```
342
+
343
+ ### If `platform_type = web-frontend`
344
+
258
345
  ```bash
259
- {conventions.test_command} # all tests in module
260
- {conventions.test_command} --class {ClassName} # specific class (faster)
261
- {conventions.test_command} --pattern "*{Resource}*" # by pattern
346
+ # Run all tests
347
+ {conventions.test_command}
348
+
349
+ # Scoped (Vitest / Jest):
350
+ npx vitest run src/features/{domain}/{Component}.test.tsx
351
+ npx jest src/features/{domain}/{Component}.test.tsx
352
+
353
+ # E2E (Playwright):
354
+ npx playwright test {UC-ID}
355
+ # E2E (Cypress):
356
+ npx cypress run --spec "cypress/e2e/{UC-ID}*"
262
357
  ```
263
358
 
359
+ ### If `platform_type = mobile`
360
+
361
+ ```bash
362
+ # Flutter:
363
+ flutter test test/{domain}/{UC-ID}_test.dart
364
+ flutter test integration_test/{UC-ID}_test.dart # integration
365
+
366
+ # React Native:
367
+ npx jest {UC-ID}
368
+
369
+ # iOS (Xcode command line):
370
+ xcodebuild test -scheme {Scheme} -destination 'platform=iOS Simulator,name=iPhone 15'
371
+
372
+ # Android:
373
+ ./gradlew test # unit tests
374
+ ./gradlew connectedAndroidTest # instrumented (device/emulator required)
375
+ ```
376
+
377
+ > **Note for Android instrumented tests:** a running emulator or connected device is required before running `connectedAndroidTest`. Start one via Android Studio or: `emulator -avd {AVD_NAME} &`
378
+
379
+ ---
380
+
264
381
  ## Analyze Failures
265
382
 
383
+ ### Backend failure patterns
384
+
385
+ #### java-spring / golang / dotnet / php-laravel
386
+
387
+ | Error Pattern | Common Cause | Suggested Fix |
388
+ |---|---|---|
389
+ | `NullPointerException` | Missing mock setup | Check `given(...)`/`coEvery`/`mockk` for null dependency |
390
+ | `Bean not found` | Missing mock declaration | Add `@MockBean` / inject mock |
391
+ | `Expected 200, got 401` | Missing auth setup | Add auth token/user to test context |
392
+ | `Expected 200, got 400` | Request body fails validation | Check required fields in DTO |
393
+ | `Expected 200, got 403` | Wrong role | Add correct role to test user |
394
+ | `LazyInitializationException` | Lazy collection outside transaction | Add `@Transactional` or eager fetch |
395
+ | `Mapper not found` | Code not compiled | Run build step before tests |
396
+ | `DataIntegrityViolationException` | Duplicate key in DB setup | Use `@Transactional` + rollback, or clean DB between tests |
397
+ | Assertion mismatch | Wrong mock return value | Re-read `given(...).willReturn(...)` setup |
398
+
399
+ #### context-engineering (AI/LLM pipelines)
400
+
266
401
  | Error Pattern | Common Cause | Suggested Fix |
267
402
  |---|---|---|
268
- | NullPointerException | Missing mock setup | Check `given(...)` for null dependency |
269
- | Bean not found | Missing mock declaration | Add mock for missing dependency |
270
- | Expected 200, got 403 | Missing auth setup | Add auth user/role to test context |
271
- | Expected 200, got 400 | Request body fails validation | Check required fields in DTO |
272
- | LazyInitializationException | Lazy collection outside transaction | Add `@Transactional` or eager fetch |
273
- | Mapper not found | Code generator not run | Run compile step before tests |
403
+ | `AssertionError` on LLM mock output | Mock return value not matching schema | Re-check `mock_llm.return_value` / `mock_llm.complete.return_value` setup |
404
+ | `ValidationError` on response | LLM output structure doesn't match expected schema | Tighten schema check or add retry logic in test |
405
+ | `ConnectionError` / `APIError` | Real LLM API being called in test | Ensure `patch('...')` mock is applied never call real LLM in unit tests |
406
+ | `TimeoutError` | Test calling live LLM endpoint | Add mock; check test fixtures |
407
+ | Flaky / non-deterministic results | Real LLM response used in assertion | Replace with deterministic mock return value |
408
+
409
+ ### Web frontend failure patterns
410
+
411
+ | Error Pattern | Common Cause | Suggested Fix |
412
+ |---|---|---|
413
+ | `Unable to find role "..."` | Element not rendered yet | Wrap in `await waitFor(() => ...)` |
414
+ | `TestingLibraryElementError: Found multiple elements` | Selector too broad | Use `getByRole(..., { name: '...' })` to narrow |
415
+ | `Network request not intercepted` | Missing MSW handler / `cy.intercept` | Add handler for the endpoint |
416
+ | `act(...)` warning | State update after test ended | Await async events / `await userEvent.click(...)` |
417
+ | `Cannot read properties of undefined` | Component rendered before data loaded | Add loading state or mock resolved data |
418
+ | Playwright timeout | Page not navigated / element hidden | Check route, add `waitForSelector` |
419
+ | `expect(page.locator(...)).toBeVisible` fails | Wrong selector | Use Playwright Inspector to find correct locator |
420
+
421
+ ### Mobile failure patterns
422
+
423
+ #### Flutter
424
+ | Error Pattern | Common Cause | Suggested Fix |
425
+ |---|---|---|
426
+ | `pumpAndSettle timed out` | Async operation not completing | Use `pump(Duration(...))` for specific delay |
427
+ | `No widget found` | Widget not rendered / wrong finder | Check `find.byType`, `find.text`, `find.byKey` |
428
+ | `setState called after dispose` | Widget disposed before async completes | Cancel async in `dispose()` |
429
+ | BLoC state mismatch | Wrong event emitted | Verify `mockBloc` received correct event |
430
+
431
+ #### React Native
432
+ | Error Pattern | Common Cause | Suggested Fix |
433
+ |---|---|---|
434
+ | `Unable to find element` | Missing `testID` or wrong query | Add `accessibilityLabel` or `testID` to component |
435
+ | `act(...)` warning | Async state updates | Wrap in `act(async () => { ... })` |
436
+ | Navigation mock missing | `useNavigation` not mocked | Add jest mock for `@react-navigation/native` |
437
+
438
+ #### iOS / Android
439
+ | Error Pattern | Common Cause | Suggested Fix |
440
+ |---|---|---|
441
+ | `XCTAssertEqual failed` | Wrong expected value | Check ViewModel output for given mock |
442
+ | `Compose node not found` | Wrong `contentDescription` / `testTag` | Add `Modifier.testTag(...)` to composable |
443
+ | `Hilt injection failed` | Missing test module | Add `@UninstallModules` + `@BindValue` in test class |
444
+ | Emulator not available | `connectedAndroidTest` without device | Start emulator first, wait for it to boot |
445
+
446
+ ---
274
447
 
275
448
  ## Output
276
449
 
@@ -302,21 +475,23 @@ Suggest the logical next command based on workflow phase:
302
475
 
303
476
  | Current command | Suggest next |
304
477
  |-------------------------|-----------------------------------------------|
478
+ | /setup-ai-first | `/define-product` to start your first feature |
305
479
  | /define-product | `/generate-prd {product-definition-file}` |
306
480
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
307
481
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
308
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
482
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
483
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
309
484
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
310
485
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
311
486
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
312
487
  | /review-tech-docs | `/generate-code {feature-file}` if APPROVED; fix doc if NEEDS_FIX |
313
- | /generate-code | `/generate-tests {UC-ID}` |
488
+ | /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/generate-tests {UC-ID}` |
314
489
  | /generate-tests | `/run-tests {UC-ID}` |
315
490
  | /run-tests (passing) | `/review-code {UC-ID}` |
316
491
  | /run-tests (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
317
492
  | /review-code | `/smoke-test {UC-ID}` or create PR |
318
493
  | /smoke-test | Create PR and link to ticket |
319
- | /validate-traces | `/generate-code {UC-ID}` for gaps |
494
+ | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
320
495
  | /fix-bug | Create PR and link to ticket |
321
496
  | /debug | `/fix-bug {ticket-id}` if fix needed |
322
497
 
@@ -330,14 +505,17 @@ Next : {suggested command with example arguments}
330
505
 
331
506
 
332
507
  ```
333
- /run-tests Report — {service}
508
+ /run-tests Report — {UC-ID} ({active_module})
334
509
  ✅ Passed: {N} | ❌ Failed: {M} | ⏭️ Skipped: {K} | Duration: {X}s
335
510
 
336
511
  ## Failed Tests
337
512
  | Test | Error | Root Cause |
338
- |------|-------|-----------|
513
+ |------|-------|------------|
339
514
 
340
515
  ## Recommendations
341
516
  {specific fix per failure}
342
- Next: /fix-bug if real bug, or correct test if wrong expectation.
517
+
518
+ Next:
519
+ All tests pass → /review-code {UC-ID}
520
+ Tests fail → /fix-bug {TICKET_ID} (real bug) or fix test (wrong expectation)
343
521
  ```