@atlashub/smartstack-cli 3.2.0 → 3.3.1
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/dist/index.js +605 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-reader.md +1 -1
- package/templates/agents/ba-writer.md +8 -1
- package/templates/skills/business-analyse/SKILL.md +21 -23
- package/templates/skills/business-analyse/_architecture.md +123 -0
- package/templates/skills/business-analyse/_elicitation.md +206 -0
- package/templates/skills/business-analyse/_module-loop.md +56 -0
- package/templates/skills/business-analyse/_shared.md +75 -531
- package/templates/skills/business-analyse/_suggestions.md +34 -0
- package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
- package/templates/skills/business-analyse/questionnaire.md +2 -2
- package/templates/skills/business-analyse/react/components.md +1 -1
- package/templates/skills/business-analyse/react/schema.md +1 -1
- package/templates/skills/business-analyse/references/html-data-mapping.md +294 -0
- package/templates/skills/business-analyse/schemas/feature-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/handoff-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +1 -1
- package/templates/skills/business-analyse/steps/step-00-init.md +13 -10
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +2 -0
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +5 -3
- package/templates/skills/business-analyse/steps/{step-03-specify.md → step-03a-specify.md} +16 -606
- package/templates/skills/business-analyse/steps/step-03b-compile.md +670 -0
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +7 -5
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +727 -0
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +479 -0
- package/templates/skills/business-analyse/steps/step-06-extract.md +4 -2
- package/templates/skills/business-analyse/templates/tpl-frd.md +1 -1
- package/templates/skills/business-analyse/templates/tpl-launch-displays.md +161 -0
- package/templates/skills/business-analyse/templates/tpl-progress.md +171 -0
- package/templates/skills/business-analyse/steps/step-05-handoff.md +0 -1682
|
@@ -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`
|