@anhth2/spec-driven-dev-plugin 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +1 -1
- package/bin/index.js +184 -15
- package/commands/debug.md +196 -10
- package/commands/debug.tmpl +170 -6
- package/commands/define-product.md +31 -5
- package/commands/define-product.tmpl +5 -1
- package/commands/fix-bug.md +74 -10
- package/commands/fix-bug.tmpl +48 -6
- package/commands/generate-bdd.md +49 -8
- package/commands/generate-bdd.tmpl +23 -4
- package/commands/generate-code.md +109 -18
- package/commands/generate-code.tmpl +83 -14
- package/commands/generate-prd.md +33 -6
- package/commands/generate-prd.tmpl +7 -2
- package/commands/generate-tech-docs.md +85 -8
- package/commands/generate-tech-docs.tmpl +59 -4
- package/commands/generate-tests.md +454 -36
- package/commands/generate-tests.tmpl +428 -32
- package/commands/refine-prd.md +39 -7
- package/commands/refine-prd.tmpl +13 -3
- package/commands/review-code.md +57 -5
- package/commands/review-code.tmpl +31 -1
- package/commands/review-context.md +41 -11
- package/commands/review-context.tmpl +15 -7
- package/commands/review-tech-docs.md +39 -8
- package/commands/review-tech-docs.tmpl +13 -4
- package/commands/run-tests.md +159 -17
- package/commands/run-tests.tmpl +133 -13
- package/commands/setup-ai-first.md +85 -9
- package/commands/setup-ai-first.tmpl +30 -8
- package/commands/smoke-test.md +191 -21
- package/commands/smoke-test.tmpl +165 -17
- package/commands/validate-traces.md +40 -7
- package/commands/validate-traces.tmpl +14 -3
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/debug.md +196 -10
- package/core/commands/define-product.md +31 -5
- package/core/commands/fix-bug.md +74 -10
- package/core/commands/generate-bdd.md +49 -8
- package/core/commands/generate-code.md +109 -18
- package/core/commands/generate-prd.md +33 -6
- package/core/commands/generate-tech-docs.md +85 -8
- package/core/commands/generate-tests.md +454 -36
- package/core/commands/refine-prd.md +39 -7
- package/core/commands/review-code.md +57 -5
- package/core/commands/review-context.md +41 -11
- package/core/commands/review-tech-docs.md +39 -8
- package/core/commands/run-tests.md +159 -17
- package/core/commands/setup-ai-first.md +85 -9
- package/core/commands/smoke-test.md +191 -21
- package/core/commands/validate-traces.md +40 -7
- package/core/skills/code/SKILL.md +29 -6
- package/core/skills/debug/SKILL.md +31 -7
- package/core/skills/discovery/SKILL.md +25 -3
- package/core/skills/prd/SKILL.md +8 -6
- package/core/skills/setup-ai-first/SKILL.md +3 -2
- package/core/skills/spec/SKILL.md +7 -5
- package/core/skills/test/SKILL.md +54 -9
- package/core/steps/context-loader.md +22 -1
- package/core/steps/gate.md +1 -1
- package/core/steps/report-footer.md +3 -2
- package/core/steps/spawn-agent.md +3 -1
- package/package.json +1 -1
- package/scripts/init.sh +2 -2
- package/scripts/upgrade.sh +4 -4
- package/skills/code/SKILL.md +29 -6
- package/skills/debug/SKILL.md +31 -7
- package/skills/discovery/SKILL.md +25 -3
- package/skills/prd/SKILL.md +8 -6
- package/skills/setup-ai-first/SKILL.md +3 -2
- package/skills/spec/SKILL.md +7 -5
- package/skills/test/SKILL.md +54 -9
- package/steps/context-loader.md +22 -1
- package/steps/gate.md +1 -1
- package/steps/report-footer.md +3 -2
- package/steps/spawn-agent.md +3 -1
package/commands/run-tests.md
CHANGED
|
@@ -31,7 +31,7 @@ Display and wait for response:
|
|
|
31
31
|
```
|
|
32
32
|
⚙️ MODEL CHECK
|
|
33
33
|
──────────────────────────────────────────────────────────────────
|
|
34
|
-
Recommended : 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
|
|
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
|
|
@@ -140,7 +140,7 @@ If `paths` section is absent, use these defaults:
|
|
|
140
140
|
- `domain_knowledge_dir` = `specs/domain-knowledge`
|
|
141
141
|
- `business_dictionary` = `specs/domain-knowledge/business-dictionary.md`
|
|
142
142
|
- `core_entities` = `specs/domain-knowledge/core-entities.md`
|
|
143
|
-
- `tech_docs_dir` = `tech-docs`
|
|
143
|
+
- `tech_docs_dir` = `specs/tech-docs`
|
|
144
144
|
- `trace_dir` = `.trace`
|
|
145
145
|
|
|
146
146
|
If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
|
|
@@ -217,6 +217,26 @@ If the file does not exist → skip silently.
|
|
|
217
217
|
|
|
218
218
|
---
|
|
219
219
|
|
|
220
|
+
## Step 6.5 — [PLATFORM] Derive active_module and platform_type
|
|
221
|
+
|
|
222
|
+
Using `tech_stack.module` loaded in Step 1, derive and store two variables for use by all downstream commands:
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
active_module = tech_stack.module (e.g. "java-spring", "react", "flutter")
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| `platform_type` | Modules |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `backend` | `java-spring`, `golang`, `dotnet`, `php-laravel`, `context-engineering` |
|
|
231
|
+
| `web-frontend` | `react`, `nextjs`, `vue`, `nuxt`, `angular` |
|
|
232
|
+
| `mobile` | `flutter`, `react-native`, `ios-swiftui`, `android-compose` |
|
|
233
|
+
|
|
234
|
+
If `tech_stack.module` is blank or not recognized → set `platform_type = "unknown"` and flag as ⚠️ in the Step 7 recap.
|
|
235
|
+
|
|
236
|
+
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).
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
220
240
|
## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
|
|
221
241
|
|
|
222
242
|
After loading all context, synthesize and output a compact summary block.
|
|
@@ -227,6 +247,7 @@ Output exactly this block:
|
|
|
227
247
|
```
|
|
228
248
|
[CTX LOADED]
|
|
229
249
|
Stack : {language} / {framework} / {database}
|
|
250
|
+
Platform : {active_module} ({platform_type})
|
|
230
251
|
Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Service → Repository}
|
|
231
252
|
Ticket : {ticket_prefix}-
|
|
232
253
|
Dict : {loaded — N canonical terms, M banned terms | missing}
|
|
@@ -252,25 +273,142 @@ After completing all steps, you have loaded:
|
|
|
252
273
|
Proceed to the next step of the calling command.
|
|
253
274
|
|
|
254
275
|
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Service Detection
|
|
279
|
+
|
|
280
|
+
Read `active_module` from context (resolved in context-loader Step 1).
|
|
281
|
+
Use it to select the correct run command and error analysis table below.
|
|
282
|
+
|
|
255
283
|
---
|
|
256
284
|
|
|
257
285
|
## Run
|
|
286
|
+
|
|
287
|
+
### If `platform_type = backend`
|
|
288
|
+
|
|
258
289
|
```bash
|
|
259
|
-
|
|
260
|
-
{conventions.test_command}
|
|
261
|
-
|
|
290
|
+
# Run all tests for this UC
|
|
291
|
+
{conventions.test_command}
|
|
292
|
+
|
|
293
|
+
# Scoped to specific class (faster feedback)
|
|
294
|
+
# java-spring:
|
|
295
|
+
mvn test -Dtest={ClassName}
|
|
296
|
+
# golang:
|
|
297
|
+
go test ./... -run Test{FunctionName}
|
|
298
|
+
# dotnet:
|
|
299
|
+
dotnet test --filter "FullyQualifiedName~{ClassName}"
|
|
300
|
+
# php-laravel:
|
|
301
|
+
php artisan test --filter {ClassName}
|
|
302
|
+
# context-engineering (pytest):
|
|
303
|
+
pytest tests/{domain}/{test_file}.py -v
|
|
304
|
+
pytest tests/{domain}/{test_file}.py::{TestClass}::{test_method} -v
|
|
305
|
+
pytest tests/ --cov={source_dir} --cov-report=term-missing
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### If `platform_type = web-frontend`
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Run all tests
|
|
312
|
+
{conventions.test_command}
|
|
313
|
+
|
|
314
|
+
# Scoped (Vitest / Jest):
|
|
315
|
+
npx vitest run src/features/{domain}/{Component}.test.tsx
|
|
316
|
+
npx jest src/features/{domain}/{Component}.test.tsx
|
|
317
|
+
|
|
318
|
+
# E2E (Playwright):
|
|
319
|
+
npx playwright test {UC-ID}
|
|
320
|
+
# E2E (Cypress):
|
|
321
|
+
npx cypress run --spec "cypress/e2e/{UC-ID}*"
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### If `platform_type = mobile`
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
# Flutter:
|
|
328
|
+
flutter test test/{domain}/{UC-ID}_test.dart
|
|
329
|
+
flutter test integration_test/{UC-ID}_test.dart # integration
|
|
330
|
+
|
|
331
|
+
# React Native:
|
|
332
|
+
npx jest {UC-ID}
|
|
333
|
+
|
|
334
|
+
# iOS (Xcode command line):
|
|
335
|
+
xcodebuild test -scheme {Scheme} -destination 'platform=iOS Simulator,name=iPhone 15'
|
|
336
|
+
|
|
337
|
+
# Android:
|
|
338
|
+
./gradlew test # unit tests
|
|
339
|
+
./gradlew connectedAndroidTest # instrumented (device/emulator required)
|
|
262
340
|
```
|
|
263
341
|
|
|
342
|
+
> **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} &`
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
264
346
|
## Analyze Failures
|
|
265
347
|
|
|
348
|
+
### Backend failure patterns
|
|
349
|
+
|
|
350
|
+
#### java-spring / golang / dotnet / php-laravel
|
|
351
|
+
|
|
352
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
353
|
+
|---|---|---|
|
|
354
|
+
| `NullPointerException` | Missing mock setup | Check `given(...)`/`coEvery`/`mockk` for null dependency |
|
|
355
|
+
| `Bean not found` | Missing mock declaration | Add `@MockBean` / inject mock |
|
|
356
|
+
| `Expected 200, got 401` | Missing auth setup | Add auth token/user to test context |
|
|
357
|
+
| `Expected 200, got 400` | Request body fails validation | Check required fields in DTO |
|
|
358
|
+
| `Expected 200, got 403` | Wrong role | Add correct role to test user |
|
|
359
|
+
| `LazyInitializationException` | Lazy collection outside transaction | Add `@Transactional` or eager fetch |
|
|
360
|
+
| `Mapper not found` | Code not compiled | Run build step before tests |
|
|
361
|
+
| `DataIntegrityViolationException` | Duplicate key in DB setup | Use `@Transactional` + rollback, or clean DB between tests |
|
|
362
|
+
| Assertion mismatch | Wrong mock return value | Re-read `given(...).willReturn(...)` setup |
|
|
363
|
+
|
|
364
|
+
#### context-engineering (AI/LLM pipelines)
|
|
365
|
+
|
|
366
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
367
|
+
|---|---|---|
|
|
368
|
+
| `AssertionError` on LLM mock output | Mock return value not matching schema | Re-check `mock_llm.return_value` / `mock_llm.complete.return_value` setup |
|
|
369
|
+
| `ValidationError` on response | LLM output structure doesn't match expected schema | Tighten schema check or add retry logic in test |
|
|
370
|
+
| `ConnectionError` / `APIError` | Real LLM API being called in test | Ensure `patch('...')` mock is applied — never call real LLM in unit tests |
|
|
371
|
+
| `TimeoutError` | Test calling live LLM endpoint | Add mock; check test fixtures |
|
|
372
|
+
| Flaky / non-deterministic results | Real LLM response used in assertion | Replace with deterministic mock return value |
|
|
373
|
+
|
|
374
|
+
### Web frontend failure patterns
|
|
375
|
+
|
|
266
376
|
| Error Pattern | Common Cause | Suggested Fix |
|
|
267
377
|
|---|---|---|
|
|
268
|
-
|
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
|
|
|
272
|
-
|
|
|
273
|
-
|
|
|
378
|
+
| `Unable to find role "..."` | Element not rendered yet | Wrap in `await waitFor(() => ...)` |
|
|
379
|
+
| `TestingLibraryElementError: Found multiple elements` | Selector too broad | Use `getByRole(..., { name: '...' })` to narrow |
|
|
380
|
+
| `Network request not intercepted` | Missing MSW handler / `cy.intercept` | Add handler for the endpoint |
|
|
381
|
+
| `act(...)` warning | State update after test ended | Await async events / `await userEvent.click(...)` |
|
|
382
|
+
| `Cannot read properties of undefined` | Component rendered before data loaded | Add loading state or mock resolved data |
|
|
383
|
+
| Playwright timeout | Page not navigated / element hidden | Check route, add `waitForSelector` |
|
|
384
|
+
| `expect(page.locator(...)).toBeVisible` fails | Wrong selector | Use Playwright Inspector to find correct locator |
|
|
385
|
+
|
|
386
|
+
### Mobile failure patterns
|
|
387
|
+
|
|
388
|
+
#### Flutter
|
|
389
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
390
|
+
|---|---|---|
|
|
391
|
+
| `pumpAndSettle timed out` | Async operation not completing | Use `pump(Duration(...))` for specific delay |
|
|
392
|
+
| `No widget found` | Widget not rendered / wrong finder | Check `find.byType`, `find.text`, `find.byKey` |
|
|
393
|
+
| `setState called after dispose` | Widget disposed before async completes | Cancel async in `dispose()` |
|
|
394
|
+
| BLoC state mismatch | Wrong event emitted | Verify `mockBloc` received correct event |
|
|
395
|
+
|
|
396
|
+
#### React Native
|
|
397
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
398
|
+
|---|---|---|
|
|
399
|
+
| `Unable to find element` | Missing `testID` or wrong query | Add `accessibilityLabel` or `testID` to component |
|
|
400
|
+
| `act(...)` warning | Async state updates | Wrap in `act(async () => { ... })` |
|
|
401
|
+
| Navigation mock missing | `useNavigation` not mocked | Add jest mock for `@react-navigation/native` |
|
|
402
|
+
|
|
403
|
+
#### iOS / Android
|
|
404
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
405
|
+
|---|---|---|
|
|
406
|
+
| `XCTAssertEqual failed` | Wrong expected value | Check ViewModel output for given mock |
|
|
407
|
+
| `Compose node not found` | Wrong `contentDescription` / `testTag` | Add `Modifier.testTag(...)` to composable |
|
|
408
|
+
| `Hilt injection failed` | Missing test module | Add `@UninstallModules` + `@BindValue` in test class |
|
|
409
|
+
| Emulator not available | `connectedAndroidTest` without device | Start emulator first, wait for it to boot |
|
|
410
|
+
|
|
411
|
+
---
|
|
274
412
|
|
|
275
413
|
## Output
|
|
276
414
|
|
|
@@ -302,6 +440,7 @@ Suggest the logical next command based on workflow phase:
|
|
|
302
440
|
|
|
303
441
|
| Current command | Suggest next |
|
|
304
442
|
|-------------------------|-----------------------------------------------|
|
|
443
|
+
| /setup-ai-first | `/define-product` to start your first feature |
|
|
305
444
|
| /define-product | `/generate-prd {product-definition-file}` |
|
|
306
445
|
| /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
|
|
307
446
|
| /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
|
|
@@ -310,13 +449,13 @@ Suggest the logical next command based on workflow phase:
|
|
|
310
449
|
| /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
|
|
311
450
|
| /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
|
|
312
451
|
| /review-tech-docs | `/generate-code {feature-file}` if APPROVED; fix doc if NEEDS_FIX |
|
|
313
|
-
| /generate-code | `/generate-tests {UC-ID}`
|
|
452
|
+
| /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/generate-tests {UC-ID}` |
|
|
314
453
|
| /generate-tests | `/run-tests {UC-ID}` |
|
|
315
454
|
| /run-tests (passing) | `/review-code {UC-ID}` |
|
|
316
455
|
| /run-tests (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
|
|
317
456
|
| /review-code | `/smoke-test {UC-ID}` or create PR |
|
|
318
457
|
| /smoke-test | Create PR and link to ticket |
|
|
319
|
-
| /validate-traces | `/generate-code {UC-ID}
|
|
458
|
+
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
|
|
320
459
|
| /fix-bug | Create PR and link to ticket |
|
|
321
460
|
| /debug | `/fix-bug {ticket-id}` if fix needed |
|
|
322
461
|
|
|
@@ -330,14 +469,17 @@ Next : {suggested command with example arguments}
|
|
|
330
469
|
|
|
331
470
|
|
|
332
471
|
```
|
|
333
|
-
/run-tests Report — {
|
|
472
|
+
/run-tests Report — {UC-ID} ({active_module})
|
|
334
473
|
✅ Passed: {N} | ❌ Failed: {M} | ⏭️ Skipped: {K} | Duration: {X}s
|
|
335
474
|
|
|
336
475
|
## Failed Tests
|
|
337
476
|
| Test | Error | Root Cause |
|
|
338
|
-
|
|
477
|
+
|------|-------|------------|
|
|
339
478
|
|
|
340
479
|
## Recommendations
|
|
341
480
|
{specific fix per failure}
|
|
342
|
-
|
|
481
|
+
|
|
482
|
+
Next:
|
|
483
|
+
All tests pass → /review-code {UC-ID}
|
|
484
|
+
Tests fail → /fix-bug {TICKET_ID} (real bug) or fix test (wrong expectation)
|
|
343
485
|
```
|
package/commands/run-tests.tmpl
CHANGED
|
@@ -3,44 +3,164 @@
|
|
|
3
3
|
## Gate
|
|
4
4
|
{{include:steps/gate.md}}
|
|
5
5
|
|
|
6
|
-
*Note: For this command, the target in Step 1 is a UC-ID or service name
|
|
6
|
+
*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`.*
|
|
7
7
|
|
|
8
8
|
## Context
|
|
9
9
|
{{include:steps/context-loader.md}}
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## Service Detection
|
|
14
|
+
|
|
15
|
+
Read `active_module` from context (resolved in context-loader Step 1).
|
|
16
|
+
Use it to select the correct run command and error analysis table below.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
13
20
|
## Run
|
|
21
|
+
|
|
22
|
+
### If `platform_type = backend`
|
|
23
|
+
|
|
14
24
|
```bash
|
|
15
|
-
|
|
16
|
-
{conventions.test_command}
|
|
17
|
-
|
|
25
|
+
# Run all tests for this UC
|
|
26
|
+
{conventions.test_command}
|
|
27
|
+
|
|
28
|
+
# Scoped to specific class (faster feedback)
|
|
29
|
+
# java-spring:
|
|
30
|
+
mvn test -Dtest={ClassName}
|
|
31
|
+
# golang:
|
|
32
|
+
go test ./... -run Test{FunctionName}
|
|
33
|
+
# dotnet:
|
|
34
|
+
dotnet test --filter "FullyQualifiedName~{ClassName}"
|
|
35
|
+
# php-laravel:
|
|
36
|
+
php artisan test --filter {ClassName}
|
|
37
|
+
# context-engineering (pytest):
|
|
38
|
+
pytest tests/{domain}/{test_file}.py -v
|
|
39
|
+
pytest tests/{domain}/{test_file}.py::{TestClass}::{test_method} -v
|
|
40
|
+
pytest tests/ --cov={source_dir} --cov-report=term-missing
|
|
18
41
|
```
|
|
19
42
|
|
|
43
|
+
### If `platform_type = web-frontend`
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Run all tests
|
|
47
|
+
{conventions.test_command}
|
|
48
|
+
|
|
49
|
+
# Scoped (Vitest / Jest):
|
|
50
|
+
npx vitest run src/features/{domain}/{Component}.test.tsx
|
|
51
|
+
npx jest src/features/{domain}/{Component}.test.tsx
|
|
52
|
+
|
|
53
|
+
# E2E (Playwright):
|
|
54
|
+
npx playwright test {UC-ID}
|
|
55
|
+
# E2E (Cypress):
|
|
56
|
+
npx cypress run --spec "cypress/e2e/{UC-ID}*"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### If `platform_type = mobile`
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Flutter:
|
|
63
|
+
flutter test test/{domain}/{UC-ID}_test.dart
|
|
64
|
+
flutter test integration_test/{UC-ID}_test.dart # integration
|
|
65
|
+
|
|
66
|
+
# React Native:
|
|
67
|
+
npx jest {UC-ID}
|
|
68
|
+
|
|
69
|
+
# iOS (Xcode command line):
|
|
70
|
+
xcodebuild test -scheme {Scheme} -destination 'platform=iOS Simulator,name=iPhone 15'
|
|
71
|
+
|
|
72
|
+
# Android:
|
|
73
|
+
./gradlew test # unit tests
|
|
74
|
+
./gradlew connectedAndroidTest # instrumented (device/emulator required)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
> **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} &`
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
20
81
|
## Analyze Failures
|
|
21
82
|
|
|
83
|
+
### Backend failure patterns
|
|
84
|
+
|
|
85
|
+
#### java-spring / golang / dotnet / php-laravel
|
|
86
|
+
|
|
87
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `NullPointerException` | Missing mock setup | Check `given(...)`/`coEvery`/`mockk` for null dependency |
|
|
90
|
+
| `Bean not found` | Missing mock declaration | Add `@MockBean` / inject mock |
|
|
91
|
+
| `Expected 200, got 401` | Missing auth setup | Add auth token/user to test context |
|
|
92
|
+
| `Expected 200, got 400` | Request body fails validation | Check required fields in DTO |
|
|
93
|
+
| `Expected 200, got 403` | Wrong role | Add correct role to test user |
|
|
94
|
+
| `LazyInitializationException` | Lazy collection outside transaction | Add `@Transactional` or eager fetch |
|
|
95
|
+
| `Mapper not found` | Code not compiled | Run build step before tests |
|
|
96
|
+
| `DataIntegrityViolationException` | Duplicate key in DB setup | Use `@Transactional` + rollback, or clean DB between tests |
|
|
97
|
+
| Assertion mismatch | Wrong mock return value | Re-read `given(...).willReturn(...)` setup |
|
|
98
|
+
|
|
99
|
+
#### context-engineering (AI/LLM pipelines)
|
|
100
|
+
|
|
22
101
|
| Error Pattern | Common Cause | Suggested Fix |
|
|
23
102
|
|---|---|---|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
103
|
+
| `AssertionError` on LLM mock output | Mock return value not matching schema | Re-check `mock_llm.return_value` / `mock_llm.complete.return_value` setup |
|
|
104
|
+
| `ValidationError` on response | LLM output structure doesn't match expected schema | Tighten schema check or add retry logic in test |
|
|
105
|
+
| `ConnectionError` / `APIError` | Real LLM API being called in test | Ensure `patch('...')` mock is applied — never call real LLM in unit tests |
|
|
106
|
+
| `TimeoutError` | Test calling live LLM endpoint | Add mock; check test fixtures |
|
|
107
|
+
| Flaky / non-deterministic results | Real LLM response used in assertion | Replace with deterministic mock return value |
|
|
108
|
+
|
|
109
|
+
### Web frontend failure patterns
|
|
110
|
+
|
|
111
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `Unable to find role "..."` | Element not rendered yet | Wrap in `await waitFor(() => ...)` |
|
|
114
|
+
| `TestingLibraryElementError: Found multiple elements` | Selector too broad | Use `getByRole(..., { name: '...' })` to narrow |
|
|
115
|
+
| `Network request not intercepted` | Missing MSW handler / `cy.intercept` | Add handler for the endpoint |
|
|
116
|
+
| `act(...)` warning | State update after test ended | Await async events / `await userEvent.click(...)` |
|
|
117
|
+
| `Cannot read properties of undefined` | Component rendered before data loaded | Add loading state or mock resolved data |
|
|
118
|
+
| Playwright timeout | Page not navigated / element hidden | Check route, add `waitForSelector` |
|
|
119
|
+
| `expect(page.locator(...)).toBeVisible` fails | Wrong selector | Use Playwright Inspector to find correct locator |
|
|
120
|
+
|
|
121
|
+
### Mobile failure patterns
|
|
122
|
+
|
|
123
|
+
#### Flutter
|
|
124
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| `pumpAndSettle timed out` | Async operation not completing | Use `pump(Duration(...))` for specific delay |
|
|
127
|
+
| `No widget found` | Widget not rendered / wrong finder | Check `find.byType`, `find.text`, `find.byKey` |
|
|
128
|
+
| `setState called after dispose` | Widget disposed before async completes | Cancel async in `dispose()` |
|
|
129
|
+
| BLoC state mismatch | Wrong event emitted | Verify `mockBloc` received correct event |
|
|
130
|
+
|
|
131
|
+
#### React Native
|
|
132
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `Unable to find element` | Missing `testID` or wrong query | Add `accessibilityLabel` or `testID` to component |
|
|
135
|
+
| `act(...)` warning | Async state updates | Wrap in `act(async () => { ... })` |
|
|
136
|
+
| Navigation mock missing | `useNavigation` not mocked | Add jest mock for `@react-navigation/native` |
|
|
137
|
+
|
|
138
|
+
#### iOS / Android
|
|
139
|
+
| Error Pattern | Common Cause | Suggested Fix |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `XCTAssertEqual failed` | Wrong expected value | Check ViewModel output for given mock |
|
|
142
|
+
| `Compose node not found` | Wrong `contentDescription` / `testTag` | Add `Modifier.testTag(...)` to composable |
|
|
143
|
+
| `Hilt injection failed` | Missing test module | Add `@UninstallModules` + `@BindValue` in test class |
|
|
144
|
+
| Emulator not available | `connectedAndroidTest` without device | Start emulator first, wait for it to boot |
|
|
145
|
+
|
|
146
|
+
---
|
|
30
147
|
|
|
31
148
|
## Output
|
|
32
149
|
|
|
33
150
|
{{include:steps/report-footer.md}}
|
|
34
151
|
|
|
35
152
|
```
|
|
36
|
-
/run-tests Report — {
|
|
153
|
+
/run-tests Report — {UC-ID} ({active_module})
|
|
37
154
|
✅ Passed: {N} | ❌ Failed: {M} | ⏭️ Skipped: {K} | Duration: {X}s
|
|
38
155
|
|
|
39
156
|
## Failed Tests
|
|
40
157
|
| Test | Error | Root Cause |
|
|
41
|
-
|
|
158
|
+
|------|-------|------------|
|
|
42
159
|
|
|
43
160
|
## Recommendations
|
|
44
161
|
{specific fix per failure}
|
|
45
|
-
|
|
162
|
+
|
|
163
|
+
Next:
|
|
164
|
+
All tests pass → /review-code {UC-ID}
|
|
165
|
+
Tests fail → /fix-bug {TICKET_ID} (real bug) or fix test (wrong expectation)
|
|
46
166
|
```
|
|
@@ -33,7 +33,7 @@ Display and wait for response:
|
|
|
33
33
|
```
|
|
34
34
|
⚙️ MODEL CHECK
|
|
35
35
|
──────────────────────────────────────────────────────────────────
|
|
36
|
-
Recommended : claude-opus-4
|
|
36
|
+
Recommended : claude-opus-4 (or latest Opus model)
|
|
37
37
|
Why needed : Spec analysis, architecture review, code generation
|
|
38
38
|
require deep reasoning. Smaller models miss edge cases.
|
|
39
39
|
|
|
@@ -86,15 +86,17 @@ Wait for explicit "Y" or "N" from the user before continuing.
|
|
|
86
86
|
- "N" → stop and ask what the user wants to change.
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
*Note: For this command, there is no input file
|
|
89
|
+
*Note: For this command — **skip Gate Steps 1, 2, and 3** (there is no input file and no project context yet). Only run Step 0-B (model check). The project root is the **current working directory**. Proceed directly to the Precondition Check below.*
|
|
90
90
|
|
|
91
91
|
---
|
|
92
92
|
|
|
93
93
|
## Precondition Check
|
|
94
94
|
|
|
95
95
|
Check if already set up:
|
|
96
|
-
- If
|
|
97
|
-
-
|
|
96
|
+
- If `CLAUDE.md` **and** `.agent/project-context.yaml` both exist → ask: "This project is already initialized. Re-run setup to regenerate config files? (Y/N)"
|
|
97
|
+
- N → stop
|
|
98
|
+
- Y → continue (existing files will be preserved — each step will offer merge/skip)
|
|
99
|
+
- If only `specs/` exists or only partial setup detected → continue normally (safe to re-run)
|
|
98
100
|
|
|
99
101
|
## Step 1 — Create Directory Structure
|
|
100
102
|
|
|
@@ -106,8 +108,8 @@ Create these directories (skip if they exist):
|
|
|
106
108
|
│ ├── product-definition/
|
|
107
109
|
│ ├── prd/
|
|
108
110
|
│ ├── bdd/
|
|
111
|
+
│ ├── tech-docs/ ← technical design documents
|
|
109
112
|
│ └── domain-knowledge/ ← business dictionary & domain context
|
|
110
|
-
├── tech-docs/
|
|
111
113
|
├── .trace/
|
|
112
114
|
└── .agent/
|
|
113
115
|
└── review/
|
|
@@ -151,7 +153,7 @@ forbidden:
|
|
|
151
153
|
# §4. Traceability
|
|
152
154
|
# Every controller method must be tagged:
|
|
153
155
|
# @trace.implements={UC-ID}-{SC-ID}
|
|
154
|
-
# @trace.source=specs/bdd/{domain}/{UC-ID}.feature
|
|
156
|
+
# @trace.source=specs/bdd/{domain}/{UC-ID}.feature ← adjust if specs_dir differs in .agent/project-context.yaml
|
|
155
157
|
# Tests must be tagged:
|
|
156
158
|
# @trace.verifies={UC-ID}
|
|
157
159
|
|
|
@@ -171,7 +173,7 @@ commit_feature: "feat({{TICKET_PREFIX}}-{N}): {description}"
|
|
|
171
173
|
|
|
172
174
|
## Step 3 — Create project-context.yaml
|
|
173
175
|
|
|
174
|
-
Create `.agent/project-context.yaml` using
|
|
176
|
+
Create `.agent/project-context.yaml` using `.agent/templates/project-context.yaml` as the source template.
|
|
175
177
|
|
|
176
178
|
Copy the template and instruct: "Open `.agent/project-context.yaml` and fill in all `{{PLACEHOLDER}}` values. The `paths` section is pre-configured with sensible defaults — adjust if your project uses different directory names."
|
|
177
179
|
|
|
@@ -254,9 +256,25 @@ Create `specs/domain-knowledge/core-entities.md` if it does not exist:
|
|
|
254
256
|
|
|
255
257
|
Instruct: "Open `specs/domain-knowledge/core-entities.md` and define your key domain entities. Start with aggregate roots. This file is loaded by every AI command — good definitions here save significant back-and-forth during code generation."
|
|
256
258
|
|
|
257
|
-
## Step 6 —
|
|
259
|
+
## Step 6 — Install VS Code Extension (Recommended)
|
|
260
|
+
|
|
261
|
+
Recommend the user install the **Spec Driven Dev** VS Code extension — it provides Review Board + Living Documentation panels that integrate with this workflow.
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
code --install-extension edupia-team.spec-driven-dev-team
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Or: VS Code → `Ctrl+Shift+P` → **"Extensions: Install from Marketplace"** → search **Spec Driven Dev**.
|
|
268
|
+
|
|
269
|
+
**What it does:**
|
|
270
|
+
- 📋 **Review Board** — visual UI to review findings from `/refine-prd`, `/review-context`, `/review-tech-docs`
|
|
271
|
+
- 📊 **Living Documentation** — traceability dashboard driven by `.trace/*.tsv`
|
|
272
|
+
|
|
273
|
+
## Step 7 — Verify
|
|
258
274
|
|
|
259
275
|
- [ ] `specs/` exists
|
|
276
|
+
- [ ] `specs/bdd/` exists
|
|
277
|
+
- [ ] `specs/tech-docs/` exists
|
|
260
278
|
- [ ] `specs/domain-knowledge/` exists
|
|
261
279
|
- [ ] `.trace/` exists
|
|
262
280
|
- [ ] `.agent/project-context.yaml` exists
|
|
@@ -266,6 +284,62 @@ Instruct: "Open `specs/domain-knowledge/core-entities.md` and define your key do
|
|
|
266
284
|
|
|
267
285
|
## Output
|
|
268
286
|
|
|
287
|
+
# Report Footer — Standard Command Output Format
|
|
288
|
+
|
|
289
|
+
Every command report must end with this standard footer section.
|
|
290
|
+
|
|
291
|
+
## Status Badge
|
|
292
|
+
|
|
293
|
+
Choose one based on outcome:
|
|
294
|
+
- `✅ Complete` — all steps succeeded, no issues found
|
|
295
|
+
- `❌ Failed` — command could not complete due to a blocking error
|
|
296
|
+
- `⚠️ Warnings` — completed with non-blocking issues that should be reviewed
|
|
297
|
+
|
|
298
|
+
## Output Artifacts
|
|
299
|
+
|
|
300
|
+
List every file created or modified by this command:
|
|
301
|
+
```
|
|
302
|
+
Output Artifacts:
|
|
303
|
+
{created|updated} {file-path} ({brief description})
|
|
304
|
+
{created|updated} {file-path} ({brief description})
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
If no files were written (e.g., review or analysis commands) → write `Output Artifacts: none (read-only)`.
|
|
308
|
+
|
|
309
|
+
## Next Command Suggestion
|
|
310
|
+
|
|
311
|
+
Suggest the logical next command based on workflow phase:
|
|
312
|
+
|
|
313
|
+
| Current command | Suggest next |
|
|
314
|
+
|-------------------------|-----------------------------------------------|
|
|
315
|
+
| /setup-ai-first | `/define-product` to start your first feature |
|
|
316
|
+
| /define-product | `/generate-prd {product-definition-file}` |
|
|
317
|
+
| /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
|
|
318
|
+
| /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
|
|
319
|
+
| /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
|
|
320
|
+
| /generate-bdd | `/review-context {feature-file}` to verify coverage |
|
|
321
|
+
| /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
|
|
322
|
+
| /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
|
|
323
|
+
| /review-tech-docs | `/generate-code {feature-file}` if APPROVED; fix doc if NEEDS_FIX |
|
|
324
|
+
| /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/generate-tests {UC-ID}` |
|
|
325
|
+
| /generate-tests | `/run-tests {UC-ID}` |
|
|
326
|
+
| /run-tests (passing) | `/review-code {UC-ID}` |
|
|
327
|
+
| /run-tests (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
|
|
328
|
+
| /review-code | `/smoke-test {UC-ID}` or create PR |
|
|
329
|
+
| /smoke-test | Create PR and link to ticket |
|
|
330
|
+
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
|
|
331
|
+
| /fix-bug | Create PR and link to ticket |
|
|
332
|
+
| /debug | `/fix-bug {ticket-id}` if fix needed |
|
|
333
|
+
|
|
334
|
+
Format the footer as:
|
|
335
|
+
```
|
|
336
|
+
---
|
|
337
|
+
Status : {badge}
|
|
338
|
+
{Output Artifacts block}
|
|
339
|
+
Next : {suggested command with example arguments}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
|
|
269
343
|
```
|
|
270
344
|
/setup-ai-first Complete ✅
|
|
271
345
|
Next:
|
|
@@ -274,5 +348,7 @@ Next:
|
|
|
274
348
|
3. Fill specs/domain-knowledge/business-dictionary.md ← terminology rules
|
|
275
349
|
4. Fill specs/domain-knowledge/core-entities.md ← entity glossary for code gen
|
|
276
350
|
5. git add and commit those 4 files
|
|
277
|
-
6.
|
|
351
|
+
6. Install VS Code extension (if not yet installed):
|
|
352
|
+
code --install-extension edupia-team.spec-driven-dev-team
|
|
353
|
+
7. /define-product to start your first feature
|
|
278
354
|
```
|