@anhth2/spec-driven-dev-plugin 0.9.2 → 0.10.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 (94) hide show
  1. package/ARCHITECTURE.md +20 -9
  2. package/commands/debug.md +12 -12
  3. package/commands/define-product.md +11 -11
  4. package/commands/{generate-tests.md → dev-gen-test.md} +47 -15
  5. package/commands/{generate-tests.tmpl → dev-gen-test.tmpl} +18 -4
  6. package/{core/commands/run-tests.md → commands/dev-run-test.md} +61 -13
  7. package/commands/{run-tests.tmpl → dev-run-test.tmpl} +32 -2
  8. package/{core/commands/smoke-test.md → commands/dev-smoke-test.md} +16 -16
  9. package/commands/{smoke-test.tmpl → dev-smoke-test.tmpl} +5 -5
  10. package/commands/fix-bug.md +12 -12
  11. package/commands/generate-bdd.md +38 -13
  12. package/commands/generate-bdd.tmpl +9 -2
  13. package/commands/generate-code.md +85 -15
  14. package/commands/generate-code.tmpl +56 -4
  15. package/commands/generate-design-spec.md +104 -39
  16. package/commands/generate-design-spec.tmpl +93 -28
  17. package/commands/generate-prd.md +11 -11
  18. package/commands/generate-spec-manifest.md +11 -11
  19. package/commands/generate-tech-docs.md +12 -12
  20. package/commands/generate-tech-docs.tmpl +1 -1
  21. package/commands/learn.md +12 -12
  22. package/commands/propose-scenario.md +12 -12
  23. package/commands/propose-scenario.tmpl +1 -1
  24. package/commands/refine-prd.md +165 -16
  25. package/commands/refine-prd.tmpl +16 -5
  26. package/commands/report-bug.md +11 -11
  27. package/commands/review-code.md +13 -13
  28. package/commands/review-code.tmpl +1 -1
  29. package/commands/review-context.md +160 -12
  30. package/commands/review-context.tmpl +11 -1
  31. package/commands/review-tech-docs.md +11 -11
  32. package/commands/setup-ai-first.md +7 -7
  33. package/commands/sync.md +23 -20
  34. package/commands/sync.tmpl +16 -13
  35. package/commands/update-framework.md +7 -7
  36. package/commands/validate-traces.md +56 -37
  37. package/commands/validate-traces.tmpl +45 -26
  38. package/core/FRAMEWORK_VERSION +1 -1
  39. package/core/commands/debug.md +12 -12
  40. package/core/commands/define-product.md +11 -11
  41. package/core/commands/{generate-tests.md → dev-gen-test.md} +47 -15
  42. package/{commands/run-tests.md → core/commands/dev-run-test.md} +61 -13
  43. package/{commands/smoke-test.md → core/commands/dev-smoke-test.md} +16 -16
  44. package/core/commands/fix-bug.md +12 -12
  45. package/core/commands/generate-bdd.md +38 -13
  46. package/core/commands/generate-code.md +85 -15
  47. package/core/commands/generate-design-spec.md +104 -39
  48. package/core/commands/generate-prd.md +11 -11
  49. package/core/commands/generate-spec-manifest.md +11 -11
  50. package/core/commands/generate-tech-docs.md +12 -12
  51. package/core/commands/learn.md +12 -12
  52. package/core/commands/propose-scenario.md +12 -12
  53. package/core/commands/refine-prd.md +165 -16
  54. package/core/commands/report-bug.md +11 -11
  55. package/core/commands/review-code.md +13 -13
  56. package/core/commands/review-context.md +160 -12
  57. package/core/commands/review-tech-docs.md +11 -11
  58. package/core/commands/setup-ai-first.md +7 -7
  59. package/core/commands/sync.md +23 -20
  60. package/core/commands/update-framework.md +7 -7
  61. package/core/commands/validate-traces.md +56 -37
  62. package/core/skills/code/SKILL.md +18 -18
  63. package/core/skills/debug/SKILL.md +26 -26
  64. package/core/skills/design-spec/SKILL.md +11 -11
  65. package/core/skills/discovery/SKILL.md +11 -11
  66. package/core/skills/prd/SKILL.md +14 -14
  67. package/core/skills/setup-ai-first/SKILL.md +7 -7
  68. package/core/skills/spec/SKILL.md +14 -14
  69. package/core/skills/test/SKILL.md +38 -38
  70. package/core/steps/capture-lesson.md +1 -1
  71. package/core/steps/context-loader.md +4 -4
  72. package/core/steps/report-footer.md +7 -7
  73. package/core/steps/review-fanout.md +138 -0
  74. package/core/steps/spawn-agent.md +1 -1
  75. package/core/steps/trace-mirror.md +18 -0
  76. package/core/templates/design-spec.template.md +16 -8
  77. package/package.json +1 -1
  78. package/skills/code/SKILL.md +18 -18
  79. package/skills/debug/SKILL.md +26 -26
  80. package/skills/debug/SKILL.tmpl +1 -1
  81. package/skills/design-spec/SKILL.md +11 -11
  82. package/skills/discovery/SKILL.md +11 -11
  83. package/skills/prd/SKILL.md +14 -14
  84. package/skills/setup-ai-first/SKILL.md +7 -7
  85. package/skills/spec/SKILL.md +14 -14
  86. package/skills/test/SKILL.md +38 -38
  87. package/skills/test/SKILL.tmpl +9 -9
  88. package/steps/capture-lesson.md +1 -1
  89. package/steps/context-loader.md +4 -4
  90. package/steps/report-footer.md +7 -7
  91. package/steps/review-fanout.md +138 -0
  92. package/steps/spawn-agent.md +1 -1
  93. package/steps/trace-mirror.md +18 -0
  94. package/templates/design-spec.template.md +16 -8
@@ -27,6 +27,7 @@ Read:
27
27
  1. The scoped `.feature` file only
28
28
  2. Tech-doc at `{paths.tech_docs_dir}/{domain}/{UC-ID}-tech-design.md` (if exists)
29
29
  3. CLAUDE.md §architecture + §coding_standards
30
+ 4. **(FE/App only)** Design Spec at `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-*{slug}.md` (if exists) — source of screens, component inventory, and the per-screen Figma frame links.
30
31
 
31
32
  ---
32
33
 
@@ -50,6 +51,51 @@ Load System BDD for this UC: find `{specs_dir}/{domain}/system/{TICKET-ID}*.feat
50
51
  Extract all `Then` clauses → collect implied response shapes and error states.
51
52
  If System BDD not found → warn: "System BDD not found — mock layer will use placeholder fixtures." Continue.
52
53
 
54
+ **Then run the Figma Dev Mode MCP Check below** before generating any UI — the Design
55
+ Spec's frame links are the visual contract, and the local MCP reads them with far more
56
+ fidelity than a plain web link.
57
+
58
+ ---
59
+
60
+ ## Figma Dev Mode MCP Check *(FE/App UI generation only)*
61
+
62
+ *Run this only when `platform` is `web`/`app` AND generating UI (`--phase=ui`, or default
63
+ mode for an FE/App feature). Skip entirely for BE / `system` platform.*
64
+
65
+ The PO authored the Design Spec from **Figma web links** (read-only, limited). For
66
+ codegen, the **local Figma Dev Mode MCP server** (built into the Figma **desktop app**)
67
+ gives far more: exact layout, design **variables/tokens**, **Code Connect** component
68
+ mappings, selection context, and code snippets — things a web URL alone cannot return.
69
+
70
+ **Step 1 — Detect the local MCP.** Check whether a Figma Dev Mode MCP server is connected
71
+ (a `get_design_context` / `get_code` style Figma tool is available via MCP).
72
+
73
+ **Step 2 — If NOT connected → suggest the dev enable it, then wait:**
74
+
75
+ ```
76
+ 🎨 Figma Dev Mode MCP not detected.
77
+ For accurate FE code (real tokens, components, Code Connect), use the LOCAL server:
78
+
79
+ 1. Open the Figma DESKTOP app (not the browser)
80
+ 2. Open the file/frame for this feature
81
+ 3. Enable the Dev Mode MCP server:
82
+ Figma menu → Preferences → "Enable Dev Mode MCP Server"
83
+ (requires Dev or Full seat; server runs at http://127.0.0.1:3845)
84
+ 4. Make sure this MCP server is added in your Claude Code MCP config
85
+ 5. Select the frame for the screen you're implementing, then continue
86
+
87
+ Type C to continue once enabled, or S to skip (fall back to web links + text spec).
88
+ ```
89
+
90
+ - `C` → re-detect; if now connected → proceed using the local MCP.
91
+ - `S` → proceed in **fallback mode**: use the Design Spec's web frame links + textual spec
92
+ only; add a ⚠️ note in the final report that UI was generated without local Figma fidelity.
93
+
94
+ **Step 3 — When the local MCP IS connected:** for each screen being implemented, pull the
95
+ selected frame via the Figma MCP and ground the UI on the returned layout, variables, and
96
+ Code Connect mappings. Prefer Code-Connect-mapped components over inventing markup; use the
97
+ real token names, not hardcoded values.
98
+
53
99
  **If `--phase=integration`:**
54
100
  Read tech-doc `@trace.status` from `{paths.tech_docs_dir}/{domain}/{UC-ID}-tech-design.md`.
55
101
  If `draft` or `in-review` → warn:
@@ -72,7 +118,7 @@ Read `{paths.trace_dir}/{UC-ID}.tsv` if it exists. For each scenario row, note i
72
118
  | `UNTRACKED` | `implemented_by == —` | Generate — scenario has no code yet |
73
119
  | `DRIFT` | `spec_ver != gen_ver` | Regenerate — scenario updated since last codegen |
74
120
  | `OK` | implemented + tested | Skip unless explicitly re-generating |
75
- | `GAP` | implemented, no tests | Skip codegen — already coded; run `/generate-tests` instead |
121
+ | `GAP` | implemented, no tests | Skip codegen — already coded; run `/dev-gen-test` instead |
76
122
 
77
123
  Use these statuses to populate the **Scenarios** count in the CHECKPOINT plan (`{X} new, {Y} drifted, {Z} synced-skip`).
78
124
  If `.tsv` does not exist → treat all scenarios as `UNTRACKED`.
@@ -226,9 +272,12 @@ Update `{paths.trace_dir}/{UC-ID}.tsv` — for each implemented scenario, find t
226
272
  | `fe_phase` | `ui` if `--phase=ui` \| `integrated` if `--phase=integration` \| `—` if no phase flag |
227
273
  | `last_updated` | today `YYYY-MM-DD` |
228
274
 
229
- Leave all other columns (`sc_title`, `spec_ver`, `prd_version`, `prd_status`, `uc_status`, `test_count`, `test_classes`) unchanged.
275
+ Leave all other columns (`sc_title`, `spec_ver`, `prd_version`, `prd_status`, `uc_status`, `test_count`, `test_classes`, `dev_selftest`, `dev_selftest_at`) unchanged.
230
276
  `status` is computed by `/validate-traces` — do not set here.
231
277
 
278
+ ## Refresh Panel Mirror
279
+ {{include:steps/trace-mirror.md}}
280
+
232
281
  ## Commit
233
282
  ```bash
234
283
  git add {files}
@@ -245,6 +294,7 @@ Files: created={N}, extended={M}, skipped={K} | Build: SUCCESS
245
294
  Branch: feature/{TICKET_ID}-{slug}
246
295
  Phase : {UI (mock layer) | Integration (real API) | Default (full)}
247
296
  fe_phase : {ui | integrated | —}
297
+ Figma : {local Dev Mode MCP (grounded) | ⚠️ web links + text spec only (no local MCP) | n/a for BE} ← FE/App UI only
248
298
 
249
299
  Next:
250
300
  --phase=ui done:
@@ -254,9 +304,11 @@ Next:
254
304
 
255
305
  --phase=integration done:
256
306
  → /review-code {UC-ID} ← code review required
257
- → /generate-tests {UC-ID} ← integration test suite
307
+ → /dev-gen-test {UC-ID} ← integration test suite
258
308
 
259
309
  Default (no phase flag):
260
310
  → /review-code {UC-ID} ← code review required before tests
261
- → /generate-tests {UC-ID}
311
+ → /dev-gen-test {UC-ID}
312
+
313
+ 📊 Living Docs: run /validate-traces (or /sync) to push this trace to the spec-module dashboard.
262
314
  ```
@@ -163,7 +163,7 @@ If `services` section is present:
163
163
 
164
164
  **2. Route to service** — if active domain matches a key in `services`:
165
165
  - Override `paths.specs_dir` → `services.{domain}.specs_dir`
166
- - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
166
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir` — **only if `setup.spec_source` is NOT set.** When `spec_source` IS set, the tech-design (API contract) is a cross-team artifact and must live in the shared spec repo (handled in step 4), so leave `tech_docs_dir` for step 4 to route — do NOT pin it per-service here.
167
167
  - Store `active_service` = `services.{domain}.path`
168
168
  - Store `active_service_module` = `services.{domain}.module`
169
169
  - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
@@ -175,7 +175,7 @@ If `services` section is present:
175
175
  **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
176
176
  - Override `paths.prd_dir` → `{spec_source}/specs/prd`
177
177
  - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
178
- - Override `paths.tech_docs_dir` → `{spec_source}/specs/tech-docs` — **only if step 2 did not already route it to a service** (multi-service umbrellas keep per-service tech-docs). This publishes the BE-authored API contract into the shared spec repo so FE/App can read it via the spec submodule at `/generate-code --phase=integration`.
178
+ - Override `paths.tech_docs_dir` → `{spec_source}/specs/tech-docs` — **always when `spec_source` is set** (step 2 no longer pins tech-docs per-service in this case). The tech-design IS the cross-team API contract: BE authors it here, and FE/App read it from the same spec submodule at `/generate-code --phase=integration`. *(Per-service tech-docs only happen when there is no `spec_source` — a pure multi-service BE repo with no shared spec module.)*
179
179
  - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
180
180
  - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
181
181
  - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
@@ -206,7 +206,7 @@ When `active_service` has been resolved to a real path in Step 1.5 (e.g., `user-
206
206
  | `paths.specs_dir` | `{active_service}/{service paths.specs_dir}` (if set in service config, else keep Step 1.5 override) |
207
207
 
208
208
  **3. Store** `service_root = {active_service}` as the working directory anchor for all downstream commands:
209
- - Shell commands (`/run-tests`, `/generate-tests`) run **from within** `service_root`
209
+ - Shell commands (`/dev-run-test`, `/dev-gen-test`) run **from within** `service_root`
210
210
  - File write operations (test files, trace TSVs) use paths **relative to** `service_root`
211
211
 
212
212
  **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).
@@ -299,7 +299,7 @@ active_module = tech_stack.module (e.g. "java-spring", "react", "flutter")
299
299
 
300
300
  If `tech_stack.module` is blank or not recognized → set `platform_type = "unknown"` and flag as ⚠️ in the Step 7 recap.
301
301
 
302
- 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).
302
+ These two variables (`active_module`, `platform_type`) are the canonical source for all branching logic in commands that need platform-specific behavior (dev-gen-test, debug, fix-bug, dev-smoke-test).
303
303
 
304
304
  ---
305
305
 
@@ -399,19 +399,6 @@ Using `active_module` and `platform_type` derived from context loading:
399
399
 
400
400
  ---
401
401
 
402
- ## Figma Check
403
-
404
- Ask:
405
-
406
- ```
407
- Do you have a Figma link for this feature? (paste URL or press Enter to skip)
408
- ```
409
-
410
- - If URL provided → store as `figma_url`.
411
- - If skipped → `figma_url = "TBD"`. Add AI Assumption: "Figma link not provided — all screen descriptions are text-based. Link must be added and verified before Design Spec sign-off."
412
-
413
- ---
414
-
415
402
  ## Screen Discovery
416
403
 
417
404
  From the PRD's Section 4 (User Flow + Wireframe), extract all screen / page / modal names mentioned.
@@ -432,6 +419,54 @@ Wait for confirmation. Store the confirmed list as `screen_list`.
432
419
 
433
420
  ---
434
421
 
422
+ ## Figma Frame Links *(mandatory — one readable node-level link per screen)*
423
+
424
+ A Design Spec is only as good as the design it points to. The AI **cannot read a plain
425
+ file link** (`figma.com/design/{fileKey}/...` with no `node-id`) — it needs a
426
+ **node-level link to each specific frame** so it can fetch that frame's real layout,
427
+ components, and tokens via the Figma MCP. So collect one link **per screen**, not one
428
+ link for the whole feature.
429
+
430
+ **Ask the PO, listing every screen in `screen_list`:**
431
+
432
+ ```
433
+ Paste the Figma frame link for each screen below.
434
+
435
+ In Figma: select the frame → right-click → "Copy link to selection"
436
+ (the URL must contain ?node-id=... — that is the per-frame link the AI can read)
437
+
438
+ 1. {Screen 1} : ____
439
+ 2. {Screen 2} : ____
440
+ ...
441
+
442
+ If a screen has no design yet, type none for that screen.
443
+ ```
444
+
445
+ **For each answer:**
446
+
447
+ 1. **Validate format** — the URL must match `figma.com/design/{fileKey}/...?node-id={nodeId}`.
448
+ - Valid → store as `figma_frames[{screen}] = {url}`, parse out `fileKey` + `nodeId`.
449
+ - A file link with **no `node-id`** → reject it: "This link points to the whole file, not a frame. Re-copy via right-click → Copy link to selection." Re-ask for that screen.
450
+ - `none` → `figma_frames[{screen}] = "TBD"`, mark that screen ❌ Missing.
451
+
452
+ 2. **Fetch the frame via Figma MCP** (only for valid links) — call `get_design_context`
453
+ (and `get_screenshot` when useful) with the parsed `fileKey` + `nodeId` to read the
454
+ real layout, component names, and design tokens. Ground every Screen Spec in this
455
+ fetched data; do **not** invent layout the frame does not show. If a fetch fails
456
+ (permission / not found) → treat that screen as ❌ Missing and note the fetch error.
457
+
458
+ 3. Derive the feature-level `figma_url` = the file link (without `node-id`) shared by the
459
+ frames, for the Metadata row. If frames span multiple files, list each.
460
+
461
+ **Mandatory gate (does not abort — produces a draft):**
462
+ - If **any** screen is ❌ Missing → the spec is generated as a **draft** with those screens
463
+ flagged, but `Status` stays `draft` and **sign-off / `/generate-bdd` is blocked** until
464
+ every screen has a readable, fetched frame link. Record `missing_frames = [screens]`.
465
+ - Add one AI Assumption per missing screen: "No readable Figma frame for {screen} — spec
466
+ for this screen is text-only and must not be signed off until a `node-id` link is added."
467
+
468
+ ---
469
+
435
470
  ## CHECKPOINT
436
471
 
437
472
  ```
@@ -443,9 +478,13 @@ Module : {active_module}
443
478
  Service : {active_service}
444
479
  Domain : {domain}
445
480
  Screens : {N} — {comma-separated screen_list}
446
- Figma : {figma_url}
481
+ Figma : {linked}/{N} screens have readable frame links{; missing: comma-separated missing_frames}
447
482
  Output path : {paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform}-{slug}.md
448
483
 
484
+ {If missing_frames non-empty}:
485
+ ⚠️ {count} screen(s) without a readable Figma frame link — these will be generated as
486
+ text-only drafts and the spec cannot be signed off until their node-id links are added.
487
+
449
488
  Generate? (Y/N)
450
489
  ```
451
490
 
@@ -470,6 +509,15 @@ Apply these rules consistently when generating all sections:
470
509
  - `app` / `app-ios` / `app-android` → include gestures, safe area, minimum touch targets, navigation pattern, deep links, permissions, offline behavior.
471
510
  - Only generate the section relevant to `active_platform`. Omit the other platform's section entirely.
472
511
 
512
+ **Figma grounding (mandatory):**
513
+ - For every screen with a fetched frame (`figma_frames[screen]` is a valid link), base the
514
+ Layout, Component Inventory, and Screen States on the **fetched Figma data** — real
515
+ component names, real tokens, real frame structure. Do not contradict or invent layout.
516
+ - Use the exact per-screen `figma_frames[screen]` URL in the Screen Inventory, each Screen
517
+ Spec header, and the Figma Summary — never a synthetic `{figma_url}#screen1` fragment.
518
+ - For ❌ Missing screens: generate a text-only draft from the PRD, prefix the Screen Spec
519
+ with `> [DRAFT — no Figma frame; do not sign off]`, and leave the Figma cell as ❌ Missing.
520
+
473
521
  **Screen states (mandatory per screen):**
474
522
  - Every screen must document at minimum: `default`, `loading`, `error`.
475
523
  - Add `empty` when the screen can display zero-data state.
@@ -499,7 +547,7 @@ Write `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform
499
547
  | **Service** | {active_service} |
500
548
  | **Domain** | {domain} |
501
549
  | **Business PRD** | [{TICKET-ID}]({relative-path-to-prd.md}) |
502
- | **Figma** | {figma_url} |
550
+ | **Figma** | {figma_url — feature file link} ({linked}/{N} frames linked) |
503
551
  | **Author** | {PO name or "AI-assisted"} |
504
552
  | **Created** | {YYYY-MM-DD} |
505
553
  | **Updated** | {YYYY-MM-DD} |
@@ -510,8 +558,8 @@ Write `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform
510
558
 
511
559
  | # | Screen Name | Entry Point | Figma Frame | Notes |
512
560
  |---|-------------|-------------|-------------|-------|
513
- | 1 | {Screen 1} | {how user arrives — e.g., tap CTA on Home} | [Frame]({figma_url}#screen1) | |
514
- | 2 | {Screen 2} | {entry point} | [Frame]({figma_url}#screen2) | |
561
+ | 1 | {Screen 1} | {how user arrives — e.g., tap CTA on Home} | [Frame]({figma_frames[Screen 1]}) | |
562
+ | 2 | {Screen 2} | {entry point} | [Frame]({figma_frames[Screen 2]}) / ❌ Missing | |
515
563
 
516
564
  ---
517
565
 
@@ -524,7 +572,7 @@ Write `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform
524
572
 
525
573
  ## Screen 1: {Screen Name}
526
574
 
527
- **Figma**: [{Frame name}]({figma_frame_url})
575
+ **Figma**: [{Frame name}]({figma_frames[Screen 1]}) <!-- ❌ Missing → prefix this screen with `> [DRAFT — no Figma frame; do not sign off]` -->
528
576
 
529
577
  ### Layout
530
578
 
@@ -680,10 +728,10 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
680
728
 
681
729
  ## Figma Summary
682
730
 
683
- | Screen | Figma Frame | Designer Status |
684
- |-----------------|-------------------------------|------------------------|
685
- | {Screen 1} | [Link]({figma_frame_url}) | ✅ Ready / ⏳ WIP / ❌ Missing |
686
- | {Screen 2} | [Link]({figma_frame_url}) | Ready / WIP / Missing |
731
+ | Screen | Figma Frame | Link / Fetch Status |
732
+ |-----------------|--------------------------------------|--------------------------------------|
733
+ | {Screen 1} | [Link]({figma_frames[Screen 1]}) | ✅ Linked & fetched |
734
+ | {Screen 2} | | Missing no node-id link provided |
687
735
 
688
736
  ## Design Tokens Referenced
689
737
 
@@ -705,6 +753,7 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
705
753
  > PO must review and confirm before sign-off.
706
754
 
707
755
  - {Assumption 1 — [AI DRAFT]}
756
+ - {One per ❌ Missing screen: "No readable Figma frame for {screen} — text-only draft; blocks sign-off until a node-id link is added."}
708
757
 
709
758
  ---
710
759
 
@@ -716,9 +765,10 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
716
765
 
717
766
  <!--
718
767
  NEXT STEPS:
719
- 1. Share with Designer verify Figma links, update component inventory.
720
- 2. PO + Designer sign off: change Status "approved".
721
- 3. Run /generate-bdd "{prd-file}" BDD uses AC-UI from this spec for FE scenarios.
768
+ 1. Fill any Missing Figma frame links (node-id links) — re-run to fetch & ground them.
769
+ 2. Share with Designer verify Figma links, update component inventory.
770
+ 3. PO + Designer sign off: change Status → "approved" (only allowed when 0 screens are Missing).
771
+ 4. Run /generate-bdd "{prd-file}" — BDD uses AC-UI from this spec for FE scenarios.
722
772
  -->
723
773
  ````
724
774
 
@@ -733,7 +783,9 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
733
783
  - [ ] Only the platform-relevant section generated in Section 4
734
784
  - [ ] AC-UI items are testable (clear pass/fail, not "looks good")
735
785
  - [ ] Business PRD cross-reference link is valid relative path
736
- - [ ] If `figma_url = "TBD"` AI Assumption added in Appendix
786
+ - [ ] Every screen has a node-level Figma frame link (`?node-id=`) — and screens with a link were fetched via Figma MCP and used to ground the spec
787
+ - [ ] Each ❌ Missing screen is flagged in-spec (`> [DRAFT — no Figma frame...]`), listed in Figma Summary, and has an AI Assumption
788
+ - [ ] If any screen is ❌ Missing → Status stays `draft` and the Output below blocks `/generate-bdd`
737
789
 
738
790
  ---
739
791
 
@@ -777,13 +829,13 @@ Suggest the logical next command based on workflow phase:
777
829
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
778
830
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
779
831
  | /review-tech-docs | `/generate-code {feature-file}` if APPROVED; fix doc if NEEDS_FIX |
780
- | /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/generate-tests {UC-ID}` |
781
- | /generate-tests | `/run-tests {UC-ID}` |
782
- | /run-tests (passing) | `/review-code {UC-ID}` |
783
- | /run-tests (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
784
- | /review-code | `/smoke-test {UC-ID}` or create PR |
785
- | /smoke-test | Create PR and link to ticket |
786
- | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
832
+ | /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/dev-gen-test {UC-ID}` |
833
+ | /dev-gen-test | `/dev-run-test {UC-ID}` |
834
+ | /dev-run-test (passing) | `/review-code {UC-ID}` |
835
+ | /dev-run-test (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
836
+ | /review-code | `/dev-smoke-test {UC-ID}` or create PR |
837
+ | /dev-smoke-test | Create PR and link to ticket |
838
+ | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/dev-gen-test {UC-ID}`; all OK → create PR |
787
839
  | /fix-bug | Create PR and link to ticket |
788
840
  | /debug | `/fix-bug {ticket-id}` if fix needed |
789
841
  | /report-bug | Send to dev (`/fix-bug {BUG-ID}`); if coverage gap → `/propose-scenario {UC-ID}` |
@@ -801,12 +853,25 @@ Next : {suggested command with example arguments}
801
853
  ```
802
854
 
803
855
 
856
+ {If missing_frames is empty}:
804
857
  ```
805
858
  /generate-design-spec Complete — {TICKET-ID} [{active_platform}]
806
859
  ---
807
- Status : ✅ Complete
860
+ Status : ✅ Complete — all {N} screens linked & fetched from Figma
808
861
  Output Artifacts:
809
862
  created {paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform}-{slug}.md (v1.0)
810
- Next : Share with Designer → add Figma links → PO + Designer sign-off (Status: approved)
863
+ Next : Share with Designer → PO + Designer sign-off (Status: approved)
811
864
  → /generate-bdd {prd-file} (generates BDD per service; reads AC-UI from Design Spec)
812
865
  ```
866
+
867
+ {If missing_frames is non-empty}:
868
+ ```
869
+ /generate-design-spec Complete (DRAFT) — {TICKET-ID} [{active_platform}]
870
+ ---
871
+ Status : ⚠️ Warnings — {count} screen(s) without a readable Figma frame: {comma-separated missing_frames}
872
+ Output Artifacts:
873
+ created {paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform}-{slug}.md (v1.0, draft)
874
+ Next : 🔒 Sign-off & /generate-bdd are BLOCKED until every screen has a node-id Figma link.
875
+ 1. In Figma: select each missing frame → right-click → Copy link to selection
876
+ 2. Re-run /generate-design-spec {prd-file} → AI fetches & grounds the new frames
877
+ ```
@@ -46,19 +46,6 @@ Using `active_module` and `platform_type` derived from context loading:
46
46
 
47
47
  ---
48
48
 
49
- ## Figma Check
50
-
51
- Ask:
52
-
53
- ```
54
- Do you have a Figma link for this feature? (paste URL or press Enter to skip)
55
- ```
56
-
57
- - If URL provided → store as `figma_url`.
58
- - If skipped → `figma_url = "TBD"`. Add AI Assumption: "Figma link not provided — all screen descriptions are text-based. Link must be added and verified before Design Spec sign-off."
59
-
60
- ---
61
-
62
49
  ## Screen Discovery
63
50
 
64
51
  From the PRD's Section 4 (User Flow + Wireframe), extract all screen / page / modal names mentioned.
@@ -79,6 +66,54 @@ Wait for confirmation. Store the confirmed list as `screen_list`.
79
66
 
80
67
  ---
81
68
 
69
+ ## Figma Frame Links *(mandatory — one readable node-level link per screen)*
70
+
71
+ A Design Spec is only as good as the design it points to. The AI **cannot read a plain
72
+ file link** (`figma.com/design/{fileKey}/...` with no `node-id`) — it needs a
73
+ **node-level link to each specific frame** so it can fetch that frame's real layout,
74
+ components, and tokens via the Figma MCP. So collect one link **per screen**, not one
75
+ link for the whole feature.
76
+
77
+ **Ask the PO, listing every screen in `screen_list`:**
78
+
79
+ ```
80
+ Paste the Figma frame link for each screen below.
81
+
82
+ In Figma: select the frame → right-click → "Copy link to selection"
83
+ (the URL must contain ?node-id=... — that is the per-frame link the AI can read)
84
+
85
+ 1. {Screen 1} : ____
86
+ 2. {Screen 2} : ____
87
+ ...
88
+
89
+ If a screen has no design yet, type none for that screen.
90
+ ```
91
+
92
+ **For each answer:**
93
+
94
+ 1. **Validate format** — the URL must match `figma.com/design/{fileKey}/...?node-id={nodeId}`.
95
+ - Valid → store as `figma_frames[{screen}] = {url}`, parse out `fileKey` + `nodeId`.
96
+ - A file link with **no `node-id`** → reject it: "This link points to the whole file, not a frame. Re-copy via right-click → Copy link to selection." Re-ask for that screen.
97
+ - `none` → `figma_frames[{screen}] = "TBD"`, mark that screen ❌ Missing.
98
+
99
+ 2. **Fetch the frame via Figma MCP** (only for valid links) — call `get_design_context`
100
+ (and `get_screenshot` when useful) with the parsed `fileKey` + `nodeId` to read the
101
+ real layout, component names, and design tokens. Ground every Screen Spec in this
102
+ fetched data; do **not** invent layout the frame does not show. If a fetch fails
103
+ (permission / not found) → treat that screen as ❌ Missing and note the fetch error.
104
+
105
+ 3. Derive the feature-level `figma_url` = the file link (without `node-id`) shared by the
106
+ frames, for the Metadata row. If frames span multiple files, list each.
107
+
108
+ **Mandatory gate (does not abort — produces a draft):**
109
+ - If **any** screen is ❌ Missing → the spec is generated as a **draft** with those screens
110
+ flagged, but `Status` stays `draft` and **sign-off / `/generate-bdd` is blocked** until
111
+ every screen has a readable, fetched frame link. Record `missing_frames = [screens]`.
112
+ - Add one AI Assumption per missing screen: "No readable Figma frame for {screen} — spec
113
+ for this screen is text-only and must not be signed off until a `node-id` link is added."
114
+
115
+ ---
116
+
82
117
  ## CHECKPOINT
83
118
 
84
119
  ```
@@ -90,9 +125,13 @@ Module : {active_module}
90
125
  Service : {active_service}
91
126
  Domain : {domain}
92
127
  Screens : {N} — {comma-separated screen_list}
93
- Figma : {figma_url}
128
+ Figma : {linked}/{N} screens have readable frame links{; missing: comma-separated missing_frames}
94
129
  Output path : {paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform}-{slug}.md
95
130
 
131
+ {If missing_frames non-empty}:
132
+ ⚠️ {count} screen(s) without a readable Figma frame link — these will be generated as
133
+ text-only drafts and the spec cannot be signed off until their node-id links are added.
134
+
96
135
  Generate? (Y/N)
97
136
  ```
98
137
 
@@ -117,6 +156,15 @@ Apply these rules consistently when generating all sections:
117
156
  - `app` / `app-ios` / `app-android` → include gestures, safe area, minimum touch targets, navigation pattern, deep links, permissions, offline behavior.
118
157
  - Only generate the section relevant to `active_platform`. Omit the other platform's section entirely.
119
158
 
159
+ **Figma grounding (mandatory):**
160
+ - For every screen with a fetched frame (`figma_frames[screen]` is a valid link), base the
161
+ Layout, Component Inventory, and Screen States on the **fetched Figma data** — real
162
+ component names, real tokens, real frame structure. Do not contradict or invent layout.
163
+ - Use the exact per-screen `figma_frames[screen]` URL in the Screen Inventory, each Screen
164
+ Spec header, and the Figma Summary — never a synthetic `{figma_url}#screen1` fragment.
165
+ - For ❌ Missing screens: generate a text-only draft from the PRD, prefix the Screen Spec
166
+ with `> [DRAFT — no Figma frame; do not sign off]`, and leave the Figma cell as ❌ Missing.
167
+
120
168
  **Screen states (mandatory per screen):**
121
169
  - Every screen must document at minimum: `default`, `loading`, `error`.
122
170
  - Add `empty` when the screen can display zero-data state.
@@ -146,7 +194,7 @@ Write `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform
146
194
  | **Service** | {active_service} |
147
195
  | **Domain** | {domain} |
148
196
  | **Business PRD** | [{TICKET-ID}]({relative-path-to-prd.md}) |
149
- | **Figma** | {figma_url} |
197
+ | **Figma** | {figma_url — feature file link} ({linked}/{N} frames linked) |
150
198
  | **Author** | {PO name or "AI-assisted"} |
151
199
  | **Created** | {YYYY-MM-DD} |
152
200
  | **Updated** | {YYYY-MM-DD} |
@@ -157,8 +205,8 @@ Write `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform
157
205
 
158
206
  | # | Screen Name | Entry Point | Figma Frame | Notes |
159
207
  |---|-------------|-------------|-------------|-------|
160
- | 1 | {Screen 1} | {how user arrives — e.g., tap CTA on Home} | [Frame]({figma_url}#screen1) | |
161
- | 2 | {Screen 2} | {entry point} | [Frame]({figma_url}#screen2) | |
208
+ | 1 | {Screen 1} | {how user arrives — e.g., tap CTA on Home} | [Frame]({figma_frames[Screen 1]}) | |
209
+ | 2 | {Screen 2} | {entry point} | [Frame]({figma_frames[Screen 2]}) / ❌ Missing | |
162
210
 
163
211
  ---
164
212
 
@@ -171,7 +219,7 @@ Write `{paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform
171
219
 
172
220
  ## Screen 1: {Screen Name}
173
221
 
174
- **Figma**: [{Frame name}]({figma_frame_url})
222
+ **Figma**: [{Frame name}]({figma_frames[Screen 1]}) <!-- ❌ Missing → prefix this screen with `> [DRAFT — no Figma frame; do not sign off]` -->
175
223
 
176
224
  ### Layout
177
225
 
@@ -327,10 +375,10 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
327
375
 
328
376
  ## Figma Summary
329
377
 
330
- | Screen | Figma Frame | Designer Status |
331
- |-----------------|-------------------------------|------------------------|
332
- | {Screen 1} | [Link]({figma_frame_url}) | ✅ Ready / ⏳ WIP / ❌ Missing |
333
- | {Screen 2} | [Link]({figma_frame_url}) | Ready / WIP / Missing |
378
+ | Screen | Figma Frame | Link / Fetch Status |
379
+ |-----------------|--------------------------------------|--------------------------------------|
380
+ | {Screen 1} | [Link]({figma_frames[Screen 1]}) | ✅ Linked & fetched |
381
+ | {Screen 2} | | Missing no node-id link provided |
334
382
 
335
383
  ## Design Tokens Referenced
336
384
 
@@ -352,6 +400,7 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
352
400
  > PO must review and confirm before sign-off.
353
401
 
354
402
  - {Assumption 1 — [AI DRAFT]}
403
+ - {One per ❌ Missing screen: "No readable Figma frame for {screen} — text-only draft; blocks sign-off until a node-id link is added."}
355
404
 
356
405
  ---
357
406
 
@@ -363,9 +412,10 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
363
412
 
364
413
  <!--
365
414
  NEXT STEPS:
366
- 1. Share with Designer verify Figma links, update component inventory.
367
- 2. PO + Designer sign off: change Status "approved".
368
- 3. Run /generate-bdd "{prd-file}" BDD uses AC-UI from this spec for FE scenarios.
415
+ 1. Fill any Missing Figma frame links (node-id links) — re-run to fetch & ground them.
416
+ 2. Share with Designer verify Figma links, update component inventory.
417
+ 3. PO + Designer sign off: change Status → "approved" (only allowed when 0 screens are Missing).
418
+ 4. Run /generate-bdd "{prd-file}" — BDD uses AC-UI from this spec for FE scenarios.
369
419
  -->
370
420
  ````
371
421
 
@@ -380,7 +430,9 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
380
430
  - [ ] Only the platform-relevant section generated in Section 4
381
431
  - [ ] AC-UI items are testable (clear pass/fail, not "looks good")
382
432
  - [ ] Business PRD cross-reference link is valid relative path
383
- - [ ] If `figma_url = "TBD"` AI Assumption added in Appendix
433
+ - [ ] Every screen has a node-level Figma frame link (`?node-id=`) — and screens with a link were fetched via Figma MCP and used to ground the spec
434
+ - [ ] Each ❌ Missing screen is flagged in-spec (`> [DRAFT — no Figma frame...]`), listed in Figma Summary, and has an AI Assumption
435
+ - [ ] If any screen is ❌ Missing → Status stays `draft` and the Output below blocks `/generate-bdd`
384
436
 
385
437
  ---
386
438
 
@@ -388,12 +440,25 @@ Exit: {how the user leaves — back stack / tab switch / deeplink out}
388
440
 
389
441
  {{include:steps/report-footer.md}}
390
442
 
443
+ {If missing_frames is empty}:
391
444
  ```
392
445
  /generate-design-spec Complete — {TICKET-ID} [{active_platform}]
393
446
  ---
394
- Status : ✅ Complete
447
+ Status : ✅ Complete — all {N} screens linked & fetched from Figma
395
448
  Output Artifacts:
396
449
  created {paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform}-{slug}.md (v1.0)
397
- Next : Share with Designer → add Figma links → PO + Designer sign-off (Status: approved)
450
+ Next : Share with Designer → PO + Designer sign-off (Status: approved)
398
451
  → /generate-bdd {prd-file} (generates BDD per service; reads AC-UI from Design Spec)
399
452
  ```
453
+
454
+ {If missing_frames is non-empty}:
455
+ ```
456
+ /generate-design-spec Complete (DRAFT) — {TICKET-ID} [{active_platform}]
457
+ ---
458
+ Status : ⚠️ Warnings — {count} screen(s) without a readable Figma frame: {comma-separated missing_frames}
459
+ Output Artifacts:
460
+ created {paths.design_spec_dir}/{domain}/{TICKET-ID}-design-spec-{active_platform}-{slug}.md (v1.0, draft)
461
+ Next : 🔒 Sign-off & /generate-bdd are BLOCKED until every screen has a node-id Figma link.
462
+ 1. In Figma: select each missing frame → right-click → Copy link to selection
463
+ 2. Re-run /generate-design-spec {prd-file} → AI fetches & grounds the new frames
464
+ ```
@@ -163,7 +163,7 @@ If `services` section is present:
163
163
 
164
164
  **2. Route to service** — if active domain matches a key in `services`:
165
165
  - Override `paths.specs_dir` → `services.{domain}.specs_dir`
166
- - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
166
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir` — **only if `setup.spec_source` is NOT set.** When `spec_source` IS set, the tech-design (API contract) is a cross-team artifact and must live in the shared spec repo (handled in step 4), so leave `tech_docs_dir` for step 4 to route — do NOT pin it per-service here.
167
167
  - Store `active_service` = `services.{domain}.path`
168
168
  - Store `active_service_module` = `services.{domain}.module`
169
169
  - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
@@ -175,7 +175,7 @@ If `services` section is present:
175
175
  **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
176
176
  - Override `paths.prd_dir` → `{spec_source}/specs/prd`
177
177
  - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
178
- - Override `paths.tech_docs_dir` → `{spec_source}/specs/tech-docs` — **only if step 2 did not already route it to a service** (multi-service umbrellas keep per-service tech-docs). This publishes the BE-authored API contract into the shared spec repo so FE/App can read it via the spec submodule at `/generate-code --phase=integration`.
178
+ - Override `paths.tech_docs_dir` → `{spec_source}/specs/tech-docs` — **always when `spec_source` is set** (step 2 no longer pins tech-docs per-service in this case). The tech-design IS the cross-team API contract: BE authors it here, and FE/App read it from the same spec submodule at `/generate-code --phase=integration`. *(Per-service tech-docs only happen when there is no `spec_source` — a pure multi-service BE repo with no shared spec module.)*
179
179
  - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
180
180
  - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
181
181
  - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
@@ -206,7 +206,7 @@ When `active_service` has been resolved to a real path in Step 1.5 (e.g., `user-
206
206
  | `paths.specs_dir` | `{active_service}/{service paths.specs_dir}` (if set in service config, else keep Step 1.5 override) |
207
207
 
208
208
  **3. Store** `service_root = {active_service}` as the working directory anchor for all downstream commands:
209
- - Shell commands (`/run-tests`, `/generate-tests`) run **from within** `service_root`
209
+ - Shell commands (`/dev-run-test`, `/dev-gen-test`) run **from within** `service_root`
210
210
  - File write operations (test files, trace TSVs) use paths **relative to** `service_root`
211
211
 
212
212
  **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).
@@ -299,7 +299,7 @@ active_module = tech_stack.module (e.g. "java-spring", "react", "flutter")
299
299
 
300
300
  If `tech_stack.module` is blank or not recognized → set `platform_type = "unknown"` and flag as ⚠️ in the Step 7 recap.
301
301
 
302
- 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).
302
+ These two variables (`active_module`, `platform_type`) are the canonical source for all branching logic in commands that need platform-specific behavior (dev-gen-test, debug, fix-bug, dev-smoke-test).
303
303
 
304
304
  ---
305
305
 
@@ -632,13 +632,13 @@ Suggest the logical next command based on workflow phase:
632
632
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
633
633
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
634
634
  | /review-tech-docs | `/generate-code {feature-file}` if APPROVED; fix doc if NEEDS_FIX |
635
- | /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/generate-tests {UC-ID}` |
636
- | /generate-tests | `/run-tests {UC-ID}` |
637
- | /run-tests (passing) | `/review-code {UC-ID}` |
638
- | /run-tests (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
639
- | /review-code | `/smoke-test {UC-ID}` or create PR |
640
- | /smoke-test | Create PR and link to ticket |
641
- | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
635
+ | /generate-code | First gen → `/review-code {UC-ID}`; re-gen → `/dev-gen-test {UC-ID}` |
636
+ | /dev-gen-test | `/dev-run-test {UC-ID}` |
637
+ | /dev-run-test (passing) | `/review-code {UC-ID}` |
638
+ | /dev-run-test (failing) | `/fix-bug {ticket-id}` or `/debug {error}` |
639
+ | /review-code | `/dev-smoke-test {UC-ID}` or create PR |
640
+ | /dev-smoke-test | Create PR and link to ticket |
641
+ | /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/dev-gen-test {UC-ID}`; all OK → create PR |
642
642
  | /fix-bug | Create PR and link to ticket |
643
643
  | /debug | `/fix-bug {ticket-id}` if fix needed |
644
644
  | /report-bug | Send to dev (`/fix-bug {BUG-ID}`); if coverage gap → `/propose-scenario {UC-ID}` |