@anhth2/spec-driven-dev-plugin 0.8.0 → 0.9.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 (89) hide show
  1. package/ARCHITECTURE.md +6 -2
  2. package/commands/debug.md +152 -0
  3. package/commands/debug.tmpl +16 -0
  4. package/commands/define-product.md +57 -0
  5. package/commands/fix-bug.md +153 -0
  6. package/commands/fix-bug.tmpl +17 -0
  7. package/commands/generate-bdd.md +277 -13
  8. package/commands/generate-bdd.tmpl +220 -13
  9. package/commands/generate-code.md +154 -2
  10. package/commands/generate-code.tmpl +97 -2
  11. package/commands/generate-design-spec.md +57 -0
  12. package/commands/generate-prd.md +75 -0
  13. package/commands/generate-prd.tmpl +18 -0
  14. package/commands/generate-spec-manifest.md +57 -0
  15. package/commands/generate-tech-docs.md +79 -1
  16. package/commands/generate-tech-docs.tmpl +22 -1
  17. package/commands/generate-tests.md +57 -0
  18. package/commands/learn.md +554 -0
  19. package/commands/learn.tmpl +63 -0
  20. package/commands/propose-scenario.md +521 -0
  21. package/commands/propose-scenario.tmpl +109 -0
  22. package/commands/refine-prd.md +57 -0
  23. package/commands/report-bug.md +543 -0
  24. package/commands/report-bug.tmpl +131 -0
  25. package/commands/review-code.md +153 -0
  26. package/commands/review-code.tmpl +17 -0
  27. package/commands/review-context.md +57 -0
  28. package/commands/review-tech-docs.md +139 -4
  29. package/commands/review-tech-docs.tmpl +82 -4
  30. package/commands/run-tests.md +82 -0
  31. package/commands/run-tests.tmpl +25 -0
  32. package/commands/setup-ai-first.md +15 -5
  33. package/commands/setup-ai-first.tmpl +10 -5
  34. package/commands/smoke-test.md +57 -0
  35. package/commands/sync.md +405 -0
  36. package/commands/sync.tmpl +345 -0
  37. package/commands/update-framework.md +211 -0
  38. package/commands/update-framework.tmpl +151 -0
  39. package/commands/validate-traces.md +115 -2
  40. package/commands/validate-traces.tmpl +58 -2
  41. package/core/FRAMEWORK_VERSION +1 -1
  42. package/core/commands/debug.md +152 -0
  43. package/core/commands/define-product.md +57 -0
  44. package/core/commands/fix-bug.md +153 -0
  45. package/core/commands/generate-bdd.md +277 -13
  46. package/core/commands/generate-code.md +154 -2
  47. package/core/commands/generate-design-spec.md +57 -0
  48. package/core/commands/generate-prd.md +75 -0
  49. package/core/commands/generate-spec-manifest.md +57 -0
  50. package/core/commands/generate-tech-docs.md +79 -1
  51. package/core/commands/generate-tests.md +57 -0
  52. package/core/commands/learn.md +554 -0
  53. package/core/commands/propose-scenario.md +521 -0
  54. package/core/commands/refine-prd.md +57 -0
  55. package/core/commands/report-bug.md +543 -0
  56. package/core/commands/review-code.md +153 -0
  57. package/core/commands/review-context.md +57 -0
  58. package/core/commands/review-tech-docs.md +139 -4
  59. package/core/commands/run-tests.md +82 -0
  60. package/core/commands/setup-ai-first.md +15 -5
  61. package/core/commands/smoke-test.md +57 -0
  62. package/core/commands/sync.md +405 -0
  63. package/core/commands/update-framework.md +211 -0
  64. package/core/commands/validate-traces.md +115 -2
  65. package/core/skills/code/SKILL.md +62 -0
  66. package/core/skills/debug/SKILL.md +67 -0
  67. package/core/skills/design-spec/SKILL.md +57 -0
  68. package/core/skills/discovery/SKILL.md +57 -0
  69. package/core/skills/prd/SKILL.md +10 -0
  70. package/core/skills/setup-ai-first/SKILL.md +5 -0
  71. package/core/skills/spec/SKILL.md +10 -0
  72. package/core/skills/test/SKILL.md +119 -0
  73. package/core/steps/capture-lesson.md +79 -0
  74. package/core/steps/context-loader.md +52 -0
  75. package/core/steps/report-footer.md +5 -0
  76. package/core/templates/project-context.yaml +11 -0
  77. package/package.json +1 -1
  78. package/skills/code/SKILL.md +62 -0
  79. package/skills/debug/SKILL.md +67 -0
  80. package/skills/design-spec/SKILL.md +57 -0
  81. package/skills/discovery/SKILL.md +57 -0
  82. package/skills/prd/SKILL.md +10 -0
  83. package/skills/setup-ai-first/SKILL.md +5 -0
  84. package/skills/spec/SKILL.md +10 -0
  85. package/skills/test/SKILL.md +119 -0
  86. package/steps/capture-lesson.md +79 -0
  87. package/steps/context-loader.md +52 -0
  88. package/steps/report-footer.md +5 -0
  89. package/templates/project-context.yaml +11 -0
@@ -178,6 +178,37 @@ If `services` section is present:
178
178
  - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
179
179
  - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
180
180
  - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
181
+ - Override `paths.bug_reports_dir` → `{spec_source}/feedback/bug-reports`
182
+ - Override `paths.bdd_proposals_dir` → `{spec_source}/feedback/bdd-proposals`
183
+
184
+ > **Why under `spec_source`:** tester feedback (`/report-bug`, `/propose-scenario`) must land in the **shared spec repo** so PO/Dev see it when they `/sync`. In single-service mode (no `spec_source`), these default to `feedback/bug-reports` and `feedback/bdd-proposals` at repo root — still shared, same repo.
185
+
186
+ ---
187
+
188
+ ## Step 1.6 — [SERVICE CONVENTIONS] Load service-specific conventions (umbrella mode)
189
+
190
+ *Skip this step entirely if `active_service` is `"unresolved"` or context is single-service mode.*
191
+
192
+ When `active_service` has been resolved to a real path in Step 1.5 (e.g., `user-service/`):
193
+
194
+ **1. Locate service config** — try in priority order:
195
+ - `{active_service}/.agent/project-context.yaml`
196
+ - `{active_service}/project-context.yaml`
197
+
198
+ **2. If found, override with service-specific values:**
199
+
200
+ | Variable | Source |
201
+ |----------|--------|
202
+ | `conventions.test_command` | service's `conventions.test_command` |
203
+ | `conventions.build_command` | service's `conventions.build_command` |
204
+ | `paths.trace_dir` | `{active_service}/{service paths.trace_dir}` — default: `{active_service}/.trace` |
205
+ | `paths.specs_dir` | `{active_service}/{service paths.specs_dir}` (if set in service config, else keep Step 1.5 override) |
206
+
207
+ **3. Store** `service_root = {active_service}` as the working directory anchor for all downstream commands:
208
+ - Shell commands (`/run-tests`, `/generate-tests`) run **from within** `service_root`
209
+ - File write operations (test files, trace TSVs) use paths **relative to** `service_root`
210
+
211
+ **4. If service config not found** — keep umbrella defaults, still set `service_root = {active_service}` (path anchor is always needed even without a config override).
181
212
 
182
213
  ---
183
214
 
@@ -271,6 +302,25 @@ These two variables (`active_module`, `platform_type`) are the canonical source
271
302
 
272
303
  ---
273
304
 
305
+ ## Step 6.7 — [GUARDRAILS] Load Project Lessons (conditional)
306
+
307
+ *Accumulated mistakes the AI must not repeat in this project. These are added over time via `/learn`
308
+ or accepted during `/review-code`, `/fix-bug`, `/debug`.*
309
+
310
+ Resolve the lessons file path:
311
+ - Use `paths.lessons_file` if set (may be service-overridden in umbrella mode, Step 1.6)
312
+ - Else default `specs/domain-knowledge/lessons-learned.md`
313
+ - In umbrella/service mode (when `service_root` is set), if `paths.lessons_file` is unset, default to `{service_root}/.agent/project-lessons.md`
314
+
315
+ If the file exists, read it and store ALL lessons as **ACTIVE GUARDRAILS** for the session:
316
+ - Treat each lesson's **Rule** as a hard constraint — same priority as CLAUDE.md coding standards (Step 3).
317
+ - Before generating or modifying any artifact (PRD, BDD, tech-doc, code, test), check the output against every lesson whose `category` matches the current command AND whose `scope` matches the target (domain / file).
318
+ - If a generated output would violate a lesson → correct it **before** presenting, and note which lesson (`L-NNN`) was applied.
319
+
320
+ If the file does not exist → skip silently (no lessons captured yet).
321
+
322
+ ---
323
+
274
324
  ## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
275
325
 
276
326
  After loading all context, synthesize and output a compact summary block.
@@ -286,7 +336,9 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
286
336
  Ticket : {ticket_prefix}-
287
337
  Dict : {loaded — N canonical terms, M banned terms | missing}
288
338
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
339
+ Lessons : {loaded — N guardrails | none yet}
289
340
  Service : {active_service} ({active_service_module}) | single-service
341
+ Svc Root : {service_root} — conventions + trace_dir loaded from service config | —
290
342
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
291
343
  ```
292
344
 
@@ -410,6 +462,101 @@ git commit -m "fix({TICKET_ID}): {description}"
410
462
  git push -u origin fix/{TICKET_ID}-{slug}
411
463
  ```
412
464
 
465
+ ## Phase 6 — Offer to Record a Lesson (optional)
466
+
467
+ If the root cause was a **mistake the AI made during generation and could repeat**
468
+ (e.g. it generated code that skipped a layer, missed a null guard, used a wrong pattern —
469
+ NOT an external cause like a third-party outage or bad input data), ask:
470
+
471
+ ```
472
+ This root cause looks like a repeatable AI mistake.
473
+ Record it as a project lesson so it isn't generated again? (Y/N)
474
+ ```
475
+
476
+ If `Y` → run the capture procedure below with `source=/fix-bug {TICKET_ID}`, an appropriate
477
+ `category` (usually `code-gen`), and `scope` = the affected domain or file glob.
478
+
479
+ # Capture Lesson — Record a Recurring Mistake as a Guardrail
480
+
481
+ Reusable procedure to persist a "lesson" so the AI does not repeat a mistake in this project.
482
+ Used by `/learn` (manual) and offered by `/review-code`, `/fix-bug`, `/debug` (auto).
483
+
484
+ > **Project memory, not model training.** A lesson is plain text injected into context at the
485
+ > start of every command (context-loader Step 6.7). Functionally this stops the repeat — the AI
486
+ > sees the guardrail before it generates. No model weights change.
487
+
488
+ ## L1 — Resolve the lessons file
489
+
490
+ Resolve `lessons_path` in this order:
491
+ 1. `paths.lessons_file` from loaded context (may be service-overridden in umbrella mode, Step 1.6)
492
+ 2. Default `specs/domain-knowledge/lessons-learned.md` (single-service)
493
+ 3. In umbrella/service mode (when `service_root` is set) default `{service_root}/.agent/project-lessons.md`
494
+
495
+ ## L2 — Build the lesson
496
+
497
+ Gather these fields — from `$ARGUMENTS` (for `/learn`) or from the calling command's findings
498
+ (for `/review-code`, `/fix-bug`, `/debug`):
499
+
500
+ | Field | Meaning |
501
+ |-------|---------|
502
+ | `category` | one of: `code-gen` \| `bdd` \| `tech-docs` \| `tests` \| `prd` \| `general` |
503
+ | `title` | short phrase naming the mistake |
504
+ | `mistake` | concretely, what the AI did wrong |
505
+ | `rule` | imperative correction — "Always …" / "Never …" — testable, not vague |
506
+ | `scope` | where it applies: a domain, a file glob (e.g. `*Controller.*`), or `all` |
507
+ | `source` | how captured: `/learn` \| `/review-code {UC-ID}` \| `/fix-bug {TICKET}` \| `/debug` |
508
+
509
+ If `rule` is vague (e.g. "be careful"), rewrite it into a concrete, checkable instruction before saving.
510
+
511
+ ## L3 — De-duplicate
512
+
513
+ Read existing lessons in `lessons_path`. If one already covers the same mistake:
514
+ - **Refine** that entry (tighten the Rule, widen/narrow Scope, bump Date, append the new Source) — do NOT add a duplicate.
515
+
516
+ Otherwise assign the next id `L-{NNN}` = (highest existing number + 1), zero-padded to 3 digits.
517
+
518
+ ## L4 — Write
519
+
520
+ If `lessons_path` does not exist, create it with this header first:
521
+
522
+ ```markdown
523
+ # Project Lessons — Learned Guardrails
524
+
525
+ > Mistakes the AI must NOT repeat in this project. Loaded by context-loader at the start of
526
+ > every command and treated as hard constraints (same priority as CLAUDE.md coding standards).
527
+ > Add with /learn, or accept the prompt during /review-code, /fix-bug, /debug.
528
+ > Commit this file so the whole team shares the guardrails.
529
+
530
+ | Category | Applies to |
531
+ |----------|-----------|
532
+ | code-gen | /generate-code output |
533
+ | bdd | /generate-bdd output |
534
+ | tech-docs | /generate-tech-docs output |
535
+ | tests | /generate-tests output |
536
+ | prd | /generate-prd, /refine-prd output |
537
+ | general | every command |
538
+
539
+ ---
540
+ ```
541
+
542
+ Insert the new lesson directly under the `---` separator (**newest first**), in this exact shape:
543
+
544
+ ```markdown
545
+ ### L-{NNN} — [{category}] {title}
546
+ - **Date**: {today YYYY-MM-DD}
547
+ - **Scope**: {scope}
548
+ - **Mistake**: {mistake}
549
+ - **Rule**: {rule}
550
+ - **Source**: {source}
551
+
552
+ ```
553
+
554
+ ## L5 — Confirm
555
+
556
+ Print: `📝 Lesson {id} recorded → {lessons_path} ([{category}] {title})`
557
+ Then remind: `Commit {lessons_path} so the team shares this guardrail.`
558
+
559
+
413
560
  ## Output
414
561
 
415
562
  # Report Footer — Standard Command Output Format
@@ -459,6 +606,11 @@ Suggest the logical next command based on workflow phase:
459
606
  | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
460
607
  | /fix-bug | Create PR and link to ticket |
461
608
  | /debug | `/fix-bug {ticket-id}` if fix needed |
609
+ | /report-bug | Send to dev (`/fix-bug {BUG-ID}`); if coverage gap → `/propose-scenario {UC-ID}` |
610
+ | /propose-scenario | Notify PO/Dev to review the proposal in `feedback/bdd-proposals/` |
611
+ | /learn | Continue working — lesson applies on next command |
612
+ | /sync | `/validate-traces` for full coverage; act on any `📥 tester feedback` surfaced |
613
+ | /update-framework | Review `git diff .agent/`, commit; `/sync` for project content |
462
614
 
463
615
  Format the footer as:
464
616
  ```
@@ -474,6 +626,7 @@ Next : {suggested command with example arguments}
474
626
  Root Cause: {analysis}
475
627
  Changes: {list}
476
628
  ✅ Regression test added | ✅ Build: SUCCESS
629
+ {📝 Lesson L-NNN recorded (if captured)}
477
630
  Branch: fix/{TICKET_ID}-{slug}
478
631
  Next: Create PR and link to ticket.
479
632
  ```
@@ -176,6 +176,37 @@ If `services` section is present:
176
176
  - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
177
177
  - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
178
178
  - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
179
+ - Override `paths.bug_reports_dir` → `{spec_source}/feedback/bug-reports`
180
+ - Override `paths.bdd_proposals_dir` → `{spec_source}/feedback/bdd-proposals`
181
+
182
+ > **Why under `spec_source`:** tester feedback (`/report-bug`, `/propose-scenario`) must land in the **shared spec repo** so PO/Dev see it when they `/sync`. In single-service mode (no `spec_source`), these default to `feedback/bug-reports` and `feedback/bdd-proposals` at repo root — still shared, same repo.
183
+
184
+ ---
185
+
186
+ ## Step 1.6 — [SERVICE CONVENTIONS] Load service-specific conventions (umbrella mode)
187
+
188
+ *Skip this step entirely if `active_service` is `"unresolved"` or context is single-service mode.*
189
+
190
+ When `active_service` has been resolved to a real path in Step 1.5 (e.g., `user-service/`):
191
+
192
+ **1. Locate service config** — try in priority order:
193
+ - `{active_service}/.agent/project-context.yaml`
194
+ - `{active_service}/project-context.yaml`
195
+
196
+ **2. If found, override with service-specific values:**
197
+
198
+ | Variable | Source |
199
+ |----------|--------|
200
+ | `conventions.test_command` | service's `conventions.test_command` |
201
+ | `conventions.build_command` | service's `conventions.build_command` |
202
+ | `paths.trace_dir` | `{active_service}/{service paths.trace_dir}` — default: `{active_service}/.trace` |
203
+ | `paths.specs_dir` | `{active_service}/{service paths.specs_dir}` (if set in service config, else keep Step 1.5 override) |
204
+
205
+ **3. Store** `service_root = {active_service}` as the working directory anchor for all downstream commands:
206
+ - Shell commands (`/run-tests`, `/generate-tests`) run **from within** `service_root`
207
+ - File write operations (test files, trace TSVs) use paths **relative to** `service_root`
208
+
209
+ **4. If service config not found** — keep umbrella defaults, still set `service_root = {active_service}` (path anchor is always needed even without a config override).
179
210
 
180
211
  ---
181
212
 
@@ -269,6 +300,25 @@ These two variables (`active_module`, `platform_type`) are the canonical source
269
300
 
270
301
  ---
271
302
 
303
+ ## Step 6.7 — [GUARDRAILS] Load Project Lessons (conditional)
304
+
305
+ *Accumulated mistakes the AI must not repeat in this project. These are added over time via `/learn`
306
+ or accepted during `/review-code`, `/fix-bug`, `/debug`.*
307
+
308
+ Resolve the lessons file path:
309
+ - Use `paths.lessons_file` if set (may be service-overridden in umbrella mode, Step 1.6)
310
+ - Else default `specs/domain-knowledge/lessons-learned.md`
311
+ - In umbrella/service mode (when `service_root` is set), if `paths.lessons_file` is unset, default to `{service_root}/.agent/project-lessons.md`
312
+
313
+ If the file exists, read it and store ALL lessons as **ACTIVE GUARDRAILS** for the session:
314
+ - Treat each lesson's **Rule** as a hard constraint — same priority as CLAUDE.md coding standards (Step 3).
315
+ - Before generating or modifying any artifact (PRD, BDD, tech-doc, code, test), check the output against every lesson whose `category` matches the current command AND whose `scope` matches the target (domain / file).
316
+ - If a generated output would violate a lesson → correct it **before** presenting, and note which lesson (`L-NNN`) was applied.
317
+
318
+ If the file does not exist → skip silently (no lessons captured yet).
319
+
320
+ ---
321
+
272
322
  ## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
273
323
 
274
324
  After loading all context, synthesize and output a compact summary block.
@@ -284,7 +334,9 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
284
334
  Ticket : {ticket_prefix}-
285
335
  Dict : {loaded — N canonical terms, M banned terms | missing}
286
336
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
337
+ Lessons : {loaded — N guardrails | none yet}
287
338
  Service : {active_service} ({active_service_module}) | single-service
339
+ Svc Root : {service_root} — conventions + trace_dir loaded from service config | —
288
340
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
289
341
  ```
290
342
 
@@ -306,6 +358,194 @@ After completing all steps, you have loaded:
306
358
  Proceed to the next step of the calling command.
307
359
 
308
360
 
361
+ > **Tester proposals (optional input):** before generating, check `{paths.bdd_proposals_dir}/` (default `{spec_source}/feedback/bdd-proposals/`) for scenarios proposed by testers via `/propose-scenario` that map to this UC's ACs. Incorporate any the PO/Dev has accepted — then the tester's draft is removed/archived from `feedback/`. Skip if the folder is empty.
362
+
363
+ ---
364
+
365
+ ## Repo Mode Detection
366
+
367
+ After loading context, determine which mode to operate in:
368
+
369
+ - **Spec repo mode**: `project-context.yaml` has NO `services` section OR `setup.mode: spec`
370
+ - **Umbrella mode**: `project-context.yaml` HAS `services` section AND `setup.mode: umbrella`
371
+
372
+ → Spec repo mode → proceed to **Platform Selection** below (skip Service Detection)
373
+ → Umbrella mode → proceed to **Service Detection** below (skip Platform Selection)
374
+
375
+ ---
376
+
377
+ ## Platform Selection (Spec Repo Mode Only)
378
+
379
+ *Skip this section if running in umbrella mode.*
380
+
381
+ Ask the user to select the target platform:
382
+
383
+ ```
384
+ Which platform is this BDD for?
385
+ 1. web — FE/Web (React, Next.js, Angular, Vue, Nuxt)
386
+ 2. app — Mobile (Flutter, React Native, iOS, Android)
387
+ 3. system — System/BE BDD (synthesized from existing web + app BDDs)
388
+ ```
389
+
390
+ Wait for user selection. Set `active_platform` = chosen value.
391
+
392
+ **Output path (spec repo mode):**
393
+ `{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC{N}-{slug}.feature`
394
+
395
+ **Platform vocabulary:**
396
+
397
+ | Platform | "user action" | "type/input" | "observe" | "navigate" |
398
+ |---|---|---|---|---|
399
+ | web | "clicks" | "types into" / "enters" | "sees" / "the page shows" | "navigates to" / "goes to" |
400
+ | app | "taps" | "enters" / "inputs" | "sees" / "the screen shows" | "navigates to" / "opens" |
401
+ | system | N/A — use business events | — | "the system returns" / "receives response" | — |
402
+
403
+ ---
404
+
405
+ ## System BDD Synthesis (active_platform = system)
406
+
407
+ *Only applies when platform = system. Skip for web and app.*
408
+
409
+ ### Step S0 — Brownfield Check
410
+
411
+ Check the source PRD Metadata table for `| **API Source** | existing |`.
412
+
413
+ **Nếu `API Source: existing`:**
414
+ - API contract đã được PO ghi trong phần "Existing API Contract" của PRD.
415
+ - **Skip Steps S1–S3** — không cần scan FE/App BDD, không cần conflict resolution.
416
+ - Dùng bảng "Existing API Contract" trong PRD làm contract input cho Step S4.
417
+ - Set `# @trace.api_source: existing` trong header của file system BDD được gen.
418
+
419
+ **Nếu `API Source` không có hoặc không phải `existing`:**
420
+ - Tiếp tục Steps S1–S3 (normal synthesis flow).
421
+
422
+ ---
423
+
424
+ ### Step S1 — Scan available FE/App BDDs
425
+
426
+ Search for existing BDDs for this TICKET-ID:
427
+ - Web BDDs: `{paths.specs_dir}/{domain}/web/{TICKET-ID}-*.feature`
428
+ - App BDDs: `{paths.specs_dir}/{domain}/app/{TICKET-ID}-*.feature`
429
+
430
+ Classify the feature:
431
+
432
+ | Condition | Mode |
433
+ |---|---|
434
+ | Both web + app BDDs found | **Multi-platform** — synthesize from both |
435
+ | Only web BDD found | **Web-only** — synthesize from web |
436
+ | Only app BDD found | **App-only** — synthesize from app |
437
+ | No FE/App BDDs found | **Backend-only** — gen directly from PRD |
438
+
439
+ ---
440
+
441
+ ### Step S2 — Extract expected contracts per platform
442
+
443
+ For each found BDD file, extract:
444
+ - **Triggers**: what user actions call the backend? (map to logical "request" events)
445
+ - **Expected response data**: what fields/shape does each `Then` clause need from the system?
446
+ - **Error signals**: what error states must the backend signal?
447
+ - **Business rules**: what invariants does each platform assume the system enforces?
448
+
449
+ ---
450
+
451
+ ### Step S3 — Cross-Platform Conflict Check (multi-platform mode only)
452
+
453
+ *Skip if web-only, app-only, or backend-only.*
454
+
455
+ Compare the extracted contracts across platforms. Flag a conflict if any of these differ:
456
+
457
+ | Conflict type | Example |
458
+ |---|---|
459
+ | **Response shape mismatch** | Web expects `{ token, redirect_url }`, App expects `{ token, user_profile }` |
460
+ | **Error semantics mismatch** | Web expects HTTP 423 for lock, App expects custom error code `ACC_LOCKED` |
461
+ | **Business rule contradiction** | Web BDD says "lock after 5 attempts", App BDD says "lock after 3 attempts" |
462
+ | **Data field conflict** | Web expects `expires_in: seconds`, App expects `expires_at: ISO timestamp` |
463
+
464
+ **If conflicts detected → CHECKPOINT (mandatory, cannot skip):**
465
+
466
+ ```
467
+ ⚠️ CROSS-PLATFORM CONTRACT CONFLICT
468
+ ──────────────────────────────────────────────────────────────────
469
+ Feature : {TICKET-ID} — {UC name}
470
+
471
+ Conflict 1: Response shape mismatch
472
+ Web BDD (Then): user sees dashboard → implies { token, redirect_url }
473
+ App BDD (Then): app navigates to HomeScreen → implies { token, user_profile }
474
+
475
+ Resolution options:
476
+ A — Union response
477
+ BE returns all fields: { token, redirect_url, user_profile }
478
+ Clients ignore fields they don't use. Simple, slight over-fetch.
479
+ B — Platform hint in request
480
+ Client sends X-Platform: web|app in header, BE tailors response.
481
+ Cleaner responses, more BE logic.
482
+ C — Separate endpoints
483
+ POST /auth/login/web and POST /auth/login/app
484
+ Maximum flexibility, more endpoints to maintain.
485
+ D — Custom: describe your approach
486
+ ──────────────────────────────────────────────────────────────────
487
+ Choose resolution for each conflict (A/B/C/D):
488
+ ```
489
+
490
+ Wait for PO's resolution per conflict. Record each decision as a `# @system.resolution:` annotation in the generated system BDD file.
491
+
492
+ **If no conflicts → proceed to Step S4 directly.**
493
+
494
+ ---
495
+
496
+ ### Step S4 — Generate System BDD scenarios
497
+
498
+ Generate scenarios based on mode and resolved conflicts:
499
+
500
+ - **Multi-platform**: synthesize from both web + app contracts, applying resolved resolutions
501
+ - **Web-only / App-only**: derive from the single platform's contracts
502
+ - **Backend-only**: derive directly from PRD AC/BR using business event language (not HTTP)
503
+
504
+ System BDD step vocabulary (always use — regardless of FE/App vocabulary):
505
+ - Triggers: "the system receives {event}" / "a {actor} submits {action}"
506
+ - Assertions: "the system returns {data}" / "the system signals {error}" / "the system stores {state}"
507
+ - Do NOT use UI words (click, tap, see, navigate) in system BDD
508
+
509
+ **If multi-platform with resolution A (union):**
510
+ - System BDD shows the full response contract: all fields from all platforms
511
+ - Add comment: `# @system.resolution: union — clients receive all fields`
512
+
513
+ **If resolution B (platform hint):**
514
+ - Write separate `Scenario Outline` using Examples table for `web` vs `app` response variants
515
+ - Add comment: `# @system.resolution: platform-hint — X-Platform header determines response shape`
516
+
517
+ **If resolution C (separate endpoints):**
518
+ - Write separate Scenarios for each endpoint
519
+ - Note the endpoint split explicitly in the SCOPE section
520
+
521
+ ---
522
+
523
+ ## Service Detection (Umbrella Mode Only)
524
+
525
+ *Skip this section if running in spec repo mode.*
526
+
527
+ Read the PRD Metadata table for `| **Service** |` and `| **Module** |` rows.
528
+
529
+ | Condition | Action |
530
+ |---|---|
531
+ | PRD has `Service` row AND value is not "default" | Use it as `active_service` + `active_module`. Load catalog for that module. |
532
+ | PRD has no `Service` row AND `services` defined in project-context.yaml | Ask: "Which service is this BDD for?" (list services, wait for selection) |
533
+ | Single-service project (no `services` array) | `active_service = "default"`, `active_module = tech_stack.module` |
534
+
535
+ **Output path (umbrella mode):**
536
+ - `active_service = "default"` → `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`
537
+ - `active_service ≠ "default"` → `{paths.specs_dir}/{domain}/{active_service}/{TICKET-ID}-UC{N}-{slug}.feature`
538
+
539
+ **Platform vocabulary** — adapt BDD step wording based on `active_module`:
540
+
541
+ | Platform type | Modules | "click" | "type" | "see" | "navigate" |
542
+ |---|---|---|---|---|---|
543
+ | Web | react, nextjs, vue, nuxt, angular | "clicks" | "types into" / "enters" | "sees" / "the page shows" | "navigates to" / "goes to" |
544
+ | Mobile | flutter, react-native, ios-swiftui, android-compose | "taps" | "enters" / "inputs" | "sees" / "the screen shows" | "navigates to" / "opens" |
545
+ | Backend / API | java-spring, golang, dotnet, php-laravel | *(no UI steps — use)* "submits a request" / "calls the API" | — | "receives response" / "the system returns" | — |
546
+
547
+ Apply this vocabulary silently when writing Gherkin steps. Do NOT mix web and mobile terms in the same feature file.
548
+
309
549
  ---
310
550
 
311
551
  ## Orchestration Check
@@ -342,7 +582,9 @@ After generating all `.feature` and `.tsv` files for the assigned UC, return the
342
582
 
343
583
  Before generating, check for existing `.feature` files for this PRD:
344
584
 
345
- 1. Look for `{paths.specs_dir}/{domain}/{TICKET-ID}-UC*.feature`.
585
+ 1. Resolve the search path based on mode:
586
+ - **Spec repo mode**: `{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC*.feature`
587
+ - **Umbrella mode**: `{paths.specs_dir}/{domain}/{TICKET-ID}-UC*.feature` (or with `{active_service}/` if multi-service)
346
588
  2. Read current PRD `| **Version** |` from metadata (e.g., `1.2`).
347
589
 
348
590
  **If no existing feature files** → fresh generation, proceed normally. Use PRD version as `@trace.prd_version`.
@@ -445,7 +687,12 @@ CHECKPOINT: "Does this outline look correct? Do you want to add or remove any SC
445
687
 
446
688
  ## Generate
447
689
 
448
- For each UC, write `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`:
690
+ **Output path by mode:**
691
+ - **Spec repo mode**: `{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC{N}-{slug}.feature`
692
+ - **Umbrella mode (single-service)**: `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`
693
+ - **Umbrella mode (multi-service)**: `{paths.specs_dir}/{domain}/{active_service}/{TICKET-ID}-UC{N}-{slug}.feature`
694
+
695
+ For each UC, write to the resolved path above. Use vocabulary for the active platform (from Platform Selection or Service Detection).
449
696
 
450
697
  ```gherkin
451
698
  # ============================================================
@@ -453,8 +700,9 @@ For each UC, write `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`
453
700
  # @trace.title: <Feature name>
454
701
  # @trace.revision: 1 ← static field; use @trace.bdd_version for version tracking (incremented by /review-context --fix or --resume)
455
702
  # @trace.domain: <domain>
456
- # @trace.service: <ServiceName>
457
- # @trace.module: {tech_stack.module value e.g. java-spring | react | flutter; write "unknown" if not set in project-context.yaml}
703
+ # @trace.platform: {active_platform — web | app | system | (omit in umbrella mode)}
704
+ # @trace.service: {active_serviceomit in spec repo mode}
705
+ # @trace.module: {active_module in umbrella mode; "unknown" in spec repo mode}
458
706
  # @trace.status: draft
459
707
  # @trace.author: AI-generated
460
708
  # @trace.created_at: {YYYY-MM-DD}
@@ -562,7 +810,7 @@ After generating all `.feature` files, create or update `{paths.trace_dir}/{UC-I
562
810
 
563
811
  **TSV columns (tab-separated, one header row + one data row per scenario):**
564
812
  ```
565
- sc_id\tsc_title\tspec_ver\tgen_ver\timplemented_by\ttest_count\ttest_classes\tprd_version\tbdd_version\ttech_doc_revision\tprd_status\tuc_status\tstatus\tlast_updated
813
+ sc_id\tsc_title\tspec_ver\tgen_ver\timplemented_by\ttest_count\ttest_classes\tprd_version\tbdd_version\ttech_doc_revision\tprd_status\tuc_status\tfe_phase\tstatus\tlast_updated
566
814
  ```
567
815
 
568
816
  **Rules:**
@@ -589,6 +837,7 @@ sc_id\tsc_title\tspec_ver\tgen_ver\timplemented_by\ttest_count\ttest_classes\tpr
589
837
  | `tech_doc_revision` | `—` |
590
838
  | `prd_status` | read `\| **Status** \|` from PRD metadata |
591
839
  | `uc_status` | `draft` for new UCs; keep existing value for re-gen |
840
+ | `fe_phase` | `—` (set by `/generate-code --phase` when FE implements) |
592
841
  | `status` | `UNTRACKED` |
593
842
  | `last_updated` | today `YYYY-MM-DD` |
594
843
 
@@ -641,6 +890,11 @@ Suggest the logical next command based on workflow phase:
641
890
  | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
642
891
  | /fix-bug | Create PR and link to ticket |
643
892
  | /debug | `/fix-bug {ticket-id}` if fix needed |
893
+ | /report-bug | Send to dev (`/fix-bug {BUG-ID}`); if coverage gap → `/propose-scenario {UC-ID}` |
894
+ | /propose-scenario | Notify PO/Dev to review the proposal in `feedback/bdd-proposals/` |
895
+ | /learn | Continue working — lesson applies on next command |
896
+ | /sync | `/validate-traces` for full coverage; act on any `📥 tester feedback` surfaced |
897
+ | /update-framework | Review `git diff .agent/`, commit; `/sync` for project content |
644
898
 
645
899
  Format the footer as:
646
900
  ```
@@ -653,16 +907,26 @@ Next : {suggested command with example arguments}
653
907
 
654
908
  ```
655
909
  /generate-bdd Complete
910
+
911
+ [Spec repo mode — platform: {active_platform}]
656
912
  Files:
657
- {paths.specs_dir}/{domain}/{TICKET-ID}-UC1-{slug}.feature ({N} scenarios)
658
- {paths.specs_dir}/{domain}/{TICKET-ID}-UC2-{slug}.feature ({N} scenarios)
913
+ {paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC1-{slug}.feature ({N} scenarios)
914
+ {paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC2-{slug}.feature ({N} scenarios)
659
915
  Trace:
660
916
  {paths.trace_dir}/{TICKET-ID}-UC1.tsv ({N} rows)
661
917
  {paths.trace_dir}/{TICKET-ID}-UC2.tsv ({N} rows)
662
- Next: Run /review-context on EACH generated feature file (one per UC):
663
- /review-context {paths.specs_dir}/{domain}/{TICKET-ID}-UC1-{slug}.feature
664
- /review-context {paths.specs_dir}/{domain}/{TICKET-ID}-UC2-{slug}.feature
665
- ...
666
- → then per UC: /generate-tech-docs {feature-file} (if tech design required)
667
- or per UC: /generate-code {feature-file} (if skipping tech design)
918
+ Next (spec repo):
919
+ → Run /generate-bdd again for other platforms (web → app → system)
920
+ After all platforms generated: commit + push + notify dev team
921
+ → Dev team reads BDD from spec submodule — no /generate-bdd on their side
922
+
923
+ [Umbrella mode — service: {active_service}]
924
+ Files:
925
+ {paths.specs_dir}/{domain}/{TICKET-ID}-UC1-{slug}.feature ({N} scenarios)
926
+ Trace:
927
+ {paths.trace_dir}/{TICKET-ID}-UC1.tsv ({N} rows)
928
+ Next (umbrella):
929
+ → /review-context {feature-file} to verify coverage
930
+ → /generate-tech-docs {feature-file}
931
+ → /generate-code {feature-file}
668
932
  ```