@atlashub/smartstack-cli 3.1.0 → 3.3.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 (39) hide show
  1. package/.documentation/prd-json-v2.0.0.md +396 -0
  2. package/.documentation/testing-ba-e2e.md +462 -0
  3. package/dist/index.js +605 -25
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -2
  6. package/templates/agents/ba-reader.md +1 -1
  7. package/templates/agents/ba-writer.md +8 -1
  8. package/templates/skills/business-analyse/SKILL.md +46 -31
  9. package/templates/skills/business-analyse/_architecture.md +123 -0
  10. package/templates/skills/business-analyse/_elicitation.md +206 -0
  11. package/templates/skills/business-analyse/_module-loop.md +56 -0
  12. package/templates/skills/business-analyse/_shared.md +75 -531
  13. package/templates/skills/business-analyse/_suggestions.md +34 -0
  14. package/templates/skills/business-analyse/html/ba-interactive.html +146 -57
  15. package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
  16. package/templates/skills/business-analyse/questionnaire.md +22 -17
  17. package/templates/skills/business-analyse/react/components.md +1 -1
  18. package/templates/skills/business-analyse/react/schema.md +1 -1
  19. package/templates/skills/business-analyse/references/html-data-mapping.md +294 -0
  20. package/templates/skills/business-analyse/schemas/feature-schema.json +1 -1
  21. package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +1 -1
  22. package/templates/skills/business-analyse/schemas/sections/handoff-schema.json +1 -1
  23. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +1 -1
  24. package/templates/skills/business-analyse/steps/step-00-init.md +85 -59
  25. package/templates/skills/business-analyse/steps/step-01-cadrage.md +2 -0
  26. package/templates/skills/business-analyse/steps/step-02-decomposition.md +5 -3
  27. package/templates/skills/business-analyse/steps/{step-03-specify.md → step-03a-specify.md} +16 -606
  28. package/templates/skills/business-analyse/steps/step-03b-compile.md +670 -0
  29. package/templates/skills/business-analyse/steps/step-04-consolidation.md +7 -5
  30. package/templates/skills/business-analyse/steps/step-05a-handoff.md +727 -0
  31. package/templates/skills/business-analyse/steps/step-05b-deploy.md +479 -0
  32. package/templates/skills/business-analyse/steps/step-06-extract.md +134 -4
  33. package/templates/skills/business-analyse/templates/tpl-frd.md +1 -1
  34. package/templates/skills/business-analyse/templates/tpl-launch-displays.md +161 -0
  35. package/templates/skills/business-analyse/templates/tpl-progress.md +171 -0
  36. package/templates/skills/ralph-loop/SKILL.md +138 -20
  37. package/templates/skills/ralph-loop/steps/step-01-task.md +75 -18
  38. package/templates/skills/ralph-loop/steps/step-04-check.md +72 -5
  39. package/templates/skills/business-analyse/steps/step-05-handoff.md +0 -1414
@@ -0,0 +1,727 @@
1
+ ---
2
+ name: step-05a-handoff
3
+ description: Build handoff data - file mapping, BR-to-code, API summary - write to feature.json
4
+ model: sonnet
5
+ next_step: steps/step-05b-deploy.md
6
+ ---
7
+
8
+ > **Context files:** `_shared.md` | `_architecture.md`
9
+
10
+ # Step 5a: Handoff - Build & Write
11
+
12
+ ## MANDATORY EXECUTION RULES
13
+
14
+ - **ALWAYS** verify status = "consolidated" before proceeding
15
+ - **ALWAYS** ask user for implementation strategy preference (multi-module only)
16
+ - **ALWAYS** derive prd.json from feature.json (NEVER independently)
17
+ - **NEVER** invent entities/FRs/BRs not in feature.json
18
+ - **ALL** API routes from specification.apiEndpoints (exact copy)
19
+ - **Permission** paths from specification.permissionMatrix (full format)
20
+ - **ALWAYS** generate 5 CORE SeedData task entries per module
21
+
22
+ ## YOUR TASK
23
+
24
+ Build the development handoff data (file mapping, BR-to-code, API summary) and write it to EACH module feature.json AND master feature.json. This step focuses on DATA — artifacts (prd.json, progress.txt, HTML) are generated in step-05b.
25
+
26
+ ---
27
+
28
+ ## EXECUTION SEQUENCE
29
+
30
+ ### 1. Verify Consolidation Passed
31
+
32
+ Use ba-reader to locate the feature and verify consolidation status:
33
+
34
+ ```
35
+ ba-reader.findFeature({feature_id})
36
+ → Check status = "consolidated"
37
+ ```
38
+
39
+ **IF** status ≠ "consolidated" → **STOP**. Return to step-04-consolidation.md.
40
+
41
+ Display validation summary:
42
+
43
+ ```
44
+ ✓ Consolidation: APPROVED
45
+ ✓ Modules: {count} specified and validated
46
+ ✓ Cross-module: interactions mapped
47
+ ✓ Permissions: coherent
48
+ → Proceeding to handoff...
49
+ ```
50
+
51
+ Include:
52
+ - Number of modules
53
+ - Number of entities across all modules
54
+ - Number of use cases across all modules
55
+ - Number of business rules across all modules
56
+ - Cross-module interaction count
57
+
58
+ ---
59
+
60
+ ### 2. Implementation Strategy Choice (Multi-Module)
61
+
62
+ **IF** more than 1 module defined in feature.json:
63
+
64
+ Ask via AskUserQuestion:
65
+
66
+ ```
67
+ question: "Quelle stratégie d'implémentation préférez-vous ?"
68
+ header: "Stratégie d'implémentation"
69
+ options:
70
+ - label: "Module par module (Recommandé)"
71
+ description: "Implémenter chaque module complètement avant de passer au suivant. Suit l'ordre topologique des dépendances."
72
+ - label: "Couche par couche"
73
+ description: "Implémenter toutes les entités, puis tous les services, puis tous les contrôleurs, etc. Plus de parallélisation possible mais plus complexe."
74
+ - label: "Hybride"
75
+ description: "Modules fondation en premier (couche par couche), puis modules dépendants (module par module)"
76
+ ```
77
+
78
+ Store the chosen strategy in `handoff.implementationStrategy`.
79
+
80
+ **IF** only 1 module → default to "Module par module" (no choice needed).
81
+
82
+ ---
83
+
84
+ ### 3. Calculate Complexity
85
+
86
+ For each module in feature.json.modules[], calculate:
87
+
88
+ ```json
89
+ {
90
+ "complexity": "simple|medium|complex",
91
+ "complexityDetails": {
92
+ "entities": {count},
93
+ "useCases": {count},
94
+ "businessRules": {count},
95
+ "calculated": "{level} (≤X entities, ≤Y UCs, ≤Z BRs)"
96
+ }
97
+ }
98
+ ```
99
+
100
+ | Criteria | Simple | Medium | Complex |
101
+ |----------|--------|--------|---------|
102
+ | Entities | ≤3 | ≤6 | >6 |
103
+ | Use Cases | ≤5 | ≤12 | >12 |
104
+ | Business Rules | ≤10 | ≤20 | >20 |
105
+
106
+ **Global complexity** = highest complexity across all modules.
107
+
108
+ Example:
109
+ - Module A: 4 entities, 6 use cases, 8 BRs → **simple**
110
+ - Module B: 8 entities, 15 use cases, 25 BRs → **complex**
111
+ - Overall: **complex**
112
+
113
+ ---
114
+
115
+ ### 4. Map Specification to Files
116
+
117
+ > **IMPORTANT:** Generate `handoff.filesToCreate` as structured object with 7 categories.
118
+ > Each file entry is `{path, type, linkedFRs, linkedUCs, module}`. NO free text.
119
+ > Read `.smartstack/config.json` to extract baseNamespace for project namespace.
120
+
121
+ **Order by topological dependency** (modules with no deps first, then dependents).
122
+
123
+ For **EACH module** in topological order:
124
+
125
+ #### 4.1 Domain Files
126
+
127
+ From `analysis.entities[]` of the module:
128
+
129
+ ```json
130
+ "domain": [
131
+ {
132
+ "path": "src/Domain/Entities/{ModuleName}/{EntityName}.cs",
133
+ "type": "Entity",
134
+ "linkedFRs": ["FR-001", "FR-002"],
135
+ "linkedUCs": ["UC-001"],
136
+ "module": "{moduleCode}"
137
+ }
138
+ ]
139
+ ```
140
+
141
+ Include:
142
+ - Value objects referenced by entities
143
+ - Enums used in domain
144
+ - Domain exceptions specific to module
145
+
146
+ #### 4.2 Application Files
147
+
148
+ From `analysis.useCases[]` of the module:
149
+
150
+ ```json
151
+ "application": [
152
+ {
153
+ "path": "src/Application/Services/{ModuleName}/{ServiceName}Service.cs",
154
+ "type": "Service",
155
+ "linkedFRs": ["FR-001"],
156
+ "linkedUCs": ["UC-001", "UC-002"],
157
+ "module": "{moduleCode}"
158
+ },
159
+ {
160
+ "path": "src/Application/DTOs/{ModuleName}/{DtoName}Dto.cs",
161
+ "type": "Dto",
162
+ "linkedUCs": ["UC-001"],
163
+ "module": "{moduleCode}"
164
+ },
165
+ {
166
+ "path": "src/Application/Validators/{ModuleName}/{ValidatorName}Validator.cs",
167
+ "type": "Validator",
168
+ "linkedFRs": ["FR-001"],
169
+ "module": "{moduleCode}"
170
+ }
171
+ ]
172
+ ```
173
+
174
+ Include:
175
+ - Service per use case cluster (or per domain entity if applicable)
176
+ - DTOs for API contracts
177
+ - Validators for FluentValidation
178
+ - Query handlers
179
+
180
+ #### 4.3 Infrastructure Files
181
+
182
+ From `analysis.entities[]` of the module:
183
+
184
+ ```json
185
+ "infrastructure": [
186
+ {
187
+ "path": "src/Infrastructure/Repositories/{ModuleName}/{EntityName}Repository.cs",
188
+ "type": "Repository",
189
+ "linkedFRs": ["FR-001"],
190
+ "module": "{moduleCode}"
191
+ },
192
+ {
193
+ "path": "src/Infrastructure/Persistence/{ModuleName}DbContext.cs",
194
+ "type": "DbContext",
195
+ "linkedFRs": ["FR-001", "FR-002"],
196
+ "module": "{moduleCode}"
197
+ }
198
+ ]
199
+ ```
200
+
201
+ Include:
202
+ - Repository per entity
203
+ - DbContext configuration (if module-specific)
204
+ - Unit of Work pattern if applicable
205
+ - Specifications if complex queries
206
+
207
+ #### 4.4 API Files
208
+
209
+ From `specification.apiEndpoints[]` of the module:
210
+
211
+ ```json
212
+ "api": [
213
+ {
214
+ "path": "src/API/Controllers/{ModuleName}Controller.cs",
215
+ "type": "ApiController",
216
+ "linkedUCs": ["UC-001", "UC-002"],
217
+ "linkedFRs": ["FR-001"],
218
+ "module": "{moduleCode}"
219
+ }
220
+ ]
221
+ ```
222
+
223
+ Include:
224
+ - One controller per domain aggregate root (or logical grouping)
225
+ - Include all HTTP methods (GET, POST, PUT, DELETE, PATCH)
226
+ - Error handling and validation responses
227
+
228
+ #### 4.5 Frontend Files
229
+
230
+ From `specification.uiWireframes[]`, `specification.dashboards[]` and `analysis.useCases[]` of the module:
231
+
232
+ > **WIREFRAME TRACEABILITY RULE:** Every frontend file (Page, DashboardPage, Component) MUST include `linkedWireframes[]` referencing the wireframe `screen` identifiers from `specification.uiWireframes[]`. This ensures the BA mockups validated by the client are respected during implementation.
233
+
234
+ ```json
235
+ "frontend": [
236
+ {
237
+ "path": "src/pages/{ModuleName}/{PageName}Page.tsx",
238
+ "type": "Page",
239
+ "linkedUCs": ["UC-001", "UC-002"],
240
+ "linkedWireframes": ["{module}-list"],
241
+ "module": "{moduleCode}",
242
+ "wireframeAcceptanceCriteria": "Layout MUST match wireframe '{module}-list': elements [{elements}], actions [{actions}]. See specification.uiWireframes[] for exact mockup."
243
+ },
244
+ {
245
+ "path": "src/pages/{ModuleName}/{PageName}DetailPage.tsx",
246
+ "type": "Page",
247
+ "linkedUCs": ["UC-003"],
248
+ "linkedWireframes": ["{module}-detail"],
249
+ "module": "{moduleCode}",
250
+ "wireframeAcceptanceCriteria": "Layout MUST match wireframe '{module}-detail': elements [{elements}], actions [{actions}]. See specification.uiWireframes[] for exact mockup."
251
+ },
252
+ {
253
+ "path": "src/pages/{ModuleName}/{DashboardName}DashboardPage.tsx",
254
+ "type": "DashboardPage",
255
+ "linkedUCs": ["UC-060"],
256
+ "linkedWireframes": ["{module}-dashboard"],
257
+ "module": "{moduleCode}",
258
+ "dashboardRef": "{module}-dashboard",
259
+ "instructions": "Use Recharts library. See specification.dashboards[] for KPI definitions, chart types, filters, and data sources.",
260
+ "wireframeAcceptanceCriteria": "Layout MUST match wireframe '{module}-dashboard': KPI card positions, chart placement, filter bar location. See specification.uiWireframes[] AND specification.dashboards[] for exact mockup and KPI specs."
261
+ },
262
+ {
263
+ "path": "src/components/{ModuleName}/{ComponentName}.tsx",
264
+ "type": "Component",
265
+ "linkedUCs": ["UC-001"],
266
+ "linkedWireframes": ["{module}-{section}"],
267
+ "module": "{moduleCode}"
268
+ },
269
+ {
270
+ "path": "src/hooks/use{ModuleName}{Hook}.ts",
271
+ "type": "Hook",
272
+ "linkedUCs": ["UC-001", "UC-002"],
273
+ "module": "{moduleCode}"
274
+ }
275
+ ]
276
+ ```
277
+
278
+ **Wireframe Acceptance Criteria (ALL frontend pages):**
279
+ > **MANDATORY** for every Page and DashboardPage task. These criteria ensure the BA mockups are respected.
280
+ - Layout structure matches the validated ASCII/SVG wireframe from `specification.uiWireframes[]`
281
+ - All `elements` listed in the wireframe are present in the generated component
282
+ - All `actions` listed in the wireframe are implemented with correct permissions
283
+ - Component mapping follows the wireframe-to-component table (see step-03 section 3b-bis)
284
+ - If wireframe shows a DataGrid → implement with `SmartTable` or `EntityCard` grid
285
+ - If wireframe shows FilterBar → implement with `SmartFilter`
286
+ - If wireframe shows ActionButton → wrap in `RequirePermission`
287
+
288
+ **Dashboard pages (type: DashboardPage):**
289
+ - Generated from `specification.dashboards[]` entries
290
+ - `dashboardRef` links to the dashboard code in specification.dashboards[]
291
+ - `linkedWireframes` links to the dashboard wireframe in specification.uiWireframes[]
292
+ - `instructions` MUST reference chart types, KPI definitions, and data sources
293
+ - Acceptance criteria for DashboardPage tasks MUST include:
294
+ - Chart library (Recharts) installed in package.json
295
+ - Chart types matching specification.dashboards[].kpis[].visualization
296
+ - KPI cards for kpi-card type visualizations
297
+ - Filters functional (dateRange, select, etc.)
298
+ - CSS variables used (no hardcoded colors) - see ui-components/patterns/dashboard-chart.md
299
+ - Responsive layout (1-col mobile, 2-col tablet, 3-col desktop)
300
+ - **KPI card positions match wireframe layout** (e.g., 4 cards in a row if wireframe shows 4)
301
+ - **Chart placement matches wireframe** (e.g., 2-column grid if wireframe shows side-by-side)
302
+
303
+ **Standard pages (type: Page):**
304
+ - Pages for major use cases
305
+ - Components for reusable UI elements
306
+ - Custom hooks for business logic
307
+ - Forms for data entry
308
+ - List/Detail views
309
+ - **ALL pages MUST reference their wireframe via `linkedWireframes`**
310
+
311
+ #### 4.6 SeedData Files
312
+
313
+ **OBLIGATORY:** 5 CORE SeedData entries per module + business seed data:
314
+
315
+ ```json
316
+ "seedData": [
317
+ {
318
+ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/NavigationModuleSeedData.cs",
319
+ "type": "SeedData",
320
+ "category": "core",
321
+ "source": "specification.seedDataCore.navigationModules",
322
+ "module": "{moduleCode}"
323
+ },
324
+ {
325
+ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/PermissionsSeedData.cs",
326
+ "type": "SeedData",
327
+ "category": "core",
328
+ "source": "specification.seedDataCore.permissions",
329
+ "module": "{moduleCode}"
330
+ },
331
+ {
332
+ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/RolesSeedData.cs",
333
+ "type": "SeedData",
334
+ "category": "core",
335
+ "source": "specification.seedDataCore.roles",
336
+ "module": "{moduleCode}"
337
+ },
338
+ {
339
+ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/TenantSeedData.cs",
340
+ "type": "SeedData",
341
+ "category": "core",
342
+ "source": "specification.seedDataCore.tenants",
343
+ "module": "{moduleCode}"
344
+ },
345
+ {
346
+ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/UserSeedData.cs",
347
+ "type": "SeedData",
348
+ "category": "core",
349
+ "source": "specification.seedDataCore.users",
350
+ "module": "{moduleCode}"
351
+ },
352
+ {
353
+ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/{Entity}SeedData.cs",
354
+ "type": "SeedData",
355
+ "category": "business",
356
+ "source": "specification.seedDataBusiness.{module}",
357
+ "module": "{moduleCode}"
358
+ }
359
+ ]
360
+ ```
361
+
362
+ **For client projects (ExtensionsDbContext), add these MANDATORY infrastructure files:**
363
+
364
+ ```json
365
+ "seedData": [
366
+ // ... 5 core + business entries above ...
367
+ {
368
+ "path": "src/Infrastructure/Persistence/Seeding/{AppPascalName}SeedDataProvider.cs",
369
+ "type": "IClientSeedDataProvider",
370
+ "category": "infrastructure",
371
+ "description": "Runtime provider that injects core seed data (navigation, permissions, roles) into Core schema",
372
+ "source": "specification.seedDataCore",
373
+ "module": "{moduleCode}"
374
+ },
375
+ {
376
+ "path": "src/Infrastructure/Persistence/Seeding/DevDataSeeder.cs",
377
+ "type": "DevDataSeeder",
378
+ "category": "infrastructure",
379
+ "description": "Seeds development/demo data for domain entities at startup",
380
+ "module": "{moduleCode}"
381
+ },
382
+ {
383
+ "path": "src/Infrastructure/Persistence/Seeding/Data/SeedConstants.cs",
384
+ "type": "SeedConstants",
385
+ "category": "infrastructure",
386
+ "description": "Shared constants for deterministic seed data",
387
+ "module": "{moduleCode}"
388
+ }
389
+ ]
390
+ ```
391
+
392
+ **Path convention:** All seed data files MUST be under `Persistence/Seeding/Data/` (matching SmartStack.app architecture).
393
+ NEVER use `Data/SeedData/` or `Infrastructure/Data/SeedData/`.
394
+
395
+ **IClientSeedDataProvider (MANDATORY for client projects):** This provider injects core seed data
396
+ (navigation, permissions, roles) into the Core schema at runtime. Generated at
397
+ `src/Infrastructure/Persistence/Seeding/{AppPascalName}SeedDataProvider.cs`.
398
+ See `/application` skill step-03b-provider for the full pattern.
399
+ Without this provider, the 5 core SeedData files are DEAD CODE and will have no effect.
400
+
401
+ Core categories (ALWAYS 5):
402
+ 1. NavigationModuleSeedData (navigation items for module)
403
+ 2. PermissionsSeedData (RBAC permissions)
404
+ 3. RolesSeedData (roles using permissions)
405
+ 4. TenantSeedData (test tenants)
406
+ 5. UserSeedData (test users)
407
+
408
+ Business categories (from specification.seedDataBusiness):
409
+ - Domain-specific reference data
410
+ - Test data fixtures
411
+ - Lookup tables (statuses, categories, etc.)
412
+
413
+ #### 4.7 Test Files
414
+
415
+ ```json
416
+ "tests": [
417
+ {
418
+ "path": "src/Tests/Unit/Domain/{ModuleName}/{Entity}Tests.cs",
419
+ "type": "UnitTests",
420
+ "linkedFRs": ["FR-001"],
421
+ "module": "{moduleCode}"
422
+ },
423
+ {
424
+ "path": "src/Tests/Unit/Application/{ModuleName}/{ServiceName}ServiceTests.cs",
425
+ "type": "UnitTests",
426
+ "linkedFRs": ["FR-001"],
427
+ "linkedUCs": ["UC-001"],
428
+ "module": "{moduleCode}"
429
+ },
430
+ {
431
+ "path": "src/Tests/Integration/{ModuleName}/{ApiControllerName}ControllerTests.cs",
432
+ "type": "IntegrationTests",
433
+ "linkedUCs": ["UC-001"],
434
+ "module": "{moduleCode}"
435
+ },
436
+ {
437
+ "path": "src/Tests/Security/{ModuleName}/{ModuleName}SecurityTests.cs",
438
+ "type": "SecurityTests",
439
+ "linkedFRs": ["FR-001"],
440
+ "module": "{moduleCode}"
441
+ }
442
+ ]
443
+ ```
444
+
445
+ Test files:
446
+ - Unit tests for domain entities and value objects
447
+ - Unit tests for services and validators
448
+ - Integration tests for API endpoints
449
+ - Security tests for authorization and tenant isolation
450
+ - E2E tests for critical user flows
451
+
452
+ ---
453
+
454
+ ### 5. Map Business Rules to Code
455
+
456
+ Derive from `analysis.businessRules[]` of **EACH module**.
457
+
458
+ Generate complete mapping for each BR:
459
+
460
+ ```json
461
+ {
462
+ "brToCodeMapping": [
463
+ {
464
+ "ruleId": "BR-VAL-001",
465
+ "title": "Order total must equal sum of item prices",
466
+ "module": "{moduleCode}",
467
+ "severity": "critical",
468
+ "implementationPoints": [
469
+ {
470
+ "layer": "Domain",
471
+ "component": "Order.cs",
472
+ "method": "CalculateTotal()",
473
+ "implementation": "Validate sum equals sum of OrderItems.Price"
474
+ },
475
+ {
476
+ "layer": "Application",
477
+ "component": "CreateOrderService.cs",
478
+ "method": "Handle()",
479
+ "implementation": "Calculate total before persisting"
480
+ },
481
+ {
482
+ "layer": "API",
483
+ "component": "OrdersController.cs",
484
+ "method": "CreateOrder()",
485
+ "implementation": "Return validation error if total mismatch"
486
+ },
487
+ {
488
+ "layer": "Frontend",
489
+ "component": "OrderForm.tsx",
490
+ "method": "calculateTotal()",
491
+ "implementation": "Real-time calculation on item change"
492
+ }
493
+ ]
494
+ },
495
+ {
496
+ "ruleId": "BR-SEC-002",
497
+ "title": "User can only view orders from their tenant",
498
+ "module": "{moduleCode}",
499
+ "severity": "critical",
500
+ "implementationPoints": [
501
+ {
502
+ "layer": "Domain",
503
+ "component": "Order.cs",
504
+ "method": "Validate()",
505
+ "implementation": "Check TenantId matches user context"
506
+ },
507
+ {
508
+ "layer": "Infrastructure",
509
+ "component": "OrderRepository.cs",
510
+ "method": "GetUserOrders()",
511
+ "implementation": "Filter by TenantId in WHERE clause"
512
+ },
513
+ {
514
+ "layer": "API",
515
+ "component": "OrdersController.cs",
516
+ "method": "GetOrders()",
517
+ "implementation": "Enforce permission check + tenant filter"
518
+ }
519
+ ]
520
+ }
521
+ ]
522
+ }
523
+ ```
524
+
525
+ For each BR include:
526
+ - **ruleId**: Reference to analysis.businessRules[].id
527
+ - **title**: The rule statement
528
+ - **module**: Which module it belongs to
529
+ - **severity**: "critical", "high", "medium", "low"
530
+ - **implementationPoints**: Array of {layer, component, method, implementation}
531
+
532
+ Layers: Domain, Application, Infrastructure, API, Frontend
533
+
534
+ ---
535
+
536
+ ### 6. API Endpoint Summary
537
+
538
+ > **ABSOLUTE RULE:** Copy **EXACTLY** from `specification.apiEndpoints[]`. **NEVER** reinvent routes.
539
+
540
+ Generate summary with full details:
541
+
542
+ ```json
543
+ {
544
+ "apiEndpointSummary": [
545
+ {
546
+ "operation": "ListOrders",
547
+ "method": "GET",
548
+ "route": "/api/business/orders",
549
+ "linkedUC": "UC-001",
550
+ "linkedFR": "FR-001",
551
+ "permissions": ["business.orders.read"],
552
+ "requestSchema": { "type": "query", "params": ["pageNumber", "pageSize", "status"] },
553
+ "responseSchema": { "type": "PaginatedOrderDto[]" },
554
+ "errorCodes": [401, 403, 400, 500],
555
+ "module": "{moduleCode}"
556
+ },
557
+ {
558
+ "operation": "CreateOrder",
559
+ "method": "POST",
560
+ "route": "/api/business/orders",
561
+ "linkedUC": "UC-002",
562
+ "linkedFR": "FR-002",
563
+ "permissions": ["business.orders.create"],
564
+ "requestSchema": { "type": "body", "schema": "CreateOrderDto" },
565
+ "responseSchema": { "type": "OrderDto" },
566
+ "errorCodes": [400, 401, 403, 422, 500],
567
+ "module": "{moduleCode}"
568
+ }
569
+ ]
570
+ }
571
+ ```
572
+
573
+ For each endpoint:
574
+ - **operation**: Use case name or operation name
575
+ - **method**: HTTP method (GET, POST, PUT, DELETE, PATCH)
576
+ - **route**: Full API path from specification
577
+ - **linkedUC**: Use case ID(s) this endpoint implements
578
+ - **linkedFR**: Feature requirement ID(s)
579
+ - **permissions**: Array of exact permission paths
580
+ - **requestSchema**: Input contract (query params or body)
581
+ - **responseSchema**: Output contract
582
+ - **errorCodes**: Expected HTTP error codes
583
+ - **module**: Which module
584
+
585
+ Total endpoints = count of specification.apiEndpoints[] across all modules.
586
+
587
+ ---
588
+
589
+ ### 7. Write Handoff to Feature.json
590
+
591
+ > **BLOCKING RULE: The handoff MUST be written in EACH module feature.json.**
592
+ > A handoff at master level alone is INSUFFICIENT. Ralph-loop consumes module-level handoffs.
593
+ > An empty module handoff (`"handoff": {}`) is a CRITICAL BUG that blocks all downstream generation.
594
+
595
+ #### 7a. Module Handoff Loop (MANDATORY)
596
+
597
+ > **STRUCTURE CARD: handoff** — Field names are EXACT. Include ALL fields below.
598
+ > ```json
599
+ > {
600
+ > "complexity": "simple|medium|complex",
601
+ > "filesToCreate": {
602
+ > "domain": [{"path": "...", "type": "Entity|ValueObject|Enum", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
603
+ > "application": [{"path": "...", "type": "Service|Dto|Validator", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
604
+ > "infrastructure": [{"path": "...", "type": "Repository|DbContext", "linkedFRs": [], "module": "..."}],
605
+ > "api": [{"path": "...", "type": "ApiController", "linkedUCs": [], "linkedFRs": [], "module": "..."}],
606
+ > "frontend": [{"path": "...", "type": "Page|Component|Hook|DashboardPage", "linkedUCs": [], "linkedWireframes": [], "module": "..."}],
607
+ > "seedData": [{"path": "...", "type": "HasData", "category": "core|business", "source": "...", "module": "..."}],
608
+ > "tests": [{"path": "...", "type": "UnitTests|IntegrationTests|SecurityTests", "linkedFRs": [], "linkedUCs": [], "module": "..."}]
609
+ > },
610
+ > "brToCodeMapping": [{"ruleId": "BR-...", "files": ["path1", "path2"], "implementation": "description"}],
611
+ > "apiEndpointSummary": [{"method": "GET|POST|PUT|DELETE", "path": "/api/...", "permission": "business.{app}.{module}.{action}", "linkedUC": "UC-..."}],
612
+ > "prdFile": ".ralph/prd-{module}.json",
613
+ > "totalFiles": 0,
614
+ > "totalTasks": 0,
615
+ > "handedOffAt": "{ISO timestamp}"
616
+ > }
617
+ > ```
618
+ > **MANDATORY fields:** ALL of the above. `filesToCreate` MUST have all 7 categories (even if empty arrays).
619
+ > **FORBIDDEN:** `handoff: {}` (empty object is a CRITICAL BUG). Missing `brToCodeMapping` or `apiEndpointSummary`.
620
+
621
+ **For i = 0; i < modules.length; i++:**
622
+
623
+ ```
624
+ 1. moduleCode = modules[i].code
625
+ 2. moduleFeatureId = modules[i].featureJsonPath or find via ba-reader.findFeature()
626
+ 3. Read the module feature.json via ba-reader.findFeature(moduleFeatureId)
627
+ 4. Build the handoff payload for THIS module:
628
+ - complexity (from step 3 calculation)
629
+ - filesToCreate (full 7-category structure from step 4, filtered for this module)
630
+ - brToCodeMapping (from step 5, filtered for this module)
631
+ - apiEndpointSummary (from step 6, filtered for this module)
632
+ - prdFile path
633
+ - totalFiles count
634
+ - totalTasks count
635
+ - handedOffAt timestamp
636
+
637
+ 5. Write via ba-writer:
638
+ ba-writer.enrichModuleHandoff({
639
+ moduleFeatureId: {moduleFeatureId},
640
+ handoffData: {
641
+ complexity: "{simple|medium|complex}",
642
+ filesToCreate: {...},
643
+ brToCodeMapping: [...],
644
+ apiEndpointSummary: [...],
645
+ prdFile: ".ralph/prd-{moduleCode}.json",
646
+ totalFiles: {count},
647
+ totalTasks: {count},
648
+ handedOffAt: "{ISO timestamp}"
649
+ }
650
+ })
651
+
652
+ 6. VERIFICATION (MANDATORY - done automatically by enrichModuleHandoff):
653
+ - handoff !== {}
654
+ - handoff.filesToCreate has 7 categories
655
+ - handoff.brToCodeMapping.length > 0
656
+ IF verification fails → STOP, report error, do NOT continue
657
+
658
+ 7. Display progress:
659
+ "✓ Handoff module {i+1}/{N} : {moduleCode} ({fileCount} fichiers, {brCount} BRs mappées)"
660
+ ```
661
+
662
+ #### 7b. Master Handoff (after ALL modules written successfully)
663
+
664
+ ```
665
+ ba-writer.enrichSection({
666
+ featureId: {feature_id},
667
+ section: "handoff",
668
+ data: {
669
+ status: "handed-off",
670
+ complexity: "{simple|medium|complex}",
671
+ implementationStrategy: "{strategy}",
672
+ moduleCount: {count},
673
+ moduleOrder: [...],
674
+ totalFilesToCreate: {sum across all modules},
675
+ totalTasks: {sum across all modules},
676
+ prdStructure: "per-module | consolidated",
677
+ prdFiles: [
678
+ { module: "{module1}", path: ".ralph/prd-{module1}.json" },
679
+ { module: "{module2}", path: ".ralph/prd-{module2}.json" }
680
+ ],
681
+ progressTrackerPath: ".ralph/progress.txt",
682
+ handedOffAt: "{ISO timestamp}"
683
+ }
684
+ })
685
+ ```
686
+
687
+ #### 7c. Final Verification (BLOCKING)
688
+
689
+ ```
690
+ count = 0
691
+ FOR each module in modules[]:
692
+ Read module feature.json
693
+ IF module.handoff !== {} AND module.status === "handed-off":
694
+ count++
695
+
696
+ IF count < modules.length:
697
+ → BLOCKING ERROR: {modules.length - count} modules missing handoff
698
+ → List the missing modules by name
699
+ → DO NOT proceed to step 10
700
+ → Return to 9a for missing modules only
701
+
702
+ IF count === modules.length:
703
+ ba-writer.updateStatus({feature_id}, "handed-off")
704
+ Display: "✓ Handoff complet: {count}/{modules.length} modules avec handoff valide"
705
+ ```
706
+
707
+ Status journey: analyze → consolidate → **handed-off**
708
+
709
+ ---
710
+
711
+ ## SELF-VERIFICATION (MANDATORY before loading step-05b)
712
+
713
+ Before proceeding to step-05b-deploy.md, VERIFY:
714
+
715
+ 1. **ALL module feature.json** have `handoff` section with 7 categories in `filesToCreate` (domain, application, infrastructure, api, frontend, seedData, tests)
716
+ 2. **ALL module feature.json** have `handoff.brToCodeMapping.length > 0`
717
+ 3. **ALL module feature.json** status = "handed-off"
718
+ 4. **Master feature.json** has `handoff` section with implementationStrategy, moduleOrder, totalFilesToCreate
719
+ 5. **Master status** = "handed-off"
720
+
721
+ **IF any check fails → FIX before proceeding.** Do NOT generate artifacts (prd.json, progress.txt) without complete handoff data.
722
+
723
+ ---
724
+
725
+ ## NEXT STEP
726
+
727
+ Load: `steps/step-05b-deploy.md`