@atlashub/smartstack-cli 2.1.0 → 2.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.
- package/.documentation/business-analyse.html +1503 -1058
- package/dist/index.js +92 -55
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
- package/templates/agents/ba-reader.md +250 -0
- package/templates/agents/ba-writer.md +210 -0
- package/templates/agents/docs-context-reader.md +51 -33
- package/templates/skills/_shared.md +2 -0
- package/templates/skills/business-analyse/SKILL.md +120 -108
- package/templates/skills/business-analyse/_shared.md +136 -146
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +478 -0
- package/templates/skills/business-analyse/questionnaire/01-context.md +3 -15
- package/templates/skills/business-analyse/questionnaire/03-scope.md +7 -7
- package/templates/skills/business-analyse/questionnaire/08-performance.md +7 -21
- package/templates/skills/business-analyse/questionnaire/09-constraints.md +0 -13
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +0 -13
- package/templates/skills/business-analyse/questionnaire/12-migration.md +1 -1
- package/templates/skills/business-analyse/questionnaire.md +72 -76
- package/templates/skills/business-analyse/react/components.md +317 -154
- package/templates/skills/business-analyse/react/i18n-template.md +167 -106
- package/templates/skills/business-analyse/react/schema.md +474 -107
- package/templates/skills/business-analyse/schemas/feature-schema.json +860 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +395 -285
- package/templates/skills/business-analyse/steps/step-01-analyse.md +523 -0
- package/templates/skills/business-analyse/steps/step-02-specify.md +899 -0
- package/templates/skills/business-analyse/steps/step-03-validate.md +1009 -0
- package/templates/skills/business-analyse/steps/step-04-handoff.md +1802 -0
- package/templates/skills/business-analyse/templates/tpl-handoff.md +49 -64
- package/templates/skills/business-analyse/steps/step-01-discover.md +0 -737
- package/templates/skills/business-analyse/steps/step-02-analyse.md +0 -299
- package/templates/skills/business-analyse/steps/step-03-specify.md +0 -472
- package/templates/skills/business-analyse/steps/step-04-validate.md +0 -335
- package/templates/skills/business-analyse/steps/step-05-handoff.md +0 -741
- package/templates/skills/business-analyse/steps/step-06-doc-html.md +0 -320
- package/templates/skills/business-analyse/templates/00-context.md +0 -105
- package/templates/skills/business-analyse/templates/tpl-brd.md +0 -97
- package/templates/skills/business-analyse/templates/tpl-discovery.md +0 -78
- package/templates/skills/business-analyse/tracking/change-template.md +0 -30
|
@@ -0,0 +1,1802 @@
|
|
|
1
|
+
# Step 04: Handoff
|
|
2
|
+
|
|
3
|
+
> **Version:** 3.0.0
|
|
4
|
+
> **Name:** step-04-handoff
|
|
5
|
+
> **Next step:** null (final step in business-analyse)
|
|
6
|
+
> **Purpose:** Generate development handoff package (feature.json.handoff + .ralph/prd.json) ready for coding
|
|
7
|
+
> **Input:** feature.json (specification + validation sections, status: "approved")
|
|
8
|
+
> **Output:** feature.json.handoff enriched + .ralph/prd.json + .ralph/progress.txt + status: "handed-off"
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Introduction
|
|
13
|
+
|
|
14
|
+
This step **finalizes the transition** from business analysis to development. You will:
|
|
15
|
+
|
|
16
|
+
1. **Verify validation passed** - Ensure status is "approved"
|
|
17
|
+
2. **Explore existing patterns** - Search for similar modules, code generators, or scaffolding agents
|
|
18
|
+
3. **Map specification to files** - Document which backend/frontend/seeddata tables implement each requirement
|
|
19
|
+
4. **Generate implementation instructions** - Task breakdown for developers
|
|
20
|
+
5. **Map business rules to code** - Where each BR will be validated
|
|
21
|
+
6. **Define API endpoints** - RESTful routes for all operations
|
|
22
|
+
7. **Test requirements** - Unit, integration, and E2E test mapping
|
|
23
|
+
8. **Plan i18n keys** - Translation keys for UI and messages
|
|
24
|
+
9. **Generate Ralph Loop prd.json** - Comprehensive product requirements document
|
|
25
|
+
10. **Initialize progress tracker** - Progress.txt for monitoring completion
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Mode Support
|
|
30
|
+
|
|
31
|
+
### Standard Mode
|
|
32
|
+
Execute full handoff with all implementation details.
|
|
33
|
+
|
|
34
|
+
### Micro Mode
|
|
35
|
+
IF use_case = micro:
|
|
36
|
+
- Simplified handoff with minimal tasks
|
|
37
|
+
- Only essential CRUD endpoints
|
|
38
|
+
- Basic prd.json (fewer layers, simplified task decomposition)
|
|
39
|
+
- Auto-suggest Feature Full agent for fast scaffolding
|
|
40
|
+
|
|
41
|
+
### Delta Mode
|
|
42
|
+
IF use_case = refactoring:
|
|
43
|
+
- Generate handoff only for affected features
|
|
44
|
+
- Reuse existing implementation patterns
|
|
45
|
+
- Update prd.json only for changed sections
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. Verify Validation Passed
|
|
50
|
+
|
|
51
|
+
### 2.1 Check Status
|
|
52
|
+
|
|
53
|
+
Before proceeding, verify:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"validation": {
|
|
58
|
+
"status": "approved" ✓,
|
|
59
|
+
"approvalMode": "standard|force",
|
|
60
|
+
"approvedAt": "2025-02-01T10:35:00Z",
|
|
61
|
+
"decision": {
|
|
62
|
+
"approved": true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Issue:** If status ≠ "approved" → **Stop. Return to step-03-validate.md.**
|
|
69
|
+
|
|
70
|
+
### 2.2 Validation Summary
|
|
71
|
+
|
|
72
|
+
Display summary before proceeding:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Validating approval status...
|
|
76
|
+
✓ Validation: APPROVED
|
|
77
|
+
✓ Specification: Complete & consistent
|
|
78
|
+
✓ Decision: Ready for handoff
|
|
79
|
+
|
|
80
|
+
Proceeding to implementation planning...
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 3. Explore Existing Patterns
|
|
86
|
+
|
|
87
|
+
### 3.1 Parallel Agents & Code Generators
|
|
88
|
+
|
|
89
|
+
Before generating prd.json, check for existing tools:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Searching for similar modules and scaffolding agents...
|
|
93
|
+
|
|
94
|
+
Available options:
|
|
95
|
+
1. Feature Full (claude-code skill) → Fast scaffolding (recommended)
|
|
96
|
+
2. Ralph Loop (local prd.json runner) → Task-driven development
|
|
97
|
+
3. Economy Mode (async generation) → Large-scale projects
|
|
98
|
+
4. Custom MCP Tools (SmartStack.mcp) → Validation & generation
|
|
99
|
+
|
|
100
|
+
Selected: Feature Full + Ralph Loop
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3.2 Code Generation Options
|
|
104
|
+
|
|
105
|
+
Offer user choices:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"generationOptions": [
|
|
110
|
+
{
|
|
111
|
+
"id": 1,
|
|
112
|
+
"tool": "Feature Full",
|
|
113
|
+
"description": "Parallel code generation (C#, React, tests)",
|
|
114
|
+
"duration": "15-30 min",
|
|
115
|
+
"coverage": "70-80%"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": 2,
|
|
119
|
+
"tool": "Ralph Loop",
|
|
120
|
+
"description": "Task-driven coding (sequential, detailed)",
|
|
121
|
+
"duration": "1-2 hours",
|
|
122
|
+
"coverage": "95-100%"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": 3,
|
|
126
|
+
"tool": "Economy Mode",
|
|
127
|
+
"description": "Asynchronous generation in background",
|
|
128
|
+
"duration": "varies",
|
|
129
|
+
"coverage": "Depends on parallelization"
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
"recommended": "Feature Full + Ralph Loop (combined approach)"
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
User selects which agent to use in next step.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 4. Map Specification to Files
|
|
141
|
+
|
|
142
|
+
> **IMPORTANT :** Cette section génère `handoff.filesToCreate` comme un **objet structuré** avec 7 catégories.
|
|
143
|
+
> Chaque fichier est un objet `{path, type, linkedFRs, linkedUCs}`. **PAS de texte libre.**
|
|
144
|
+
> Les chemins doivent utiliser le namespace du projet (lire `.smartstack/config.json.baseNamespace`).
|
|
145
|
+
|
|
146
|
+
### 4.1 Domain File Mapping
|
|
147
|
+
|
|
148
|
+
For each entity in `specification.entities[]`, create domain files:
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"filesToCreate": {
|
|
153
|
+
"domain": [
|
|
154
|
+
{
|
|
155
|
+
"path": "src/Domain/Entities/Order.cs",
|
|
156
|
+
"type": "Entity",
|
|
157
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003"]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"path": "src/Domain/Entities/OrderStatus.cs",
|
|
161
|
+
"type": "Enum",
|
|
162
|
+
"linkedFRs": ["FR-001"]
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 4.2 Application File Mapping
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"filesToCreate": {
|
|
174
|
+
"application": [
|
|
175
|
+
{
|
|
176
|
+
"path": "src/Application/Services/OrderService.cs",
|
|
177
|
+
"type": "Service",
|
|
178
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003", "FR-004"],
|
|
179
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003", "UC-004"]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"path": "src/Application/DTOs/OrderDto.cs",
|
|
183
|
+
"type": "DTO",
|
|
184
|
+
"linkedFRs": ["FR-001"]
|
|
185
|
+
}
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 4.3 Infrastructure File Mapping
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"filesToCreate": {
|
|
196
|
+
"infrastructure": [
|
|
197
|
+
{
|
|
198
|
+
"path": "src/Infrastructure/Repositories/OrderRepository.cs",
|
|
199
|
+
"type": "Repository",
|
|
200
|
+
"linkedFRs": ["FR-001"]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"path": "src/Infrastructure/Data/Migrations/AddOrderTable.cs",
|
|
204
|
+
"type": "Migration",
|
|
205
|
+
"linkedFRs": ["FR-001"]
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 4.4 API File Mapping
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"filesToCreate": {
|
|
217
|
+
"api": [
|
|
218
|
+
{
|
|
219
|
+
"path": "src/API/Controllers/OrdersController.cs",
|
|
220
|
+
"type": "ApiController",
|
|
221
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003", "UC-004", "UC-005", "UC-006"]
|
|
222
|
+
}
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 4.5 Frontend File Mapping
|
|
229
|
+
|
|
230
|
+
For each use case in `specification.useCases[]`, create UI files:
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"filesToCreate": {
|
|
235
|
+
"frontend": [
|
|
236
|
+
{
|
|
237
|
+
"path": "src/pages/Orders/OrderListPage.tsx",
|
|
238
|
+
"type": "Page",
|
|
239
|
+
"linkedUCs": ["UC-001"],
|
|
240
|
+
"linkedFRs": ["FR-001"]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"path": "src/components/Orders/OrderListTable.tsx",
|
|
244
|
+
"type": "Component",
|
|
245
|
+
"linkedFRs": ["FR-001"]
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"path": "src/components/Orders/CreateOrderForm.tsx",
|
|
249
|
+
"type": "Component",
|
|
250
|
+
"linkedFRs": ["FR-002", "FR-003"]
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"path": "src/services/api/OrdersApiClient.ts",
|
|
254
|
+
"type": "ApiClient",
|
|
255
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003"]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"path": "src/stores/ordersSlice.ts",
|
|
259
|
+
"type": "ReduxSlice",
|
|
260
|
+
"linkedFRs": ["FR-001"]
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 4.6 SeedData File Mapping
|
|
268
|
+
|
|
269
|
+
> **OBLIGATOIRE : 2 catégories de SeedData**
|
|
270
|
+
> 1. **SeedData Core** (5 fichiers obligatoires) : navigation, permissions, rôles — dérivés de `specification.seedDataCore`
|
|
271
|
+
> 2. **SeedData Métier** (N fichiers) : tables de référence (Status, Priority, etc.) — dérivés de `specification.entities` et `specification.navigationHierarchy`
|
|
272
|
+
|
|
273
|
+
#### 4.6.1 SeedData Core (OBLIGATOIRE - 5 fichiers)
|
|
274
|
+
|
|
275
|
+
**Source :** `feature.json.specification.seedDataCore` (généré en step-02)
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"filesToCreate": {
|
|
280
|
+
"seedData": [
|
|
281
|
+
{
|
|
282
|
+
"path": "src/Infrastructure/Data/SeedData/NavigationModuleConfiguration.cs",
|
|
283
|
+
"type": "HasData",
|
|
284
|
+
"category": "core",
|
|
285
|
+
"source": "specification.seedDataCore.navigationModules",
|
|
286
|
+
"linkedFRs": []
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"path": "src/Infrastructure/Data/SeedData/NavigationTranslationConfiguration.cs",
|
|
290
|
+
"type": "HasData",
|
|
291
|
+
"category": "core",
|
|
292
|
+
"source": "specification.seedDataCore.navigationTranslations",
|
|
293
|
+
"linkedFRs": []
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"path": "src/Infrastructure/Data/SeedData/PermissionConfiguration.cs",
|
|
297
|
+
"type": "HasData",
|
|
298
|
+
"category": "core",
|
|
299
|
+
"source": "specification.seedDataCore.permissions",
|
|
300
|
+
"linkedFRs": []
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"path": "src/Infrastructure/Data/SeedData/RolePermissionConfiguration.cs",
|
|
304
|
+
"type": "HasData",
|
|
305
|
+
"category": "core",
|
|
306
|
+
"source": "specification.seedDataCore.rolePermissions",
|
|
307
|
+
"linkedFRs": []
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"path": "src/Application/Constants/Permissions.cs",
|
|
311
|
+
"type": "Constants",
|
|
312
|
+
"category": "core",
|
|
313
|
+
"source": "specification.seedDataCore.permissionConstants",
|
|
314
|
+
"linkedFRs": []
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
> **CRITIQUE :** Sans ces 5 fichiers, le module sera invisible dans l'application (erreur 403).
|
|
322
|
+
> Le contenu de chaque fichier doit correspondre EXACTEMENT aux données dans `specification.seedDataCore`.
|
|
323
|
+
|
|
324
|
+
#### 4.6.2 SeedData Métier
|
|
325
|
+
|
|
326
|
+
Map mandatory SeedData tables from `specification.navigationHierarchy.seedDataRequired`:
|
|
327
|
+
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"filesToCreate": {
|
|
331
|
+
"seedData": [
|
|
332
|
+
{
|
|
333
|
+
"path": "src/Infrastructure/Data/SeedData/OrderStatusConfiguration.cs",
|
|
334
|
+
"type": "HasData",
|
|
335
|
+
"category": "business",
|
|
336
|
+
"source": "specification.navigationHierarchy.seedDataRequired[0]",
|
|
337
|
+
"linkedFRs": ["FR-001"],
|
|
338
|
+
"rows": 5
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
"path": "src/Infrastructure/Data/SeedData/OrderPriorityConfiguration.cs",
|
|
342
|
+
"type": "HasData",
|
|
343
|
+
"category": "business",
|
|
344
|
+
"linkedFRs": [],
|
|
345
|
+
"rows": 3
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### 4.7 Tests File Mapping
|
|
353
|
+
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"filesToCreate": {
|
|
357
|
+
"tests": [
|
|
358
|
+
{
|
|
359
|
+
"path": "src/Tests/Application/OrderServiceTests.cs",
|
|
360
|
+
"type": "UnitTests",
|
|
361
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003", "FR-004"]
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"path": "src/Tests/Integration/OrderApiTests.cs",
|
|
365
|
+
"type": "IntegrationTests",
|
|
366
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003"]
|
|
367
|
+
}
|
|
368
|
+
]
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 5. Generate Implementation Instructions
|
|
376
|
+
|
|
377
|
+
### 5.1 Backend Implementation Sequence
|
|
378
|
+
|
|
379
|
+
Create ordered task list:
|
|
380
|
+
|
|
381
|
+
```json
|
|
382
|
+
{
|
|
383
|
+
"implementationSequence": {
|
|
384
|
+
"backend": [
|
|
385
|
+
{
|
|
386
|
+
"phase": 1,
|
|
387
|
+
"name": "Domain Layer",
|
|
388
|
+
"tasks": [
|
|
389
|
+
{
|
|
390
|
+
"taskId": "TASK-001",
|
|
391
|
+
"title": "Define Order entity",
|
|
392
|
+
"linkedFRs": ["FR-001"],
|
|
393
|
+
"file": "src/Domain/Entities/Order.cs",
|
|
394
|
+
"priority": 1,
|
|
395
|
+
"effort": "2h"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"taskId": "TASK-002",
|
|
399
|
+
"title": "Define order status enum",
|
|
400
|
+
"linkedFRs": ["FR-001"],
|
|
401
|
+
"file": "src/Domain/Entities/OrderStatus.cs",
|
|
402
|
+
"priority": 2,
|
|
403
|
+
"effort": "1h"
|
|
404
|
+
}
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"phase": 2,
|
|
409
|
+
"name": "SeedData Layer",
|
|
410
|
+
"tasks": [
|
|
411
|
+
{
|
|
412
|
+
"taskId": "TASK-003",
|
|
413
|
+
"title": "Create SeedData migration for Order_Status",
|
|
414
|
+
"linkedFRs": [],
|
|
415
|
+
"file": "src/Infrastructure/Data/Migrations/Seed_Order_Status.cs",
|
|
416
|
+
"priority": 1,
|
|
417
|
+
"effort": "1h"
|
|
418
|
+
}
|
|
419
|
+
]
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"phase": 3,
|
|
423
|
+
"name": "Application Layer",
|
|
424
|
+
"tasks": [
|
|
425
|
+
{
|
|
426
|
+
"taskId": "TASK-004",
|
|
427
|
+
"title": "Create OrderService with CRUD operations",
|
|
428
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003", "FR-004"],
|
|
429
|
+
"file": "src/Application/Services/OrderService.cs",
|
|
430
|
+
"priority": 1,
|
|
431
|
+
"effort": "4h"
|
|
432
|
+
}
|
|
433
|
+
]
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"phase": 4,
|
|
437
|
+
"name": "Infrastructure Layer",
|
|
438
|
+
"tasks": [
|
|
439
|
+
{
|
|
440
|
+
"taskId": "TASK-005",
|
|
441
|
+
"title": "Create OrderRepository",
|
|
442
|
+
"linkedFRs": ["FR-001"],
|
|
443
|
+
"file": "src/Infrastructure/Repositories/OrderRepository.cs",
|
|
444
|
+
"priority": 1,
|
|
445
|
+
"effort": "2h"
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
"phase": 5,
|
|
451
|
+
"name": "API Layer",
|
|
452
|
+
"tasks": [
|
|
453
|
+
{
|
|
454
|
+
"taskId": "TASK-006",
|
|
455
|
+
"title": "Create OrdersController with endpoints",
|
|
456
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003"],
|
|
457
|
+
"file": "src/API/Controllers/OrdersController.cs",
|
|
458
|
+
"priority": 1,
|
|
459
|
+
"effort": "3h"
|
|
460
|
+
}
|
|
461
|
+
]
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"phase": 6,
|
|
465
|
+
"name": "Frontend Layer",
|
|
466
|
+
"tasks": [
|
|
467
|
+
{
|
|
468
|
+
"taskId": "TASK-007",
|
|
469
|
+
"title": "Create OrderListPage component",
|
|
470
|
+
"linkedUCs": ["UC-001"],
|
|
471
|
+
"file": "src/pages/Orders/OrderListPage.tsx",
|
|
472
|
+
"priority": 1,
|
|
473
|
+
"effort": "3h"
|
|
474
|
+
}
|
|
475
|
+
]
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
"phase": 7,
|
|
479
|
+
"name": "i18n Layer",
|
|
480
|
+
"tasks": [
|
|
481
|
+
{
|
|
482
|
+
"taskId": "TASK-008",
|
|
483
|
+
"title": "Add i18n keys for Order module",
|
|
484
|
+
"file": "src/locales/en/orders.json",
|
|
485
|
+
"priority": 2,
|
|
486
|
+
"effort": "1h"
|
|
487
|
+
}
|
|
488
|
+
]
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"phase": 8,
|
|
492
|
+
"name": "Tests & Validation",
|
|
493
|
+
"tasks": [
|
|
494
|
+
{
|
|
495
|
+
"taskId": "TASK-009",
|
|
496
|
+
"title": "Unit tests for OrderService",
|
|
497
|
+
"linkedFRs": ["FR-001", "FR-002"],
|
|
498
|
+
"file": "src/Tests/Application/OrderServiceTests.cs",
|
|
499
|
+
"priority": 1,
|
|
500
|
+
"effort": "2h"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"taskId": "TASK-010",
|
|
504
|
+
"title": "Integration tests for OrdersController",
|
|
505
|
+
"linkedUCs": ["UC-001", "UC-002"],
|
|
506
|
+
"file": "src/Tests/Integration/OrderApiTests.cs",
|
|
507
|
+
"priority": 1,
|
|
508
|
+
"effort": "2h"
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
}
|
|
512
|
+
]
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### 5.2 Decomposition Rules
|
|
518
|
+
|
|
519
|
+
For task breakdown:
|
|
520
|
+
|
|
521
|
+
| Layer | Unit | Tasks |
|
|
522
|
+
|-------|------|-------|
|
|
523
|
+
| **Domain** | Entity + Enum | 1-3 per entity |
|
|
524
|
+
| **SeedData** | Table | 1 per table |
|
|
525
|
+
| **Application** | Service | 1 per major feature (CRUD + business logic) |
|
|
526
|
+
| **Infrastructure** | Repository | 1 per entity |
|
|
527
|
+
| **API** | Controller | 1 per resource |
|
|
528
|
+
| **Frontend** | Page/Component | 1 per major UC |
|
|
529
|
+
| **i18n** | Locales | 1 for all keys |
|
|
530
|
+
| **Tests** | Suite | 1 unit + 1 integration per layer |
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## 6. Map Business Rules to Code
|
|
535
|
+
|
|
536
|
+
### 6.1 BR Implementation Mapping
|
|
537
|
+
|
|
538
|
+
> **IMPORTANT :** Générer `handoff.brToCodeMapping[]` (pas `businessRuleMappings`).
|
|
539
|
+
> Dériver depuis `feature.json.analysis.businessRules[]`.
|
|
540
|
+
> Chaque BR doit avoir au minimum 1 point d'implémentation. Format structuré obligatoire.
|
|
541
|
+
|
|
542
|
+
For each business rule in `analysis.businessRules[]`, specify where it will be validated:
|
|
543
|
+
|
|
544
|
+
```json
|
|
545
|
+
{
|
|
546
|
+
"brToCodeMapping": [
|
|
547
|
+
{
|
|
548
|
+
"ruleId": "BR-001",
|
|
549
|
+
"title": "Order number must be unique",
|
|
550
|
+
"implementationPoints": [
|
|
551
|
+
{
|
|
552
|
+
"layer": "Domain",
|
|
553
|
+
"component": "Order.cs",
|
|
554
|
+
"method": "Validate()",
|
|
555
|
+
"implementation": "Throw DomainException if duplicate"
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
"layer": "Infrastructure",
|
|
559
|
+
"component": "OrderRepository.cs",
|
|
560
|
+
"method": "Create()",
|
|
561
|
+
"implementation": "Check uniqueness before INSERT"
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
"layer": "API",
|
|
565
|
+
"component": "OrdersController.cs",
|
|
566
|
+
"method": "CreateOrder()",
|
|
567
|
+
"implementation": "Validate via service, return 409 Conflict if duplicate"
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
"layer": "Frontend",
|
|
571
|
+
"component": "CreateOrderForm.tsx",
|
|
572
|
+
"method": "validateOrderNumber()",
|
|
573
|
+
"implementation": "Real-time validation via API endpoint"
|
|
574
|
+
}
|
|
575
|
+
]
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"ruleId": "BR-002",
|
|
579
|
+
"title": "Only Manager can approve orders",
|
|
580
|
+
"implementationPoints": [
|
|
581
|
+
{
|
|
582
|
+
"layer": "API",
|
|
583
|
+
"component": "OrdersController.cs",
|
|
584
|
+
"method": "[Authorize(Roles = \"Manager\")]",
|
|
585
|
+
"implementation": "Attribute-based authorization"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"layer": "Application",
|
|
589
|
+
"component": "OrderService.cs",
|
|
590
|
+
"method": "ApproveOrder()",
|
|
591
|
+
"implementation": "Check user role, throw UnauthorizedAccessException if not Manager"
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
"layer": "Frontend",
|
|
595
|
+
"component": "OrderDetailPage.tsx",
|
|
596
|
+
"method": "canApprove()",
|
|
597
|
+
"implementation": "Hide/disable Approve button for non-managers"
|
|
598
|
+
}
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
]
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### 6.2 Validation Rules Implementation
|
|
606
|
+
|
|
607
|
+
Map validations to code layers:
|
|
608
|
+
|
|
609
|
+
```json
|
|
610
|
+
{
|
|
611
|
+
"validationMappings": [
|
|
612
|
+
{
|
|
613
|
+
"validation": "OrderNumber: required, unique, max 20 chars",
|
|
614
|
+
"domain": "Order.cs: Field attribute + Validate() method",
|
|
615
|
+
"database": "CREATE UNIQUE INDEX idx_Order_OrderNumber; CHECK length(OrderNumber) <= 20",
|
|
616
|
+
"service": "OrderService.cs: Pre-save validation",
|
|
617
|
+
"api": "OrdersController.cs: ModelState validation",
|
|
618
|
+
"frontend": "CreateOrderForm.tsx: Inline validation + API check"
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## 7. Define API Endpoints
|
|
627
|
+
|
|
628
|
+
> **RÈGLE ABSOLUE :** COPIER EXACTEMENT les routes depuis `specification.apiEndpoints[]`.
|
|
629
|
+
> Ne PAS réinventer de routes ni changer le préfixe.
|
|
630
|
+
> Le `handoff.apiEndpointSummary` doit être un sous-ensemble de `specification.apiEndpoints` enrichi avec `linkedUC`.
|
|
631
|
+
> Si `specification.apiEndpoints` utilise `/api/freebike/fleetmanagement/...`, le handoff doit utiliser **exactement le même préfixe**.
|
|
632
|
+
> Ne JAMAIS substituer par `/api/v1/...` ou un autre format.
|
|
633
|
+
|
|
634
|
+
### 7.1 RESTful Route Mapping
|
|
635
|
+
|
|
636
|
+
**Source :** `specification.apiEndpoints[]` — copier les routes, enrichir avec linkedUC/linkedFR :
|
|
637
|
+
|
|
638
|
+
```json
|
|
639
|
+
{
|
|
640
|
+
"apiEndpoints": [
|
|
641
|
+
{
|
|
642
|
+
"useCase": "UC-001: List Orders",
|
|
643
|
+
"method": "GET",
|
|
644
|
+
"route": "/api/v1/orders",
|
|
645
|
+
"description": "Retrieve paginated list of orders with filtering and sorting",
|
|
646
|
+
"parameters": [
|
|
647
|
+
{
|
|
648
|
+
"name": "page",
|
|
649
|
+
"type": "int",
|
|
650
|
+
"default": 1,
|
|
651
|
+
"description": "Page number (1-indexed)"
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
"name": "pageSize",
|
|
655
|
+
"type": "int",
|
|
656
|
+
"default": 25,
|
|
657
|
+
"values": [10, 25, 50, 100]
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
"name": "status",
|
|
661
|
+
"type": "string",
|
|
662
|
+
"values": ["Draft", "Submitted", "Approved", "Shipped", "Delivered"],
|
|
663
|
+
"optional": true
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
"name": "sortBy",
|
|
667
|
+
"type": "string",
|
|
668
|
+
"values": ["orderNumber", "orderDate", "status"],
|
|
669
|
+
"default": "orderDate"
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
"name": "sortDir",
|
|
673
|
+
"type": "string",
|
|
674
|
+
"values": ["asc", "desc"],
|
|
675
|
+
"default": "desc"
|
|
676
|
+
}
|
|
677
|
+
],
|
|
678
|
+
"response": {
|
|
679
|
+
"statusCode": 200,
|
|
680
|
+
"body": {
|
|
681
|
+
"data": [
|
|
682
|
+
{
|
|
683
|
+
"id": "int",
|
|
684
|
+
"orderNumber": "string",
|
|
685
|
+
"orderDate": "datetime",
|
|
686
|
+
"status": "string"
|
|
687
|
+
}
|
|
688
|
+
],
|
|
689
|
+
"pagination": {
|
|
690
|
+
"page": "int",
|
|
691
|
+
"pageSize": "int",
|
|
692
|
+
"totalPages": "int",
|
|
693
|
+
"totalRecords": "int"
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
},
|
|
697
|
+
"linkedFRs": ["FR-001"],
|
|
698
|
+
"permissions": ["Read"]
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"useCase": "UC-002: Create Order",
|
|
702
|
+
"method": "POST",
|
|
703
|
+
"route": "/api/v1/orders",
|
|
704
|
+
"description": "Create new order with validation",
|
|
705
|
+
"requestBody": {
|
|
706
|
+
"orderNumber": "string (required, unique)",
|
|
707
|
+
"orderDate": "datetime (required, not future)",
|
|
708
|
+
"customerId": "int (required, FK)",
|
|
709
|
+
"status": "string (default: Draft)"
|
|
710
|
+
},
|
|
711
|
+
"response": {
|
|
712
|
+
"statusCode": 201,
|
|
713
|
+
"body": {
|
|
714
|
+
"id": "int",
|
|
715
|
+
"orderNumber": "string",
|
|
716
|
+
"orderDate": "datetime",
|
|
717
|
+
"createdBy": "string",
|
|
718
|
+
"createdDate": "datetime"
|
|
719
|
+
}
|
|
720
|
+
},
|
|
721
|
+
"errors": [
|
|
722
|
+
{
|
|
723
|
+
"statusCode": 400,
|
|
724
|
+
"code": "VALIDATION_FAILED",
|
|
725
|
+
"message": "Validation failed: [field details]"
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
"statusCode": 409,
|
|
729
|
+
"code": "DUPLICATE_ORDER_NUMBER",
|
|
730
|
+
"message": "Order number already exists"
|
|
731
|
+
}
|
|
732
|
+
],
|
|
733
|
+
"linkedFRs": ["FR-002", "FR-003"],
|
|
734
|
+
"permissions": ["Create"]
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
"useCase": "UC-003: View Order Detail",
|
|
738
|
+
"method": "GET",
|
|
739
|
+
"route": "/api/v1/orders/{id}",
|
|
740
|
+
"description": "Retrieve full order details including lines and history",
|
|
741
|
+
"parameters": [
|
|
742
|
+
{
|
|
743
|
+
"name": "id",
|
|
744
|
+
"type": "int",
|
|
745
|
+
"required": true,
|
|
746
|
+
"location": "path"
|
|
747
|
+
}
|
|
748
|
+
],
|
|
749
|
+
"response": {
|
|
750
|
+
"statusCode": 200,
|
|
751
|
+
"body": {
|
|
752
|
+
"id": "int",
|
|
753
|
+
"orderNumber": "string",
|
|
754
|
+
"orderDate": "datetime",
|
|
755
|
+
"customerId": "int",
|
|
756
|
+
"status": "string",
|
|
757
|
+
"lines": [
|
|
758
|
+
{
|
|
759
|
+
"id": "int",
|
|
760
|
+
"productId": "int",
|
|
761
|
+
"quantity": "int",
|
|
762
|
+
"unitPrice": "decimal"
|
|
763
|
+
}
|
|
764
|
+
]
|
|
765
|
+
}
|
|
766
|
+
},
|
|
767
|
+
"linkedFRs": ["FR-001"],
|
|
768
|
+
"permissions": ["Read"]
|
|
769
|
+
}
|
|
770
|
+
]
|
|
771
|
+
}
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
### 7.2 Endpoint Summary Table
|
|
775
|
+
|
|
776
|
+
```json
|
|
777
|
+
{
|
|
778
|
+
"endpointSummary": [
|
|
779
|
+
{
|
|
780
|
+
"operation": "List",
|
|
781
|
+
"method": "GET",
|
|
782
|
+
"route": "/api/v1/orders",
|
|
783
|
+
"linkedUC": "UC-001",
|
|
784
|
+
"permissions": "Read"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
"operation": "Create",
|
|
788
|
+
"method": "POST",
|
|
789
|
+
"route": "/api/v1/orders",
|
|
790
|
+
"linkedUC": "UC-002",
|
|
791
|
+
"permissions": "Create"
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
"operation": "Read",
|
|
795
|
+
"method": "GET",
|
|
796
|
+
"route": "/api/v1/orders/{id}",
|
|
797
|
+
"linkedUC": "UC-003",
|
|
798
|
+
"permissions": "Read"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
"operation": "Update",
|
|
802
|
+
"method": "PUT",
|
|
803
|
+
"route": "/api/v1/orders/{id}",
|
|
804
|
+
"linkedUC": "UC-004",
|
|
805
|
+
"permissions": "Update"
|
|
806
|
+
},
|
|
807
|
+
{
|
|
808
|
+
"operation": "Delete",
|
|
809
|
+
"method": "DELETE",
|
|
810
|
+
"route": "/api/v1/orders/{id}",
|
|
811
|
+
"linkedUC": "UC-005",
|
|
812
|
+
"permissions": "Delete"
|
|
813
|
+
},
|
|
814
|
+
{
|
|
815
|
+
"operation": "Approve",
|
|
816
|
+
"method": "POST",
|
|
817
|
+
"route": "/api/v1/orders/{id}/approve",
|
|
818
|
+
"linkedUC": "UC-006",
|
|
819
|
+
"permissions": "Approve"
|
|
820
|
+
}
|
|
821
|
+
],
|
|
822
|
+
"totalEndpoints": 6
|
|
823
|
+
}
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
---
|
|
827
|
+
|
|
828
|
+
## 8. Test Requirements
|
|
829
|
+
|
|
830
|
+
### 8.1 Unit Test Coverage
|
|
831
|
+
|
|
832
|
+
For each service/component, define test cases:
|
|
833
|
+
|
|
834
|
+
```json
|
|
835
|
+
{
|
|
836
|
+
"unitTests": [
|
|
837
|
+
{
|
|
838
|
+
"testClass": "OrderServiceTests",
|
|
839
|
+
"testCases": [
|
|
840
|
+
{
|
|
841
|
+
"testName": "CreateOrder_WithValidData_ReturnsSuccess",
|
|
842
|
+
"linkedFR": "FR-002",
|
|
843
|
+
"givenState": "Valid order data",
|
|
844
|
+
"when": "CreateOrder() called",
|
|
845
|
+
"then": "Returns new order with ID"
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
"testName": "CreateOrder_WithDuplicateOrderNumber_ThrowsException",
|
|
849
|
+
"linkedBR": "BR-001",
|
|
850
|
+
"givenState": "Order with number ORD-001 exists",
|
|
851
|
+
"when": "CreateOrder(ORD-001) called",
|
|
852
|
+
"then": "Throws DuplicateOrderNumberException"
|
|
853
|
+
},
|
|
854
|
+
{
|
|
855
|
+
"testName": "ApproveOrder_ByNonManager_ThrowsUnauthorized",
|
|
856
|
+
"linkedBR": "BR-002",
|
|
857
|
+
"givenState": "Order exists, user is User role",
|
|
858
|
+
"when": "ApproveOrder() called",
|
|
859
|
+
"then": "Throws UnauthorizedAccessException"
|
|
860
|
+
}
|
|
861
|
+
],
|
|
862
|
+
"coverage": "95%"
|
|
863
|
+
}
|
|
864
|
+
]
|
|
865
|
+
}
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
### 8.2 Integration Test Coverage
|
|
869
|
+
|
|
870
|
+
For APIs, define integration tests:
|
|
871
|
+
|
|
872
|
+
```json
|
|
873
|
+
{
|
|
874
|
+
"integrationTests": [
|
|
875
|
+
{
|
|
876
|
+
"testClass": "OrdersControllerTests",
|
|
877
|
+
"testCases": [
|
|
878
|
+
{
|
|
879
|
+
"testName": "GetOrders_WithoutAuth_Returns401",
|
|
880
|
+
"when": "GET /api/v1/orders without token",
|
|
881
|
+
"then": "Returns 401 Unauthorized"
|
|
882
|
+
},
|
|
883
|
+
{
|
|
884
|
+
"testName": "CreateOrder_WithInvalidData_Returns400",
|
|
885
|
+
"when": "POST /api/v1/orders with missing orderNumber",
|
|
886
|
+
"then": "Returns 400 BadRequest with validation errors"
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
"testName": "CreateOrder_ByAuthorizedUser_Returns201",
|
|
890
|
+
"linkedUC": "UC-002",
|
|
891
|
+
"when": "POST /api/v1/orders with valid data by authorized user",
|
|
892
|
+
"then": "Returns 201 Created with order details"
|
|
893
|
+
}
|
|
894
|
+
]
|
|
895
|
+
}
|
|
896
|
+
]
|
|
897
|
+
}
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
### 8.3 E2E Test Coverage
|
|
901
|
+
|
|
902
|
+
For critical user journeys:
|
|
903
|
+
|
|
904
|
+
```json
|
|
905
|
+
{
|
|
906
|
+
"e2eTests": [
|
|
907
|
+
{
|
|
908
|
+
"journey": "Create and Approve Order",
|
|
909
|
+
"scenario": "User creates order, manager approves it",
|
|
910
|
+
"steps": [
|
|
911
|
+
"1. Navigate to /orders",
|
|
912
|
+
"2. Click 'Create New Order'",
|
|
913
|
+
"3. Fill form and submit",
|
|
914
|
+
"4. Verify order created with Draft status",
|
|
915
|
+
"5. Login as manager",
|
|
916
|
+
"6. Navigate to order detail",
|
|
917
|
+
"7. Click 'Approve'",
|
|
918
|
+
"8. Verify status changed to Approved"
|
|
919
|
+
],
|
|
920
|
+
"linkedUCs": ["UC-002", "UC-006"]
|
|
921
|
+
}
|
|
922
|
+
]
|
|
923
|
+
}
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
## 9. Plan i18n Keys
|
|
929
|
+
|
|
930
|
+
### 9.1 i18n Key Mapping
|
|
931
|
+
|
|
932
|
+
For all user-facing strings, define translation keys:
|
|
933
|
+
|
|
934
|
+
```json
|
|
935
|
+
{
|
|
936
|
+
"i18nKeys": [
|
|
937
|
+
{
|
|
938
|
+
"key": "orders.menu.label",
|
|
939
|
+
"defaultText": "Orders",
|
|
940
|
+
"context": "Menu item"
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
"key": "orders.list.title",
|
|
944
|
+
"defaultText": "Order Management",
|
|
945
|
+
"context": "Page title"
|
|
946
|
+
},
|
|
947
|
+
{
|
|
948
|
+
"key": "orders.list.createButton",
|
|
949
|
+
"defaultText": "Create New Order",
|
|
950
|
+
"context": "Button label"
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
"key": "orders.list.columns.orderNumber",
|
|
954
|
+
"defaultText": "Order Number",
|
|
955
|
+
"context": "Table column header"
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
"key": "orders.list.columns.orderDate",
|
|
959
|
+
"defaultText": "Order Date",
|
|
960
|
+
"context": "Table column header"
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"key": "orders.list.columns.status",
|
|
964
|
+
"defaultText": "Status",
|
|
965
|
+
"context": "Table column header"
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
"key": "orders.form.labels.orderNumber",
|
|
969
|
+
"defaultText": "Order Number",
|
|
970
|
+
"context": "Form field label"
|
|
971
|
+
},
|
|
972
|
+
{
|
|
973
|
+
"key": "orders.form.labels.orderDate",
|
|
974
|
+
"defaultText": "Order Date",
|
|
975
|
+
"context": "Form field label"
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
"key": "orders.form.validations.orderNumberRequired",
|
|
979
|
+
"defaultText": "Order number is required",
|
|
980
|
+
"context": "Validation message"
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
"key": "orders.form.validations.orderNumberFormat",
|
|
984
|
+
"defaultText": "Format must be ORD-XXXXXX",
|
|
985
|
+
"context": "Validation message"
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
"key": "orders.messages.createdSuccess",
|
|
989
|
+
"defaultText": "Order {orderNumber} created successfully",
|
|
990
|
+
"context": "Success message",
|
|
991
|
+
"variables": ["orderNumber"]
|
|
992
|
+
},
|
|
993
|
+
{
|
|
994
|
+
"key": "orders.messages.approvedSuccess",
|
|
995
|
+
"defaultText": "Order approved",
|
|
996
|
+
"context": "Success message"
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
"key": "orders.messages.notFound",
|
|
1000
|
+
"defaultText": "Order not found",
|
|
1001
|
+
"context": "Error message"
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
"key": "orders.enums.status.draft",
|
|
1005
|
+
"defaultText": "Draft",
|
|
1006
|
+
"context": "Enum value"
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
"key": "orders.enums.status.submitted",
|
|
1010
|
+
"defaultText": "Submitted for Review",
|
|
1011
|
+
"context": "Enum value"
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
"key": "orders.enums.status.approved",
|
|
1015
|
+
"defaultText": "Approved",
|
|
1016
|
+
"context": "Enum value"
|
|
1017
|
+
}
|
|
1018
|
+
],
|
|
1019
|
+
"totalKeys": 16,
|
|
1020
|
+
"locales": ["en", "fr", "es", "de"]
|
|
1021
|
+
}
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
### 9.2 i18n File Structure
|
|
1025
|
+
|
|
1026
|
+
```
|
|
1027
|
+
src/locales/
|
|
1028
|
+
├── en/
|
|
1029
|
+
│ ├── common.json
|
|
1030
|
+
│ ├── orders.json ← Order module strings
|
|
1031
|
+
│ └── ...
|
|
1032
|
+
├── fr/
|
|
1033
|
+
│ ├── common.json
|
|
1034
|
+
│ ├── orders.json
|
|
1035
|
+
│ └── ...
|
|
1036
|
+
└── es/
|
|
1037
|
+
├── common.json
|
|
1038
|
+
└── orders.json
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
---
|
|
1042
|
+
|
|
1043
|
+
## 10. Ralph Loop prd.json Generation
|
|
1044
|
+
|
|
1045
|
+
> **RÈGLE FONDAMENTALE : Le prd.json est DÉRIVÉ du feature.json, jamais généré indépendamment.**
|
|
1046
|
+
>
|
|
1047
|
+
> Règles de dérivation strictes :
|
|
1048
|
+
> 1. Les entités dans `prd.json.architecture.entities[]` doivent reprendre **EXACTEMENT** les noms et champs de `feature.json.analysis.entities[]`
|
|
1049
|
+
> 2. Les `linkedFRs` et `linkedBRs` dans les tasks doivent utiliser les IDs **existants** dans le feature.json (pas d'invention)
|
|
1050
|
+
> 3. Les chemins de fichiers doivent correspondre à la structure réelle du projet (lire `.smartstack/config.json` pour le `baseNamespace`)
|
|
1051
|
+
> 4. Les permissions doivent reprendre le format **complet** de `specification.permissionMatrix` (ex: `business.freebike.fleetmanagement.vehicles.read`)
|
|
1052
|
+
> 5. Les routes API doivent être **identiques** à `specification.apiEndpoints[].path`
|
|
1053
|
+
> 6. **AUCUNE entité, FR, BR, UC ou route ne doit apparaître dans le prd.json si elle n'existe pas dans le feature.json**
|
|
1054
|
+
|
|
1055
|
+
### 10.1 PRD Document Structure
|
|
1056
|
+
|
|
1057
|
+
Generate comprehensive product requirements document (**derived from feature.json**) :
|
|
1058
|
+
|
|
1059
|
+
```json
|
|
1060
|
+
{
|
|
1061
|
+
"prd": {
|
|
1062
|
+
"version": "2.0.0",
|
|
1063
|
+
"source": {
|
|
1064
|
+
"type": "ba-handoff",
|
|
1065
|
+
"feature_json": "docs/feature.json"
|
|
1066
|
+
},
|
|
1067
|
+
"metadata": {
|
|
1068
|
+
"title": "[Module Name] - Product Requirements Document",
|
|
1069
|
+
"description": "[Module scope description]",
|
|
1070
|
+
"createdAt": "2025-02-01T11:00:00Z",
|
|
1071
|
+
"createdBy": "business-analyse skill v3.0",
|
|
1072
|
+
"status": "handed-off",
|
|
1073
|
+
"lastModified": "2025-02-01T11:00:00Z"
|
|
1074
|
+
},
|
|
1075
|
+
"project": {
|
|
1076
|
+
"name": "[Project Name]",
|
|
1077
|
+
"module": "[Module Name]",
|
|
1078
|
+
"version": "1.0.0"
|
|
1079
|
+
},
|
|
1080
|
+
"overview": {
|
|
1081
|
+
"summary": "[Executive summary from scope]",
|
|
1082
|
+
"businessGoals": "[From scope.businessObjectives]",
|
|
1083
|
+
"stakeholders": "[From discovery.stakeholders]",
|
|
1084
|
+
"successCriteria": "[From scope.successCriteria]"
|
|
1085
|
+
},
|
|
1086
|
+
"requirements": {
|
|
1087
|
+
"functional": {
|
|
1088
|
+
"useCases": "[From specification.useCases]",
|
|
1089
|
+
"requirements": "[From specification.functionalRequirements]",
|
|
1090
|
+
"scenarios": "[From specification.gherkinScenarios]"
|
|
1091
|
+
},
|
|
1092
|
+
"nonfunctional": {
|
|
1093
|
+
"performance": "[From specification.validations if applicable]",
|
|
1094
|
+
"security": "[From specification.auditingPolicy]",
|
|
1095
|
+
"scalability": "[Derived from business rules]"
|
|
1096
|
+
}
|
|
1097
|
+
},
|
|
1098
|
+
"architecture": {
|
|
1099
|
+
"entities": "[From specification.entities]",
|
|
1100
|
+
"dataModel": "[From specification.entities relationships]",
|
|
1101
|
+
"apiEndpoints": "[From handoff.apiEndpoints]",
|
|
1102
|
+
"permissions": "[From specification.permissionMatrix]"
|
|
1103
|
+
},
|
|
1104
|
+
"implementation": {
|
|
1105
|
+
"taskBreakdown": "[From handoff.implementationSequence]",
|
|
1106
|
+
"fileMapping": "[From handoff.fileMapping]",
|
|
1107
|
+
"dependencies": "[From specification.crossModuleDependencies]",
|
|
1108
|
+
"seedData": "[From specification.navigationHierarchy.seedDataRequired]"
|
|
1109
|
+
},
|
|
1110
|
+
"testing": {
|
|
1111
|
+
"unitTests": "[From handoff.unitTests]",
|
|
1112
|
+
"integrationTests": "[From handoff.integrationTests]",
|
|
1113
|
+
"e2eTests": "[From handoff.e2eTests]",
|
|
1114
|
+
"testCoverage": 80
|
|
1115
|
+
},
|
|
1116
|
+
"i18n": {
|
|
1117
|
+
"keys": "[From handoff.i18nKeys]",
|
|
1118
|
+
"locales": ["en", "fr", "es", "de"]
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
### 10.2 Ralph Loop Task Decomposition
|
|
1125
|
+
|
|
1126
|
+
Critical section: Layer-by-layer task breakdown:
|
|
1127
|
+
|
|
1128
|
+
```json
|
|
1129
|
+
{
|
|
1130
|
+
"tasks": {
|
|
1131
|
+
"decompositionRules": {
|
|
1132
|
+
"granularity": "2-3 hour tasks (developer focus)",
|
|
1133
|
+
"layerOrder": ["Domain", "SeedData", "Application", "Infrastructure", "API", "Frontend", "i18n", "Tests", "Validation"],
|
|
1134
|
+
"dependencies": "Domain → SeedData → Application → Infrastructure → API & Frontend → i18n → Tests",
|
|
1135
|
+
"parallelization": "Infrastructure & Frontend can run in parallel after API definition"
|
|
1136
|
+
},
|
|
1137
|
+
"layers": [
|
|
1138
|
+
{
|
|
1139
|
+
"layerId": "DOMAIN",
|
|
1140
|
+
"name": "Domain Layer",
|
|
1141
|
+
"description": "Entity definitions, enums, validation rules",
|
|
1142
|
+
"tasks": [
|
|
1143
|
+
{
|
|
1144
|
+
"id": "TASK-DOMAIN-001",
|
|
1145
|
+
"title": "Define Order entity with validation",
|
|
1146
|
+
"description": "[From specification.entities[Order]]",
|
|
1147
|
+
"effort": "2h",
|
|
1148
|
+
"dependencies": [],
|
|
1149
|
+
"linkedFRs": ["FR-001"],
|
|
1150
|
+
"linkedBRs": ["BR-001", "BR-003"],
|
|
1151
|
+
"acceptance": "Order.cs created with all fields, required validation, state machine"
|
|
1152
|
+
}
|
|
1153
|
+
]
|
|
1154
|
+
},
|
|
1155
|
+
{
|
|
1156
|
+
"layerId": "SEEDDATA-CORE",
|
|
1157
|
+
"name": "SeedData Core Layer (OBLIGATOIRE)",
|
|
1158
|
+
"description": "5 mandatory SmartStack core files: navigation, permissions, roles. Source: specification.seedDataCore",
|
|
1159
|
+
"tasks": [
|
|
1160
|
+
{
|
|
1161
|
+
"id": "CORE-001",
|
|
1162
|
+
"title": "Create NavigationModuleConfiguration.cs (HasData)",
|
|
1163
|
+
"description": "Derive from specification.seedDataCore.navigationModules. Creates module + section entries.",
|
|
1164
|
+
"effort": "1h",
|
|
1165
|
+
"dependencies": ["TASK-DOMAIN-001"],
|
|
1166
|
+
"category": "seedDataCore",
|
|
1167
|
+
"linkedFRs": [],
|
|
1168
|
+
"acceptance": "NavigationModuleConfiguration.cs created with HasData() seeding all module/section entries"
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
"id": "CORE-002",
|
|
1172
|
+
"title": "Create NavigationTranslationConfiguration.cs (HasData)",
|
|
1173
|
+
"description": "Derive from specification.seedDataCore.navigationTranslations. Creates translations for fr, en, it, de.",
|
|
1174
|
+
"effort": "1h",
|
|
1175
|
+
"dependencies": ["CORE-001"],
|
|
1176
|
+
"category": "seedDataCore",
|
|
1177
|
+
"linkedFRs": [],
|
|
1178
|
+
"acceptance": "NavigationTranslationConfiguration.cs created with HasData() seeding all translations (4 languages)"
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
"id": "CORE-003",
|
|
1182
|
+
"title": "Create PermissionConfiguration.cs (HasData)",
|
|
1183
|
+
"description": "Derive from specification.seedDataCore.permissions. Full path format: business.{app}.{module}.{resource}.{action}",
|
|
1184
|
+
"effort": "1h",
|
|
1185
|
+
"dependencies": ["TASK-DOMAIN-001"],
|
|
1186
|
+
"category": "seedDataCore",
|
|
1187
|
+
"linkedFRs": [],
|
|
1188
|
+
"acceptance": "PermissionConfiguration.cs created with HasData() seeding all permissions with full paths"
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
"id": "CORE-004",
|
|
1192
|
+
"title": "Create RolePermissionConfiguration.cs (HasData)",
|
|
1193
|
+
"description": "Derive from specification.seedDataCore.rolePermissions. Maps roles to permissions using full paths.",
|
|
1194
|
+
"effort": "1h",
|
|
1195
|
+
"dependencies": ["CORE-003"],
|
|
1196
|
+
"category": "seedDataCore",
|
|
1197
|
+
"linkedFRs": [],
|
|
1198
|
+
"acceptance": "RolePermissionConfiguration.cs created with HasData() seeding role-permission assignments"
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
"id": "CORE-005",
|
|
1202
|
+
"title": "Create Permissions.cs constants (Application layer)",
|
|
1203
|
+
"description": "Derive from specification.seedDataCore.permissionConstants. PascalCase const names.",
|
|
1204
|
+
"effort": "0.5h",
|
|
1205
|
+
"dependencies": ["CORE-003"],
|
|
1206
|
+
"category": "seedDataCore",
|
|
1207
|
+
"linkedFRs": [],
|
|
1208
|
+
"acceptance": "Permissions.cs created in Application/Constants with all permission constants"
|
|
1209
|
+
}
|
|
1210
|
+
]
|
|
1211
|
+
},
|
|
1212
|
+
{
|
|
1213
|
+
"layerId": "SEEDDATA",
|
|
1214
|
+
"name": "SeedData Business Layer",
|
|
1215
|
+
"description": "Lookup tables and reference data (Status, Priority, Category, etc.)",
|
|
1216
|
+
"tasks": [
|
|
1217
|
+
{
|
|
1218
|
+
"id": "TASK-SEED-001",
|
|
1219
|
+
"title": "Create Order_Status SeedData migration",
|
|
1220
|
+
"description": "[From specification.navigationHierarchy.seedDataRequired[0]]",
|
|
1221
|
+
"effort": "1h",
|
|
1222
|
+
"dependencies": ["TASK-DOMAIN-001", "CORE-005"],
|
|
1223
|
+
"linkedFRs": [],
|
|
1224
|
+
"acceptance": "Migration creates Order_Status table with 5 status values seeded"
|
|
1225
|
+
}
|
|
1226
|
+
]
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
"layerId": "APPLICATION",
|
|
1230
|
+
"name": "Application Layer",
|
|
1231
|
+
"description": "Business logic, services, use case orchestration",
|
|
1232
|
+
"tasks": [
|
|
1233
|
+
{
|
|
1234
|
+
"id": "TASK-APP-001",
|
|
1235
|
+
"title": "Implement OrderService (CRUD + Approve)",
|
|
1236
|
+
"description": "[From specification.functionalRequirements FR-001 to FR-004]",
|
|
1237
|
+
"effort": "4h",
|
|
1238
|
+
"dependencies": ["TASK-DOMAIN-001", "TASK-SEED-001"],
|
|
1239
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003", "FR-004"],
|
|
1240
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003", "UC-004"],
|
|
1241
|
+
"acceptance": "OrderService has methods: GetAll, GetById, Create, Update, Approve with business rule validation"
|
|
1242
|
+
}
|
|
1243
|
+
]
|
|
1244
|
+
},
|
|
1245
|
+
{
|
|
1246
|
+
"layerId": "INFRASTRUCTURE",
|
|
1247
|
+
"name": "Infrastructure Layer",
|
|
1248
|
+
"description": "Data access, repositories, database operations",
|
|
1249
|
+
"tasks": [
|
|
1250
|
+
{
|
|
1251
|
+
"id": "TASK-INFRA-001",
|
|
1252
|
+
"title": "Create OrderRepository with filtering & sorting",
|
|
1253
|
+
"description": "[From apiEndpoints.parameters: page, pageSize, status, sortBy]",
|
|
1254
|
+
"effort": "2h",
|
|
1255
|
+
"dependencies": ["TASK-DOMAIN-001"],
|
|
1256
|
+
"linkedFRs": ["FR-001"],
|
|
1257
|
+
"acceptance": "OrderRepository has GetAll(filter, sort, pagination) method"
|
|
1258
|
+
}
|
|
1259
|
+
]
|
|
1260
|
+
},
|
|
1261
|
+
{
|
|
1262
|
+
"layerId": "API",
|
|
1263
|
+
"name": "API Layer",
|
|
1264
|
+
"description": "REST endpoints, request/response handling",
|
|
1265
|
+
"tasks": [
|
|
1266
|
+
{
|
|
1267
|
+
"id": "TASK-API-001",
|
|
1268
|
+
"title": "Create OrdersController with 6 endpoints",
|
|
1269
|
+
"description": "[From apiEndpoints: GET /orders, POST /orders, GET /orders/{id}, PUT /orders/{id}, DELETE /orders/{id}, POST /orders/{id}/approve]",
|
|
1270
|
+
"effort": "3h",
|
|
1271
|
+
"dependencies": ["TASK-APP-001"],
|
|
1272
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003", "UC-004", "UC-005", "UC-006"],
|
|
1273
|
+
"acceptance": "Controller has all 6 endpoints with proper HTTP methods, status codes, error handling"
|
|
1274
|
+
}
|
|
1275
|
+
]
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
"layerId": "FRONTEND",
|
|
1279
|
+
"name": "Frontend Layer",
|
|
1280
|
+
"description": "UI pages, components, state management",
|
|
1281
|
+
"tasks": [
|
|
1282
|
+
{
|
|
1283
|
+
"id": "TASK-FE-001",
|
|
1284
|
+
"title": "Create OrderListPage with table and filters",
|
|
1285
|
+
"description": "[From wireframe WF-001]",
|
|
1286
|
+
"effort": "3h",
|
|
1287
|
+
"dependencies": ["TASK-API-001"],
|
|
1288
|
+
"linkedUCs": ["UC-001"],
|
|
1289
|
+
"linkedFRs": ["FR-001"],
|
|
1290
|
+
"acceptance": "Page displays paginated order list, supports filtering by status, sorting, search"
|
|
1291
|
+
},
|
|
1292
|
+
{
|
|
1293
|
+
"id": "TASK-FE-002",
|
|
1294
|
+
"title": "Create CreateOrderForm with validation",
|
|
1295
|
+
"description": "[From wireframe WF-002, specification.validations]",
|
|
1296
|
+
"effort": "3h",
|
|
1297
|
+
"dependencies": ["TASK-API-001"],
|
|
1298
|
+
"linkedUCs": ["UC-002"],
|
|
1299
|
+
"linkedFRs": ["FR-002", "FR-003"],
|
|
1300
|
+
"acceptance": "Form validates all fields inline, shows error messages, prevents submission if invalid"
|
|
1301
|
+
}
|
|
1302
|
+
]
|
|
1303
|
+
},
|
|
1304
|
+
{
|
|
1305
|
+
"layerId": "I18N",
|
|
1306
|
+
"name": "i18n Layer",
|
|
1307
|
+
"description": "Translation keys and localization",
|
|
1308
|
+
"tasks": [
|
|
1309
|
+
{
|
|
1310
|
+
"id": "TASK-I18N-001",
|
|
1311
|
+
"title": "Add Order module translation keys",
|
|
1312
|
+
"description": "[From i18nKeys list]",
|
|
1313
|
+
"effort": "1h",
|
|
1314
|
+
"dependencies": ["TASK-FE-001", "TASK-FE-002"],
|
|
1315
|
+
"linkedFRs": [],
|
|
1316
|
+
"acceptance": "16 i18n keys added to en/orders.json, ready for translation"
|
|
1317
|
+
}
|
|
1318
|
+
]
|
|
1319
|
+
},
|
|
1320
|
+
{
|
|
1321
|
+
"layerId": "TESTS",
|
|
1322
|
+
"name": "Tests & Validation Layer",
|
|
1323
|
+
"description": "Unit, integration, and E2E tests",
|
|
1324
|
+
"tasks": [
|
|
1325
|
+
{
|
|
1326
|
+
"id": "TASK-TEST-001",
|
|
1327
|
+
"title": "Unit tests for OrderService",
|
|
1328
|
+
"description": "[From unitTests: 12 test cases]",
|
|
1329
|
+
"effort": "2h",
|
|
1330
|
+
"dependencies": ["TASK-APP-001"],
|
|
1331
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003", "FR-004"],
|
|
1332
|
+
"acceptance": "12 unit tests covering CRUD, validation, authorization"
|
|
1333
|
+
},
|
|
1334
|
+
{
|
|
1335
|
+
"id": "TASK-TEST-002",
|
|
1336
|
+
"title": "Integration tests for OrdersController",
|
|
1337
|
+
"description": "[From integrationTests: 8 test cases]",
|
|
1338
|
+
"effort": "2h",
|
|
1339
|
+
"dependencies": ["TASK-API-001"],
|
|
1340
|
+
"linkedUCs": ["UC-001", "UC-002", "UC-003"],
|
|
1341
|
+
"acceptance": "8 integration tests covering all endpoints, auth, error handling"
|
|
1342
|
+
},
|
|
1343
|
+
{
|
|
1344
|
+
"id": "TASK-TEST-003",
|
|
1345
|
+
"title": "E2E test for Order creation and approval flow",
|
|
1346
|
+
"description": "[From e2eTests: Create and Approve Order journey]",
|
|
1347
|
+
"effort": "2h",
|
|
1348
|
+
"dependencies": ["TASK-FE-002"],
|
|
1349
|
+
"linkedUCs": ["UC-002", "UC-006"],
|
|
1350
|
+
"acceptance": "E2E test covers complete user journey from create to approve"
|
|
1351
|
+
}
|
|
1352
|
+
]
|
|
1353
|
+
},
|
|
1354
|
+
{
|
|
1355
|
+
"layerId": "VALIDATION",
|
|
1356
|
+
"name": "Validation & QA Layer",
|
|
1357
|
+
"description": "Final validation against requirements",
|
|
1358
|
+
"tasks": [
|
|
1359
|
+
{
|
|
1360
|
+
"id": "TASK-VALIDATION-001",
|
|
1361
|
+
"title": "Verify all FRs implemented and tested",
|
|
1362
|
+
"description": "[Cross-reference FR vs implementation]",
|
|
1363
|
+
"effort": "1h",
|
|
1364
|
+
"dependencies": ["TASK-TEST-003"],
|
|
1365
|
+
"linkedFRs": ["FR-001", "FR-002", "FR-003", "FR-004"],
|
|
1366
|
+
"acceptance": "All FRs have corresponding code and tests"
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
"id": "TASK-VALIDATION-002",
|
|
1370
|
+
"title": "Verify all BRs validated in code",
|
|
1371
|
+
"description": "[Cross-reference BR vs validation points]",
|
|
1372
|
+
"effort": "1h",
|
|
1373
|
+
"dependencies": ["TASK-TEST-003"],
|
|
1374
|
+
"linkedBRs": ["BR-001", "BR-002", "BR-003"],
|
|
1375
|
+
"acceptance": "All BRs have corresponding validation in at least one layer"
|
|
1376
|
+
}
|
|
1377
|
+
]
|
|
1378
|
+
}
|
|
1379
|
+
],
|
|
1380
|
+
"totalTasks": 15,
|
|
1381
|
+
"totalEffort": "28h",
|
|
1382
|
+
"estimatedDuration": "1 week (4 developers in parallel)"
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
```
|
|
1386
|
+
|
|
1387
|
+
### 10.3 prd.json v2.0.0 Schema Validation
|
|
1388
|
+
|
|
1389
|
+
Ensure prd.json follows SmartStack schema:
|
|
1390
|
+
|
|
1391
|
+
```json
|
|
1392
|
+
{
|
|
1393
|
+
"validation": {
|
|
1394
|
+
"schema": "prd.json v2.0.0",
|
|
1395
|
+
"checks": [
|
|
1396
|
+
{
|
|
1397
|
+
"field": "version",
|
|
1398
|
+
"required": true,
|
|
1399
|
+
"value": "2.0.0",
|
|
1400
|
+
"status": "PASS" ✓
|
|
1401
|
+
},
|
|
1402
|
+
{
|
|
1403
|
+
"field": "source",
|
|
1404
|
+
"required": true,
|
|
1405
|
+
"value": {
|
|
1406
|
+
"type": "ba-handoff",
|
|
1407
|
+
"feature_json": "docs/feature.json"
|
|
1408
|
+
},
|
|
1409
|
+
"status": "PASS" ✓
|
|
1410
|
+
},
|
|
1411
|
+
{
|
|
1412
|
+
"field": "tasks",
|
|
1413
|
+
"required": true,
|
|
1414
|
+
"taskCount": 15,
|
|
1415
|
+
"layerCount": 9,
|
|
1416
|
+
"status": "PASS" ✓
|
|
1417
|
+
}
|
|
1418
|
+
]
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
```
|
|
1422
|
+
|
|
1423
|
+
---
|
|
1424
|
+
|
|
1425
|
+
## 11. Initialize Progress Tracker
|
|
1426
|
+
|
|
1427
|
+
### 11.1 Create .ralph/progress.txt
|
|
1428
|
+
|
|
1429
|
+
Initialize progress tracking file:
|
|
1430
|
+
|
|
1431
|
+
```
|
|
1432
|
+
═════════════════════════════════════════════════════════════════
|
|
1433
|
+
SMARTSTACK RALPH LOOP - PROGRESS TRACKER
|
|
1434
|
+
Project: [Project Name] | Module: [Module Name]
|
|
1435
|
+
Created: 2025-02-01T11:00:00Z
|
|
1436
|
+
Status: HANDED-OFF
|
|
1437
|
+
═════════════════════════════════════════════════════════════════
|
|
1438
|
+
|
|
1439
|
+
LAYER BREAKDOWN (28h total effort):
|
|
1440
|
+
|
|
1441
|
+
[DOMAIN] Domain Layer (2h)
|
|
1442
|
+
□ TASK-DOMAIN-001: Define Order entity (2h)
|
|
1443
|
+
Status: pending
|
|
1444
|
+
Assigned: [TBD]
|
|
1445
|
+
Started: [TBD]
|
|
1446
|
+
Completed: [TBD]
|
|
1447
|
+
Progress: 0%
|
|
1448
|
+
|
|
1449
|
+
[SEEDDATA-CORE] SeedData Core Layer (4.5h) — OBLIGATOIRE
|
|
1450
|
+
□ CORE-001: Create NavigationModuleConfiguration.cs (1h)
|
|
1451
|
+
Status: pending
|
|
1452
|
+
Source: specification.seedDataCore.navigationModules
|
|
1453
|
+
Progress: 0%
|
|
1454
|
+
□ CORE-002: Create NavigationTranslationConfiguration.cs (1h)
|
|
1455
|
+
Status: pending
|
|
1456
|
+
Source: specification.seedDataCore.navigationTranslations
|
|
1457
|
+
Progress: 0%
|
|
1458
|
+
□ CORE-003: Create PermissionConfiguration.cs (1h)
|
|
1459
|
+
Status: pending
|
|
1460
|
+
Source: specification.seedDataCore.permissions
|
|
1461
|
+
Progress: 0%
|
|
1462
|
+
□ CORE-004: Create RolePermissionConfiguration.cs (1h)
|
|
1463
|
+
Status: pending
|
|
1464
|
+
Source: specification.seedDataCore.rolePermissions
|
|
1465
|
+
Progress: 0%
|
|
1466
|
+
□ CORE-005: Create Permissions.cs constants (0.5h)
|
|
1467
|
+
Status: pending
|
|
1468
|
+
Source: specification.seedDataCore.permissionConstants
|
|
1469
|
+
Progress: 0%
|
|
1470
|
+
|
|
1471
|
+
[SEEDDATA] SeedData Business Layer (1h) — depends on CORE-005
|
|
1472
|
+
□ TASK-SEED-001: Create Order_Status migration (1h)
|
|
1473
|
+
Status: pending
|
|
1474
|
+
Assigned: [TBD]
|
|
1475
|
+
Started: [TBD]
|
|
1476
|
+
Completed: [TBD]
|
|
1477
|
+
Progress: 0%
|
|
1478
|
+
|
|
1479
|
+
[APPLICATION] Application Layer (4h)
|
|
1480
|
+
□ TASK-APP-001: Implement OrderService (4h)
|
|
1481
|
+
Status: pending
|
|
1482
|
+
Assigned: [TBD]
|
|
1483
|
+
Started: [TBD]
|
|
1484
|
+
Completed: [TBD]
|
|
1485
|
+
Progress: 0%
|
|
1486
|
+
Subtasks:
|
|
1487
|
+
- GetAll() method
|
|
1488
|
+
- GetById() method
|
|
1489
|
+
- Create() method with validation
|
|
1490
|
+
- Update() method
|
|
1491
|
+
- Approve() method with authorization
|
|
1492
|
+
|
|
1493
|
+
[INFRASTRUCTURE] Infrastructure Layer (2h)
|
|
1494
|
+
□ TASK-INFRA-001: Create OrderRepository (2h)
|
|
1495
|
+
Status: pending
|
|
1496
|
+
Assigned: [TBD]
|
|
1497
|
+
Started: [TBD]
|
|
1498
|
+
Completed: [TBD]
|
|
1499
|
+
Progress: 0%
|
|
1500
|
+
|
|
1501
|
+
[API] API Layer (3h)
|
|
1502
|
+
□ TASK-API-001: Create OrdersController (3h)
|
|
1503
|
+
Status: pending
|
|
1504
|
+
Assigned: [TBD]
|
|
1505
|
+
Started: [TBD]
|
|
1506
|
+
Completed: [TBD]
|
|
1507
|
+
Progress: 0%
|
|
1508
|
+
Endpoints:
|
|
1509
|
+
- GET /api/v1/orders (List)
|
|
1510
|
+
- POST /api/v1/orders (Create)
|
|
1511
|
+
- GET /api/v1/orders/{id} (Detail)
|
|
1512
|
+
- PUT /api/v1/orders/{id} (Update)
|
|
1513
|
+
- DELETE /api/v1/orders/{id} (Delete)
|
|
1514
|
+
- POST /api/v1/orders/{id}/approve (Approve)
|
|
1515
|
+
|
|
1516
|
+
[FRONTEND] Frontend Layer (6h)
|
|
1517
|
+
□ TASK-FE-001: Create OrderListPage (3h)
|
|
1518
|
+
Status: pending
|
|
1519
|
+
Assigned: [TBD]
|
|
1520
|
+
Progress: 0%
|
|
1521
|
+
□ TASK-FE-002: Create CreateOrderForm (3h)
|
|
1522
|
+
Status: pending
|
|
1523
|
+
Assigned: [TBD]
|
|
1524
|
+
Progress: 0%
|
|
1525
|
+
|
|
1526
|
+
[I18N] i18n Layer (1h)
|
|
1527
|
+
□ TASK-I18N-001: Add translation keys (1h)
|
|
1528
|
+
Status: pending
|
|
1529
|
+
Progress: 0%
|
|
1530
|
+
Keys: 16 total
|
|
1531
|
+
□ Menu labels (1)
|
|
1532
|
+
□ Page titles (1)
|
|
1533
|
+
□ Column headers (3)
|
|
1534
|
+
□ Form labels (2)
|
|
1535
|
+
□ Validation messages (4)
|
|
1536
|
+
□ Success messages (2)
|
|
1537
|
+
□ Error messages (2)
|
|
1538
|
+
□ Enum values (3)
|
|
1539
|
+
|
|
1540
|
+
[TESTS] Tests & Validation Layer (6h)
|
|
1541
|
+
□ TASK-TEST-001: Unit tests for OrderService (2h)
|
|
1542
|
+
Status: pending
|
|
1543
|
+
Progress: 0%
|
|
1544
|
+
Cases: 12 unit tests
|
|
1545
|
+
□ TASK-TEST-002: Integration tests for OrdersController (2h)
|
|
1546
|
+
Status: pending
|
|
1547
|
+
Progress: 0%
|
|
1548
|
+
Cases: 8 integration tests
|
|
1549
|
+
□ TASK-TEST-003: E2E test for Order flow (2h)
|
|
1550
|
+
Status: pending
|
|
1551
|
+
Progress: 0%
|
|
1552
|
+
Cases: 1 E2E scenario
|
|
1553
|
+
|
|
1554
|
+
[VALIDATION] Validation & QA Layer (2h)
|
|
1555
|
+
□ TASK-VALIDATION-001: Verify FRs implemented (1h)
|
|
1556
|
+
Status: pending
|
|
1557
|
+
Progress: 0%
|
|
1558
|
+
□ TASK-VALIDATION-002: Verify BRs validated (1h)
|
|
1559
|
+
Status: pending
|
|
1560
|
+
Progress: 0%
|
|
1561
|
+
|
|
1562
|
+
═════════════════════════════════════════════════════════════════
|
|
1563
|
+
SUMMARY
|
|
1564
|
+
═════════════════════════════════════════════════════════════════
|
|
1565
|
+
Total Tasks: 20 (5 CORE + 15 business)
|
|
1566
|
+
Total Effort: 32.5 hours
|
|
1567
|
+
Completed: 0 (0%)
|
|
1568
|
+
In Progress: 0 (0%)
|
|
1569
|
+
Pending: 20 (100%)
|
|
1570
|
+
Blocked: 0 (0%)
|
|
1571
|
+
|
|
1572
|
+
Dependencies:
|
|
1573
|
+
Domain → SeedData-CORE → SeedData → Application → Infrastructure
|
|
1574
|
+
↘ ↙
|
|
1575
|
+
↓ ↓
|
|
1576
|
+
API ←─────────── Frontend
|
|
1577
|
+
↓ ↓
|
|
1578
|
+
i18n & Tests ← ─────┘
|
|
1579
|
+
↓
|
|
1580
|
+
Validation
|
|
1581
|
+
|
|
1582
|
+
Critical Path: Domain → CORE → SeedData → App → Infra → API → Tests
|
|
1583
|
+
Parallel Path: Frontend can start after API definition
|
|
1584
|
+
|
|
1585
|
+
═════════════════════════════════════════════════════════════════
|
|
1586
|
+
NOTES
|
|
1587
|
+
═════════════════════════════════════════════════════════════════
|
|
1588
|
+
- Start Domain tasks immediately (critical path dependency)
|
|
1589
|
+
- Frontend & Infrastructure can run in parallel after API is stubbed
|
|
1590
|
+
- Tests should not begin until implementation 80% complete
|
|
1591
|
+
- Update this file daily during development
|
|
1592
|
+
- Colors: 🟢 Done | 🟡 In Progress | 🔴 Pending | ⚫ Blocked
|
|
1593
|
+
|
|
1594
|
+
═════════════════════════════════════════════════════════════════
|
|
1595
|
+
```
|
|
1596
|
+
|
|
1597
|
+
### 11.2 Progress Tracking Integration
|
|
1598
|
+
|
|
1599
|
+
Link progress.txt to feature.json:
|
|
1600
|
+
|
|
1601
|
+
```json
|
|
1602
|
+
{
|
|
1603
|
+
"handoff": {
|
|
1604
|
+
"progressFile": ".ralph/progress.txt",
|
|
1605
|
+
"progressTracking": {
|
|
1606
|
+
"enabled": true,
|
|
1607
|
+
"updateFrequency": "daily",
|
|
1608
|
+
"statusOptions": ["pending", "in_progress", "completed", "blocked"],
|
|
1609
|
+
"links": {
|
|
1610
|
+
"feature_json": "docs/feature.json",
|
|
1611
|
+
"prd_json": ".ralph/prd.json",
|
|
1612
|
+
"progress_txt": ".ralph/progress.txt"
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
---
|
|
1620
|
+
|
|
1621
|
+
## 12. User Choice: Next Agent
|
|
1622
|
+
|
|
1623
|
+
### 12.1 Present Options
|
|
1624
|
+
|
|
1625
|
+
After generating prd.json, offer user choices:
|
|
1626
|
+
|
|
1627
|
+
```
|
|
1628
|
+
Handoff package ready!
|
|
1629
|
+
|
|
1630
|
+
Generated:
|
|
1631
|
+
✓ feature.json.handoff section
|
|
1632
|
+
✓ .ralph/prd.json (product requirements)
|
|
1633
|
+
✓ .ralph/progress.txt (task tracker)
|
|
1634
|
+
|
|
1635
|
+
Next step: Choose your development approach
|
|
1636
|
+
|
|
1637
|
+
Options:
|
|
1638
|
+
1. [Feature Full] Fast scaffolding + test generation
|
|
1639
|
+
Duration: 15-30 min | Coverage: 70-80%
|
|
1640
|
+
✓ Fast iteration | ✓ Tests included
|
|
1641
|
+
✗ May need manual polish
|
|
1642
|
+
|
|
1643
|
+
2. [Ralph Loop] Task-driven development
|
|
1644
|
+
Duration: 1-2 hours | Coverage: 95-100%
|
|
1645
|
+
✓ Comprehensive | ✓ Detailed implementation
|
|
1646
|
+
✗ Slower, more verbose
|
|
1647
|
+
|
|
1648
|
+
3. [Feature Full] Parallel multi-layer generation
|
|
1649
|
+
Duration: 30-45 min | Coverage: 80-90%
|
|
1650
|
+
✓ Balanced | ✓ All layers in parallel
|
|
1651
|
+
✗ Complex orchestration
|
|
1652
|
+
|
|
1653
|
+
4. [End BA] Finish business analysis, manual development
|
|
1654
|
+
Duration: 0 min | Coverage: Depends on developers
|
|
1655
|
+
✓ Gives team freedom | ✓ Lighter handoff
|
|
1656
|
+
✗ No code generation
|
|
1657
|
+
|
|
1658
|
+
Recommended: Option 1 (Feature Full) for fast MVP, then Option 2 (Ralph Loop) for polish.
|
|
1659
|
+
|
|
1660
|
+
Select option: [ ]
|
|
1661
|
+
```
|
|
1662
|
+
|
|
1663
|
+
### 12.2 Remove Old Documentation Option
|
|
1664
|
+
|
|
1665
|
+
Remove step-06 from final choice:
|
|
1666
|
+
- ~~[Generate HTML documentation]~~ - NOT AVAILABLE in v3.0
|
|
1667
|
+
- Keep: Ralph Loop, Feature Full, End BA
|
|
1668
|
+
|
|
1669
|
+
---
|
|
1670
|
+
|
|
1671
|
+
## 13. Execution Workflow
|
|
1672
|
+
|
|
1673
|
+
### 13.1 Handoff Sequence
|
|
1674
|
+
|
|
1675
|
+
1. **Verify validation passed** (status: "approved")
|
|
1676
|
+
2. **Explore existing patterns** (check for code generators)
|
|
1677
|
+
3. **Calculate complexity** (simple/medium/complex)
|
|
1678
|
+
4. **Map to files** (document implementation locations — structured `filesToCreate`)
|
|
1679
|
+
5. **Generate implementation instructions** (task breakdown including CORE-001→CORE-005)
|
|
1680
|
+
6. **Map BRs to code** (`brToCodeMapping` — validation points)
|
|
1681
|
+
7. **Copy API endpoints** (from `specification.apiEndpoints` — EXACT same routes)
|
|
1682
|
+
8. **Plan tests** (coverage strategy)
|
|
1683
|
+
9. **Plan i18n** (translation keys)
|
|
1684
|
+
10. **Generate prd.json** (DERIVED from feature.json — strict alignment)
|
|
1685
|
+
11. **Initialize progress.txt** (task tracker with [SEEDDATA-CORE] section)
|
|
1686
|
+
12. **Update changelog** (step-04 entry)
|
|
1687
|
+
13. **Present user choices** (next agent selection)
|
|
1688
|
+
|
|
1689
|
+
### 13.2 Calculate Complexity
|
|
1690
|
+
|
|
1691
|
+
**OBLIGATOIRE :** Calculer et écrire `handoff.complexity` dans feature.json :
|
|
1692
|
+
|
|
1693
|
+
| Critère | Simple | Medium | Complex |
|
|
1694
|
+
|---------|--------|--------|---------|
|
|
1695
|
+
| Entities | ≤3 | ≤6 | >6 |
|
|
1696
|
+
| Use Cases | ≤5 | ≤12 | >12 |
|
|
1697
|
+
| Business Rules | ≤10 | ≤20 | >20 |
|
|
1698
|
+
|
|
1699
|
+
```json
|
|
1700
|
+
{
|
|
1701
|
+
"handoff": {
|
|
1702
|
+
"complexity": "medium",
|
|
1703
|
+
"complexityDetails": {
|
|
1704
|
+
"entities": 4,
|
|
1705
|
+
"useCases": 6,
|
|
1706
|
+
"businessRules": 5,
|
|
1707
|
+
"calculated": "medium (≤6 entities, ≤12 UCs, ≤20 BRs)"
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
```
|
|
1712
|
+
|
|
1713
|
+
La complexité la plus élevée parmi les 3 critères détermine le niveau global.
|
|
1714
|
+
|
|
1715
|
+
### 13.3 Update Changelog
|
|
1716
|
+
|
|
1717
|
+
**OBLIGATOIRE :** Ajouter une entrée changelog pour step-04 via `ba-writer` :
|
|
1718
|
+
|
|
1719
|
+
```json
|
|
1720
|
+
{
|
|
1721
|
+
"changelog": [
|
|
1722
|
+
{
|
|
1723
|
+
"step": "step-04-handoff",
|
|
1724
|
+
"timestamp": "2025-02-01T11:00:00Z",
|
|
1725
|
+
"changes": [
|
|
1726
|
+
"Complexity: medium",
|
|
1727
|
+
"Files to create: X (Y core + Z business)",
|
|
1728
|
+
"BR mappings: X rules mapped",
|
|
1729
|
+
"API endpoints: X routes (from specification)",
|
|
1730
|
+
"prd.json: X tasks across Y layers",
|
|
1731
|
+
"progress.txt initialized",
|
|
1732
|
+
"User choice: [Feature Full / Ralph Loop / End BA]"
|
|
1733
|
+
]
|
|
1734
|
+
}
|
|
1735
|
+
]
|
|
1736
|
+
}
|
|
1737
|
+
```
|
|
1738
|
+
|
|
1739
|
+
### 13.4 Output Summary
|
|
1740
|
+
|
|
1741
|
+
Display final summary:
|
|
1742
|
+
|
|
1743
|
+
```
|
|
1744
|
+
═══════════════════════════════════════════════════════════════
|
|
1745
|
+
✓ HANDOFF COMPLETE
|
|
1746
|
+
═══════════════════════════════════════════════════════════════
|
|
1747
|
+
|
|
1748
|
+
Module: Orders
|
|
1749
|
+
Status: handed-off
|
|
1750
|
+
Complexity: medium
|
|
1751
|
+
Specification: 11 sections complete
|
|
1752
|
+
Validation: approved
|
|
1753
|
+
Implementation: Ready to code
|
|
1754
|
+
|
|
1755
|
+
Generated Files:
|
|
1756
|
+
✓ docs/feature.json (specification + validation + handoff)
|
|
1757
|
+
✓ .ralph/prd.json (v2.0.0 with 20 tasks)
|
|
1758
|
+
✓ .ralph/progress.txt (progress tracker)
|
|
1759
|
+
|
|
1760
|
+
Statistics:
|
|
1761
|
+
- Use cases: 6 (UC-001 → UC-006)
|
|
1762
|
+
- Requirements: 12 FRs
|
|
1763
|
+
- Business rules: 5 BRs (mapped to code)
|
|
1764
|
+
- API endpoints: 6 REST routes (from specification)
|
|
1765
|
+
- Components: 8 frontend components
|
|
1766
|
+
- Tests: 20 test cases (unit + integration + E2E)
|
|
1767
|
+
- i18n keys: 16 translation keys
|
|
1768
|
+
- CORE tasks: 5 (navigation, permissions, roles)
|
|
1769
|
+
- Implementation: 20 tasks across 10 layers
|
|
1770
|
+
- Complexity: medium
|
|
1771
|
+
|
|
1772
|
+
Dependencies:
|
|
1773
|
+
✓ Domain → SeedData-CORE → SeedData → Application → Infrastructure → API → Frontend
|
|
1774
|
+
✓ Tests & i18n run in parallel
|
|
1775
|
+
✓ Validation confirms all FRs/BRs covered
|
|
1776
|
+
|
|
1777
|
+
Next Step: Choose development approach (Feature Full / Ralph Loop / Manual)
|
|
1778
|
+
|
|
1779
|
+
═══════════════════════════════════════════════════════════════
|
|
1780
|
+
```
|
|
1781
|
+
|
|
1782
|
+
---
|
|
1783
|
+
|
|
1784
|
+
## OUTPUT
|
|
1785
|
+
|
|
1786
|
+
> **INTERDIT : Ne générer AUCUN fichier JSON supplémentaire** (specification.json, analysis.json, handoff.json, etc.).
|
|
1787
|
+
> Le **feature.json** est le SEUL livrable JSON. Le prd.json et progress.txt sont les seuls fichiers supplémentaires autorisés.
|
|
1788
|
+
> Un fichier specification.json séparé crée une **double source de vérité** et sera rejeté par la validation.
|
|
1789
|
+
|
|
1790
|
+
This step enriches **feature.json** with:
|
|
1791
|
+
- **handoff** section containing: `complexity`, `filesToCreate` (structured object with 7 categories), `brToCodeMapping`, `apiEndpointSummary`, test plans, and i18n keys
|
|
1792
|
+
- **Status:** "handed-off"
|
|
1793
|
+
|
|
1794
|
+
Also generates:
|
|
1795
|
+
- **.ralph/prd.json** - Comprehensive product requirements (v2.0.0 schema, DERIVED from feature.json)
|
|
1796
|
+
- **.ralph/progress.txt** - Task progress tracker with 20 implementation tasks (5 CORE + 15 business)
|
|
1797
|
+
|
|
1798
|
+
**Standard mode:** Full handoff with all implementation details.
|
|
1799
|
+
**Micro mode:** Simplified handoff with minimal tasks, auto-suggest Feature Full.
|
|
1800
|
+
**Delta mode:** Handoff for affected features only, reuse existing patterns.
|
|
1801
|
+
|
|
1802
|
+
Next agent selection: Feature Full, Ralph Loop, or End BA.
|