@anhth2/spec-driven-dev-plugin 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/bin/index.js +105 -0
  2. package/commands/debug.md +37 -1
  3. package/commands/define-product.md +37 -1
  4. package/commands/fix-bug.md +37 -1
  5. package/commands/generate-bdd.md +37 -1
  6. package/commands/generate-code.md +37 -1
  7. package/commands/generate-design-spec.md +754 -0
  8. package/commands/generate-design-spec.tmpl +399 -0
  9. package/commands/generate-prd.md +58 -1
  10. package/commands/generate-prd.tmpl +21 -0
  11. package/commands/generate-spec-manifest.md +519 -0
  12. package/commands/generate-spec-manifest.tmpl +164 -0
  13. package/commands/generate-tech-docs.md +37 -1
  14. package/commands/generate-tests.md +37 -1
  15. package/commands/refine-prd.md +37 -1
  16. package/commands/review-code.md +37 -1
  17. package/commands/review-context.md +77 -1
  18. package/commands/review-context.tmpl +40 -0
  19. package/commands/review-tech-docs.md +37 -1
  20. package/commands/run-tests.md +37 -1
  21. package/commands/setup-ai-first.md +132 -4
  22. package/commands/setup-ai-first.tmpl +130 -3
  23. package/commands/smoke-test.md +37 -1
  24. package/commands/validate-traces.md +37 -1
  25. package/core/FRAMEWORK_VERSION +1 -1
  26. package/core/commands/debug.md +37 -1
  27. package/core/commands/define-product.md +37 -1
  28. package/core/commands/fix-bug.md +37 -1
  29. package/core/commands/generate-bdd.md +37 -1
  30. package/core/commands/generate-code.md +37 -1
  31. package/core/commands/generate-design-spec.md +754 -0
  32. package/core/commands/generate-prd.md +58 -1
  33. package/core/commands/generate-spec-manifest.md +519 -0
  34. package/core/commands/generate-tech-docs.md +37 -1
  35. package/core/commands/generate-tests.md +37 -1
  36. package/core/commands/refine-prd.md +37 -1
  37. package/core/commands/review-code.md +37 -1
  38. package/core/commands/review-context.md +77 -1
  39. package/core/commands/review-tech-docs.md +37 -1
  40. package/core/commands/run-tests.md +37 -1
  41. package/core/commands/setup-ai-first.md +132 -4
  42. package/core/commands/smoke-test.md +37 -1
  43. package/core/commands/validate-traces.md +37 -1
  44. package/core/skills/code/SKILL.md +39 -2
  45. package/core/skills/debug/SKILL.md +41 -3
  46. package/core/skills/design-spec/SKILL.md +450 -0
  47. package/core/skills/discovery/SKILL.md +37 -1
  48. package/core/skills/prd/SKILL.md +4 -2
  49. package/core/skills/setup-ai-first/SKILL.md +2 -1
  50. package/core/skills/spec/SKILL.md +4 -2
  51. package/core/skills/test/SKILL.md +76 -3
  52. package/core/steps/context-loader.md +35 -0
  53. package/core/steps/report-footer.md +2 -1
  54. package/core/templates/design-spec.template.md +209 -0
  55. package/core/templates/project-context.yaml +29 -0
  56. package/package.json +1 -1
  57. package/skills/code/SKILL.md +39 -2
  58. package/skills/debug/SKILL.md +41 -3
  59. package/skills/design-spec/SKILL.md +450 -0
  60. package/skills/design-spec/SKILL.tmpl +95 -0
  61. package/skills/discovery/SKILL.md +37 -1
  62. package/skills/prd/SKILL.md +4 -2
  63. package/skills/setup-ai-first/SKILL.md +2 -1
  64. package/skills/spec/SKILL.md +4 -2
  65. package/skills/test/SKILL.md +76 -3
  66. package/steps/context-loader.md +35 -0
  67. package/steps/report-footer.md +2 -1
  68. package/templates/design-spec.template.md +209 -0
  69. package/templates/project-context.yaml +29 -0
package/bin/index.js CHANGED
@@ -29,6 +29,10 @@ const serviceList = servicesRaw
29
29
  }).filter(s => s.name)
30
30
  : [];
31
31
 
32
+ const isUmbrella = args.includes('--umbrella');
33
+ const specSourceIdx = args.indexOf('--spec-source');
34
+ const specSource = specSourceIdx !== -1 ? args[specSourceIdx + 1] : null;
35
+
32
36
  const AVAILABLE_MODULES = [
33
37
  'java-spring', 'angular', 'react', 'nextjs',
34
38
  'dotnet', 'golang', 'php-laravel', 'context-engineering',
@@ -59,6 +63,9 @@ if (showHelp) {
59
63
  console.log('Install modes:');
60
64
  console.log(' --init Install framework to .agent/ + create shortcuts in .claude/commands/');
61
65
  console.log(' Recommended for new projects. Run upgrade.sh to upgrade later.');
66
+ console.log(' --init --umbrella Umbrella repo setup: installs framework at umbrella level only.');
67
+ console.log(' Generates project-context.yaml with services routing.');
68
+ console.log(' Does NOT install into service submodule directories.');
62
69
  console.log(' --project Install full commands to ./.claude/commands/ (project-scoped, legacy)');
63
70
  console.log(' (no flag) Install full commands to ~/.claude/commands/ (global, legacy)');
64
71
  console.log('');
@@ -67,6 +74,9 @@ if (showHelp) {
67
74
  console.log(' --services <list> Monorepo setup: install into each service subfolder in one command.');
68
75
  console.log(' Format: name:module,name:module,...');
69
76
  console.log(' Example: backend:java-spring,web-admin:react,app-mobile:flutter');
77
+ console.log(' --umbrella Umbrella mode (use with --init). See above.');
78
+ console.log(' --spec-source <path> Path to PO spec submodule (e.g. free-trial-specs).');
79
+ console.log(' Auto-configures prd_dir, design_spec_dir, domain_knowledge_dir.');
70
80
  console.log(' --hooks Install data-guard hook to .claude/hooks/ + update .claude/settings.json');
71
81
  console.log('');
72
82
  console.log('Available modules:');
@@ -77,6 +87,9 @@ if (showHelp) {
77
87
  console.log(' npx @anhth2/spec-driven-dev-plugin --init --module java-spring # with stack module');
78
88
  console.log(' npx @anhth2/spec-driven-dev-plugin --init \\');
79
89
  console.log(' --services backend:java-spring,web-admin:react,app-mobile:flutter # monorepo setup');
90
+ console.log(' npx @anhth2/spec-driven-dev-plugin --init --umbrella \\');
91
+ console.log(' --spec-source free-trial-specs \\');
92
+ console.log(' --services mass-product-web:nextjs # umbrella with one FE service');
80
93
  console.log(' npx @anhth2/spec-driven-dev-plugin --project --hooks # legacy project install');
81
94
  process.exit(0);
82
95
  }
@@ -178,6 +191,83 @@ if (isInit) {
178
191
  installDataGuardHook();
179
192
  }
180
193
 
194
+ // 5-alt. Umbrella mode: generate umbrella project-context.yaml (do NOT install into submodules)
195
+ if (isUmbrella) {
196
+ const rootCtxPath = path.join(agentDir, 'project-context.yaml');
197
+ if (!fs.existsSync(rootCtxPath)) {
198
+ const specSrc = specSource || 'TODO-spec-submodule';
199
+
200
+ let servicesBlock = '';
201
+ if (serviceList.length > 0) {
202
+ servicesBlock = serviceList.map(s => [
203
+ ` ${s.name}:`,
204
+ ` path: "${s.name}"`,
205
+ ` module: "${s.module || 'TODO'}"`,
206
+ ` specs_dir: "${s.name}/specs/bdd"`,
207
+ ` tech_docs_dir: "${s.name}/specs/tech-docs"`,
208
+ ].join('\n')).join('\n');
209
+ } else {
210
+ servicesBlock = [
211
+ ` # {domain}:`,
212
+ ` # path: "{service-submodule-dir}"`,
213
+ ` # module: "{stack-module}"`,
214
+ ` # specs_dir: "{service-dir}/specs/bdd"`,
215
+ ` # tech_docs_dir: "{service-dir}/specs/tech-docs"`,
216
+ ].join('\n');
217
+ }
218
+
219
+ const domainsBlock = serviceList.length > 0
220
+ ? serviceList.map(s => ` - "${s.name}"`).join('\n')
221
+ : ` - "TODO"`;
222
+
223
+ const umbrellaYaml = [
224
+ `project:`,
225
+ ` name: "${path.basename(projectRoot)}"`,
226
+ ` description: ""`,
227
+ ``,
228
+ `setup:`,
229
+ ` mode: umbrella`,
230
+ ` spec_source: "${specSrc}"`,
231
+ ``,
232
+ `# Paths auto-derived from spec_source by context-loader.`,
233
+ `# Override here only if your structure differs.`,
234
+ `paths:`,
235
+ ` prd_dir: "${specSrc}/specs/prd"`,
236
+ ` design_spec_dir: "${specSrc}/specs/design-spec"`,
237
+ ` domain_knowledge_dir: "${specSrc}/specs/domain-knowledge"`,
238
+ ` business_dictionary: "${specSrc}/specs/domain-knowledge/business-dictionary.md"`,
239
+ ` core_entities: "${specSrc}/specs/domain-knowledge/core-entities.md"`,
240
+ ` product_definitions_dir: "${specSrc}/specs/product-definition"`,
241
+ ` refinement_dir: ".agent/review"`,
242
+ ` trace_dir: ".trace"`,
243
+ ``,
244
+ `# Domain → service submodule routing.`,
245
+ `# Each key must match @trace.domain in your PRD files.`,
246
+ `services:`,
247
+ servicesBlock,
248
+ ``,
249
+ `tech_stack:`,
250
+ ` language: multi-service`,
251
+ ` module: ""`,
252
+ ``,
253
+ `conventions:`,
254
+ ` ticket_prefix: FEAT`,
255
+ ``,
256
+ `domains:`,
257
+ domainsBlock,
258
+ ``,
259
+ ].join('\n');
260
+
261
+ fs.writeFileSync(rootCtxPath, umbrellaYaml, 'utf8');
262
+ console.log('');
263
+ console.log(' ✅ .agent/project-context.yaml (umbrella mode, generated)');
264
+ if (specSource) console.log(` spec_source : ${specSrc}`);
265
+ if (serviceList.length > 0) console.log(` services : ${serviceList.map(s => s.name).join(', ')}`);
266
+ } else {
267
+ console.log(' ℹ️ .agent/project-context.yaml (already exists — skipped)');
268
+ }
269
+ }
270
+
181
271
  // 5. Monorepo: install into each service subfolder
182
272
  if (serviceList.length > 0) {
183
273
  console.log('');
@@ -307,6 +397,21 @@ if (isInit) {
307
397
  }
308
398
  console.log(`✅ Framework v${frameworkVersion} installed!`);
309
399
  console.log('');
400
+ if (isUmbrella) {
401
+ console.log('Umbrella workspace ready:');
402
+ console.log(' Open Claude Code at project root (umbrella)');
403
+ console.log(' Agent reads specs from: ' + (specSource || 'spec_source in project-context.yaml'));
404
+ if (serviceList.length > 0) {
405
+ console.log(' Service submodules configured:');
406
+ serviceList.forEach(s => console.log(` ${s.name} (${s.module || 'no module'})`));
407
+ }
408
+ console.log('');
409
+ console.log('Next steps:');
410
+ console.log(' 1. Review .agent/project-context.yaml — update service paths + domain names');
411
+ console.log(' 2. Run /setup-ai-first in Claude Code');
412
+ console.log(' 3. Commit .agent/ to git');
413
+ console.log('');
414
+ } else
310
415
  if (serviceList.length > 0) {
311
416
  console.log('Monorepo workspaces ready:');
312
417
  console.log(' PO/BA → open Claude Code at project root');
package/commands/debug.md CHANGED
@@ -134,6 +134,7 @@ Read `.agent/project-context.yaml`. Extract and store:
134
134
  - `paths.core_entities` → path to core-entities.md
135
135
  - `paths.tech_docs_dir` → technical documentation root
136
136
  - `paths.trace_dir` → trace state directory
137
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
137
138
 
138
139
  If `paths` section is absent, use these defaults:
139
140
  - `specs_dir` = `specs/bdd`
@@ -145,11 +146,44 @@ If `paths` section is absent, use these defaults:
145
146
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
146
147
  - `tech_docs_dir` = `specs/tech-docs`
147
148
  - `trace_dir` = `.trace`
149
+ - `design_spec_dir` = `specs/design-spec`
148
150
 
149
151
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
150
152
 
151
153
  ---
152
154
 
155
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
156
+
157
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
158
+
159
+ If `services` section is present:
160
+
161
+ **1. Detect active domain** (in priority order):
162
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
163
+ - Extract from target file path: segment immediately after `prd_dir` base path
164
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
165
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
166
+
167
+ **2. Route to service** — if active domain matches a key in `services`:
168
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
169
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
170
+ - Store `active_service` = `services.{domain}.path`
171
+ - Store `active_service_module` = `services.{domain}.module`
172
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
173
+
174
+ **3. Fallback** — if domain not detected or no matching service key:
175
+ - Keep default paths from Step 1
176
+ - Set `active_service = unresolved`
177
+
178
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
179
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
180
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
181
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
182
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
183
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
184
+
185
+ ---
186
+
153
187
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
154
188
 
155
189
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -255,6 +289,7 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
255
289
  Ticket : {ticket_prefix}-
256
290
  Dict : {loaded — N canonical terms, M banned terms | missing}
257
291
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
292
+ Service : {active_service} ({active_service_module}) | single-service
258
293
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
259
294
  ```
260
295
 
@@ -512,7 +547,8 @@ Suggest the logical next command based on workflow phase:
512
547
  | /define-product | `/generate-prd {product-definition-file}` |
513
548
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
514
549
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
515
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
550
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
551
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
516
552
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
517
553
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
518
554
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
@@ -131,6 +131,7 @@ Read `.agent/project-context.yaml`. Extract and store:
131
131
  - `paths.core_entities` → path to core-entities.md
132
132
  - `paths.tech_docs_dir` → technical documentation root
133
133
  - `paths.trace_dir` → trace state directory
134
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
134
135
 
135
136
  If `paths` section is absent, use these defaults:
136
137
  - `specs_dir` = `specs/bdd`
@@ -142,11 +143,44 @@ If `paths` section is absent, use these defaults:
142
143
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
143
144
  - `tech_docs_dir` = `specs/tech-docs`
144
145
  - `trace_dir` = `.trace`
146
+ - `design_spec_dir` = `specs/design-spec`
145
147
 
146
148
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
147
149
 
148
150
  ---
149
151
 
152
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
153
+
154
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
155
+
156
+ If `services` section is present:
157
+
158
+ **1. Detect active domain** (in priority order):
159
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
160
+ - Extract from target file path: segment immediately after `prd_dir` base path
161
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
162
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
163
+
164
+ **2. Route to service** — if active domain matches a key in `services`:
165
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
166
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
167
+ - Store `active_service` = `services.{domain}.path`
168
+ - Store `active_service_module` = `services.{domain}.module`
169
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
170
+
171
+ **3. Fallback** — if domain not detected or no matching service key:
172
+ - Keep default paths from Step 1
173
+ - Set `active_service = unresolved`
174
+
175
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
176
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
177
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
178
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
179
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
180
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
181
+
182
+ ---
183
+
150
184
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
151
185
 
152
186
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -252,6 +286,7 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
252
286
  Ticket : {ticket_prefix}-
253
287
  Dict : {loaded — N canonical terms, M banned terms | missing}
254
288
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
289
+ Service : {active_service} ({active_service_module}) | single-service
255
290
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
256
291
  ```
257
292
 
@@ -446,7 +481,8 @@ Suggest the logical next command based on workflow phase:
446
481
  | /define-product | `/generate-prd {product-definition-file}` |
447
482
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
448
483
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
449
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
484
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
485
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
450
486
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
451
487
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
452
488
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
@@ -131,6 +131,7 @@ Read `.agent/project-context.yaml`. Extract and store:
131
131
  - `paths.core_entities` → path to core-entities.md
132
132
  - `paths.tech_docs_dir` → technical documentation root
133
133
  - `paths.trace_dir` → trace state directory
134
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
134
135
 
135
136
  If `paths` section is absent, use these defaults:
136
137
  - `specs_dir` = `specs/bdd`
@@ -142,11 +143,44 @@ If `paths` section is absent, use these defaults:
142
143
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
143
144
  - `tech_docs_dir` = `specs/tech-docs`
144
145
  - `trace_dir` = `.trace`
146
+ - `design_spec_dir` = `specs/design-spec`
145
147
 
146
148
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
147
149
 
148
150
  ---
149
151
 
152
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
153
+
154
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
155
+
156
+ If `services` section is present:
157
+
158
+ **1. Detect active domain** (in priority order):
159
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
160
+ - Extract from target file path: segment immediately after `prd_dir` base path
161
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
162
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
163
+
164
+ **2. Route to service** — if active domain matches a key in `services`:
165
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
166
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
167
+ - Store `active_service` = `services.{domain}.path`
168
+ - Store `active_service_module` = `services.{domain}.module`
169
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
170
+
171
+ **3. Fallback** — if domain not detected or no matching service key:
172
+ - Keep default paths from Step 1
173
+ - Set `active_service = unresolved`
174
+
175
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
176
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
177
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
178
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
179
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
180
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
181
+
182
+ ---
183
+
150
184
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
151
185
 
152
186
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -252,6 +286,7 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
252
286
  Ticket : {ticket_prefix}-
253
287
  Dict : {loaded — N canonical terms, M banned terms | missing}
254
288
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
289
+ Service : {active_service} ({active_service_module}) | single-service
255
290
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
256
291
  ```
257
292
 
@@ -409,7 +444,8 @@ Suggest the logical next command based on workflow phase:
409
444
  | /define-product | `/generate-prd {product-definition-file}` |
410
445
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
411
446
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
412
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
447
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
448
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
413
449
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
414
450
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
415
451
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
@@ -129,6 +129,7 @@ Read `.agent/project-context.yaml`. Extract and store:
129
129
  - `paths.core_entities` → path to core-entities.md
130
130
  - `paths.tech_docs_dir` → technical documentation root
131
131
  - `paths.trace_dir` → trace state directory
132
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
132
133
 
133
134
  If `paths` section is absent, use these defaults:
134
135
  - `specs_dir` = `specs/bdd`
@@ -140,11 +141,44 @@ If `paths` section is absent, use these defaults:
140
141
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
141
142
  - `tech_docs_dir` = `specs/tech-docs`
142
143
  - `trace_dir` = `.trace`
144
+ - `design_spec_dir` = `specs/design-spec`
143
145
 
144
146
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
145
147
 
146
148
  ---
147
149
 
150
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
151
+
152
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
153
+
154
+ If `services` section is present:
155
+
156
+ **1. Detect active domain** (in priority order):
157
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
158
+ - Extract from target file path: segment immediately after `prd_dir` base path
159
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
160
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
161
+
162
+ **2. Route to service** — if active domain matches a key in `services`:
163
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
164
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
165
+ - Store `active_service` = `services.{domain}.path`
166
+ - Store `active_service_module` = `services.{domain}.module`
167
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
168
+
169
+ **3. Fallback** — if domain not detected or no matching service key:
170
+ - Keep default paths from Step 1
171
+ - Set `active_service = unresolved`
172
+
173
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
174
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
175
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
176
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
177
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
178
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
179
+
180
+ ---
181
+
148
182
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
149
183
 
150
184
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -250,6 +284,7 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
250
284
  Ticket : {ticket_prefix}-
251
285
  Dict : {loaded — N canonical terms, M banned terms | missing}
252
286
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
287
+ Service : {active_service} ({active_service_module}) | single-service
253
288
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
254
289
  ```
255
290
 
@@ -591,7 +626,8 @@ Suggest the logical next command based on workflow phase:
591
626
  | /define-product | `/generate-prd {product-definition-file}` |
592
627
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
593
628
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
594
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
629
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
630
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
595
631
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
596
632
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
597
633
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
@@ -131,6 +131,7 @@ Read `.agent/project-context.yaml`. Extract and store:
131
131
  - `paths.core_entities` → path to core-entities.md
132
132
  - `paths.tech_docs_dir` → technical documentation root
133
133
  - `paths.trace_dir` → trace state directory
134
+ - `paths.design_spec_dir` → Design Spec documents root (FE/App only)
134
135
 
135
136
  If `paths` section is absent, use these defaults:
136
137
  - `specs_dir` = `specs/bdd`
@@ -142,11 +143,44 @@ If `paths` section is absent, use these defaults:
142
143
  - `core_entities` = `specs/domain-knowledge/core-entities.md`
143
144
  - `tech_docs_dir` = `specs/tech-docs`
144
145
  - `trace_dir` = `.trace`
146
+ - `design_spec_dir` = `specs/design-spec`
145
147
 
146
148
  If `tech_stack.module` is set, also load `.agent/modules/{module}/stack-profile.yaml` if it exists.
147
149
 
148
150
  ---
149
151
 
152
+ ## Step 1.5 — [SERVICE ROUTING] Resolve service paths (umbrella mode)
153
+
154
+ *Skip this step entirely if `setup.mode` is not `"umbrella"` and `services` section is absent from project-context.yaml.*
155
+
156
+ If `services` section is present:
157
+
158
+ **1. Detect active domain** (in priority order):
159
+ - Read `@trace.domain` from target file frontmatter (if Gate loaded a target file)
160
+ - Extract from target file path: segment immediately after `prd_dir` base path
161
+ *(e.g., `specs/prd/user/FEAT-01.md` → domain = `user`)*
162
+ - If `$ARGUMENTS` contains a path, extract the segment after `prd_dir`
163
+
164
+ **2. Route to service** — if active domain matches a key in `services`:
165
+ - Override `paths.specs_dir` → `services.{domain}.specs_dir`
166
+ - Override `paths.tech_docs_dir` → `services.{domain}.tech_docs_dir`
167
+ - Store `active_service` = `services.{domain}.path`
168
+ - Store `active_service_module` = `services.{domain}.module`
169
+ - If service has its own `module` → use it as `active_module` (overrides `tech_stack.module`)
170
+
171
+ **3. Fallback** — if domain not detected or no matching service key:
172
+ - Keep default paths from Step 1
173
+ - Set `active_service = unresolved`
174
+
175
+ **4. Spec source auto-override** — if `setup.spec_source` is set AND the corresponding path was not already explicitly set in `paths:`:
176
+ - Override `paths.prd_dir` → `{spec_source}/specs/prd`
177
+ - Override `paths.design_spec_dir` → `{spec_source}/specs/design-spec`
178
+ - Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
179
+ - Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
180
+ - Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
181
+
182
+ ---
183
+
150
184
  ## Step 2 — [PROJECT-CONFIG] Load module stack profile (conditional)
151
185
 
152
186
  If `tech_stack.module` is set, read `.agent/modules/{module}/stack-profile.yaml`.
@@ -252,6 +286,7 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
252
286
  Ticket : {ticket_prefix}-
253
287
  Dict : {loaded — N canonical terms, M banned terms | missing}
254
288
  Entities : {loaded — EntityA, EntityB, EntityC | missing}
289
+ Service : {active_service} ({active_service_module}) | single-service
255
290
  Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
256
291
  ```
257
292
 
@@ -452,7 +487,8 @@ Suggest the logical next command based on workflow phase:
452
487
  | /define-product | `/generate-prd {product-definition-file}` |
453
488
  | /generate-prd | `/refine-prd {prd-file}` then `/review-context {prd-file}` |
454
489
  | /refine-prd | Open Review Board → update PRD → `/review-context {prd-file}` |
455
- | /review-context (PRD) | `/generate-bdd {prd-file}` if APPROVED; fix PRD if NEEDS_FIX |
490
+ | /review-context (PRD) | FE/App: `/generate-design-spec {prd-file}` (then BDD after sign-off); BE: `/generate-bdd {prd-file}` directly; fix PRD if NEEDS_FIX |
491
+ | /generate-design-spec | Designer review → Figma links confirmed → PO + Designer sign-off → `/generate-bdd {prd-file}` |
456
492
  | /generate-bdd | `/review-context {feature-file}` to verify coverage |
457
493
  | /review-context (BDD) | `/generate-tech-docs {UC-ID}` if APPROVED; regenerate if NEEDS_FIX |
458
494
  | /generate-tech-docs | `/review-tech-docs {tech-design-file}` |