@atlashub/smartstack-cli 2.9.0 → 3.0.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 +81 -17
- package/dist/mcp-entry.mjs +1302 -223
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/efcore/db-deploy.md +1 -1
- package/templates/agents/efcore/migration.md +26 -10
- package/templates/agents/efcore/rebase-snapshot.md +24 -7
- package/templates/agents/efcore/squash.md +73 -57
- package/templates/agents/gitflow/commit.md +138 -18
- package/templates/agents/gitflow/exec.md +1 -1
- package/templates/agents/gitflow/finish.md +79 -62
- package/templates/agents/gitflow/init-clone.md +186 -0
- package/templates/agents/gitflow/init-detect.md +137 -0
- package/templates/agents/gitflow/init-validate.md +210 -0
- package/templates/agents/gitflow/init.md +231 -74
- package/templates/agents/gitflow/merge.md +65 -33
- package/templates/agents/gitflow/pr.md +93 -49
- package/templates/agents/gitflow/start.md +76 -33
- package/templates/agents/gitflow/status.md +41 -71
- package/templates/hooks/appsettings-guard.sh +76 -0
- package/templates/hooks/ef-migration-check.md +1 -1
- package/templates/hooks/hooks.json +9 -0
- package/templates/project/test-frontend/msw/handlers.ts +58 -0
- package/templates/project/test-frontend/msw/server.ts +25 -0
- package/templates/project/test-frontend/setup.ts +16 -0
- package/templates/project/test-frontend/test-utils.tsx +59 -0
- package/templates/project/test-frontend/vitest.config.ts +31 -0
- package/templates/skills/_resources/config-safety.md +61 -0
- package/templates/skills/_resources/formatting-guide.md +2 -2
- package/templates/skills/application/SKILL.md +12 -3
- package/templates/skills/application/steps/step-04-backend.md +21 -0
- package/templates/skills/application/steps/step-07-tests.md +259 -120
- package/templates/skills/business-analyse/SKILL.md +57 -28
- package/templates/skills/business-analyse/_shared.md +70 -39
- package/templates/skills/business-analyse/html/ba-interactive.html +2622 -0
- package/templates/skills/business-analyse/questionnaire/00-application.md +123 -131
- package/templates/skills/business-analyse/questionnaire/01-context.md +173 -24
- package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +170 -50
- package/templates/skills/business-analyse/questionnaire/03-scope.md +154 -48
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +1 -1
- package/templates/skills/business-analyse/questionnaire/14-risk-assumptions.md +135 -0
- package/templates/skills/business-analyse/questionnaire/15-success-metrics.md +136 -0
- package/templates/skills/business-analyse/questionnaire.md +55 -46
- package/templates/skills/business-analyse/steps/step-00-init.md +24 -2
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +31 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +1 -0
- package/templates/skills/business-analyse/steps/step-05-handoff.md +103 -1
- package/templates/skills/business-analyse/steps/step-06-extract.md +518 -0
- package/templates/skills/check-version/SKILL.md +1 -1
- package/templates/skills/efcore/steps/db/step-deploy.md +22 -3
- package/templates/skills/efcore/steps/db/step-reset.md +27 -4
- package/templates/skills/efcore/steps/db/step-seed.md +46 -2
- package/templates/skills/efcore/steps/db/step-status.md +14 -0
- package/templates/skills/efcore/steps/migration/step-01-check.md +31 -5
- package/templates/skills/efcore/steps/migration/step-02-create.md +20 -4
- package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +60 -0
- package/templates/skills/efcore/steps/shared/step-00-init.md +47 -8
- package/templates/skills/efcore/steps/squash/step-03-create.md +27 -5
- package/templates/skills/gitflow/SKILL.md +91 -29
- package/templates/skills/gitflow/_shared.md +144 -2
- package/templates/skills/gitflow/phases/status.md +11 -1
- package/templates/skills/gitflow/steps/step-commit.md +1 -1
- package/templates/skills/gitflow/steps/step-init.md +202 -39
- package/templates/skills/gitflow/templates/config.json +10 -1
- package/templates/skills/ralph-loop/steps/step-03-commit.md +2 -2
- package/templates/skills/validate-feature/SKILL.md +83 -0
- package/templates/skills/validate-feature/steps/step-01-compile.md +38 -0
- package/templates/skills/validate-feature/steps/step-02-unit-tests.md +45 -0
- package/templates/skills/validate-feature/steps/step-03-integration-tests.md +53 -0
- package/templates/skills/validate-feature/steps/step-04-api-smoke.md +157 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-06-extract
|
|
3
|
+
description: Extract interactive HTML document data into feature.json - zero information loss
|
|
4
|
+
model: sonnet
|
|
5
|
+
next_step: null
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Step 6: Extraction depuis le document interactif
|
|
9
|
+
|
|
10
|
+
## REGLES D'EXECUTION
|
|
11
|
+
|
|
12
|
+
- TOUJOURS lire le fichier JSON exporte avant toute operation
|
|
13
|
+
- TOUJOURS mapper CHAQUE element sans exception (zero perte d'information)
|
|
14
|
+
- TOUJOURS utiliser ba-writer pour ecrire dans feature.json
|
|
15
|
+
- TOUJOURS afficher un resume comparatif avant/apres extraction
|
|
16
|
+
- TOUJOURS demander confirmation avant d'ecraser un feature.json existant
|
|
17
|
+
- COMMUNICATION en `{language}` (depuis metadata ou config)
|
|
18
|
+
|
|
19
|
+
## VOTRE TACHE
|
|
20
|
+
|
|
21
|
+
Lire le fichier JSON exporte depuis le document HTML interactif et transformer toutes les donnees client en feature.json conforme au schema. Chaque element saisi par le client doit se retrouver dans le feature.json sans perte ni alteration.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## SEQUENCE D'EXECUTION
|
|
26
|
+
|
|
27
|
+
### 1. Lire le fichier JSON exporte
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Lire le fichier passe en argument : {extract_path}
|
|
31
|
+
→ Parser le JSON
|
|
32
|
+
→ Valider la structure minimale : metadata, cadrage, modules
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Structure attendue du JSON exporte :**
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"metadata": {
|
|
39
|
+
"applicationName": "...",
|
|
40
|
+
"applicationId": "...",
|
|
41
|
+
"version": "...",
|
|
42
|
+
"createdAt": "...",
|
|
43
|
+
"lastModified": "...",
|
|
44
|
+
"exportedAt": "..."
|
|
45
|
+
},
|
|
46
|
+
"cadrage": {
|
|
47
|
+
"problem": { "description": "", "impactedPeople": "", "history": "", "trigger": "", "consequences": "" },
|
|
48
|
+
"current": { "tools": "", "painPoints": "", "errors": "", "steps": [] },
|
|
49
|
+
"vision": { "changes": "", "results": "", "successSign": "" },
|
|
50
|
+
"stakeholders": [{ "role": "", "function": "", "tasks": [], "frequency": "", "access": "", "frustrations": "" }],
|
|
51
|
+
"scope": {
|
|
52
|
+
"vital": [{ "name": "", "description": "" }],
|
|
53
|
+
"important": [],
|
|
54
|
+
"optional": [],
|
|
55
|
+
"excluded": []
|
|
56
|
+
},
|
|
57
|
+
"risks": [{ "description": "", "probability": "", "impact": "", "mitigation": "" }],
|
|
58
|
+
"assumptions": "",
|
|
59
|
+
"success": { "definition": "", "metrics": "", "timeline": "", "minimumConditions": "" }
|
|
60
|
+
},
|
|
61
|
+
"modules": [{ "code": "", "name": "", "description": "", "featureType": "", "priority": "", "entities": [], "status": "" }],
|
|
62
|
+
"dependencies": [{ "from": "", "to": "", "description": "" }],
|
|
63
|
+
"moduleSpecifications": {
|
|
64
|
+
"{code}": {
|
|
65
|
+
"module": {},
|
|
66
|
+
"useCases": [{ "id": "", "name": "", "actor": "", "steps": "", "alternative": "" }],
|
|
67
|
+
"businessRules": [{ "id": "", "name": "", "category": "", "statement": "", "example": "" }],
|
|
68
|
+
"entities": [{ "name": "", "description": "", "attributes": [{ "name": "", "description": "" }], "relationships": [] }],
|
|
69
|
+
"permissions": [],
|
|
70
|
+
"notes": "",
|
|
71
|
+
"mockupNotes": ""
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"consolidation": {
|
|
75
|
+
"interactions": [],
|
|
76
|
+
"e2eFlows": [{ "name": "", "steps": [{ "module": "", "action": "" }], "actors": "" }]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
SI le fichier est invalide ou manquant → STOP avec message d'erreur.
|
|
82
|
+
|
|
83
|
+
### 2. Determiner l'application et le contexte
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
application_name = metadata.applicationName OU metadata.applicationId
|
|
87
|
+
version = metadata.version OU "1.0"
|
|
88
|
+
language = "fr" (par defaut, le document HTML est en francais)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Verifier si un feature.json existe deja :
|
|
92
|
+
```
|
|
93
|
+
ba-reader.findFeature(application_name)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
SI feature.json existe :
|
|
97
|
+
→ Demander via AskUserQuestion :
|
|
98
|
+
```
|
|
99
|
+
question: "Un feature.json existe deja pour cette application. Que souhaitez-vous faire ?"
|
|
100
|
+
header: "Conflit"
|
|
101
|
+
options:
|
|
102
|
+
- label: "Remplacer"
|
|
103
|
+
description: "Ecraser le feature.json existant avec les donnees du document interactif"
|
|
104
|
+
- label: "Fusionner"
|
|
105
|
+
description: "Fusionner les nouvelles donnees avec l'existant (priorite au document interactif)"
|
|
106
|
+
- label: "Nouvelle version"
|
|
107
|
+
description: "Creer une nouvelle version (v1.1) en conservant l'ancien"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 3. Mapper le cadrage
|
|
111
|
+
|
|
112
|
+
**Transformation : HTML export → feature.json cadrage**
|
|
113
|
+
|
|
114
|
+
| Source (export JSON) | Destination (feature.json) |
|
|
115
|
+
|---------------------|---------------------------|
|
|
116
|
+
| `cadrage.problem.description` | `cadrage.problem` |
|
|
117
|
+
| `cadrage.problem.impactedPeople` | `cadrage.problem` (append) |
|
|
118
|
+
| `cadrage.problem.history` | `cadrage.problem` (append) |
|
|
119
|
+
| `cadrage.problem.trigger` | `cadrage.trigger` |
|
|
120
|
+
| `cadrage.problem.consequences` | `cadrage.problem` (append) |
|
|
121
|
+
| `cadrage.current.tools` | `cadrage.asIs` |
|
|
122
|
+
| `cadrage.current.steps[]` | `cadrage.asIs` (append process steps) |
|
|
123
|
+
| `cadrage.current.painPoints` | `cadrage.asIs` (append) |
|
|
124
|
+
| `cadrage.current.errors` | `cadrage.asIs` (append) |
|
|
125
|
+
| `cadrage.vision.changes` | `cadrage.toBe` |
|
|
126
|
+
| `cadrage.vision.results` | `cadrage.toBe` (append) |
|
|
127
|
+
| `cadrage.vision.successSign` | `cadrage.toBe` (append) |
|
|
128
|
+
| `cadrage.stakeholders[]` | `cadrage.stakeholders[]` (voir mapping detaille) |
|
|
129
|
+
| `cadrage.scope.vital[]` | `cadrage.globalScope.mustHave[]` |
|
|
130
|
+
| `cadrage.scope.important[]` | `cadrage.globalScope.shouldHave[]` |
|
|
131
|
+
| `cadrage.scope.optional[]` | `cadrage.globalScope.couldHave[]` |
|
|
132
|
+
| `cadrage.scope.excluded[]` | `cadrage.globalScope.outOfScope[]` |
|
|
133
|
+
| `cadrage.risks[]` | `cadrage.risks[]` (voir mapping detaille) |
|
|
134
|
+
| `cadrage.assumptions` | `cadrage.risks[]` (type: "assumption") |
|
|
135
|
+
| `cadrage.success.definition` | `cadrage.acceptanceCriteria[]` |
|
|
136
|
+
| `cadrage.success.metrics` | `cadrage.acceptanceCriteria[]` |
|
|
137
|
+
| `cadrage.success.timeline` | `cadrage.acceptanceCriteria[]` |
|
|
138
|
+
| `cadrage.success.minimumConditions` | `cadrage.acceptanceCriteria[]` |
|
|
139
|
+
|
|
140
|
+
**Mapping detaille des parties prenantes :**
|
|
141
|
+
|
|
142
|
+
Pour chaque `cadrage.stakeholders[i]` :
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"role": stakeholders[i].role,
|
|
146
|
+
"function": stakeholders[i].function,
|
|
147
|
+
"involvement": mapAccessToInvolvement(stakeholders[i].access),
|
|
148
|
+
"tasks": stakeholders[i].tasks,
|
|
149
|
+
"frequency": stakeholders[i].frequency,
|
|
150
|
+
"painPoints": [stakeholders[i].frustrations]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Mapping `access` → `involvement` :
|
|
155
|
+
| access (HTML) | involvement (feature.json) |
|
|
156
|
+
|--------------|---------------------------|
|
|
157
|
+
| admin | decision-maker |
|
|
158
|
+
| manager | approver |
|
|
159
|
+
| contributor | end-user |
|
|
160
|
+
| viewer | informed |
|
|
161
|
+
|
|
162
|
+
**Mapping detaille des risques :**
|
|
163
|
+
|
|
164
|
+
Pour chaque `cadrage.risks[i]` :
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"id": "RISK-" + String(i + 1).padStart(3, '0'),
|
|
168
|
+
"type": "business",
|
|
169
|
+
"description": risks[i].description,
|
|
170
|
+
"probability": risks[i].probability,
|
|
171
|
+
"impact": risks[i].impact,
|
|
172
|
+
"priority": computePriority(risks[i].probability, risks[i].impact),
|
|
173
|
+
"mitigation": risks[i].mitigation
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Pour les hypotheses (texte libre `cadrage.assumptions`) :
|
|
178
|
+
```
|
|
179
|
+
Decouper le texte par lignes
|
|
180
|
+
Pour chaque ligne non vide, creer un risque :
|
|
181
|
+
{
|
|
182
|
+
"id": "RISK-ASM-" + index,
|
|
183
|
+
"type": "assumption",
|
|
184
|
+
"description": ligne,
|
|
185
|
+
"probability": "medium",
|
|
186
|
+
"impact": "medium",
|
|
187
|
+
"priority": "medium",
|
|
188
|
+
"mitigation": "A verifier avant le demarrage du projet"
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Mapping de la couverture :**
|
|
193
|
+
|
|
194
|
+
Construire `cadrage.coverageMatrix[]` a partir du scope :
|
|
195
|
+
```
|
|
196
|
+
Pour chaque item dans scope.vital :
|
|
197
|
+
{ "item": item.name, "category": "mustHave", "module": assignModule(item), "notes": item.description }
|
|
198
|
+
Pour chaque item dans scope.important :
|
|
199
|
+
{ "item": item.name, "category": "shouldHave", "module": assignModule(item), "notes": item.description }
|
|
200
|
+
Pour chaque item dans scope.optional :
|
|
201
|
+
{ "item": item.name, "category": "couldHave", "module": assignModule(item), "notes": item.description }
|
|
202
|
+
Pour chaque item dans scope.excluded :
|
|
203
|
+
{ "item": item.name, "category": "outOfScope", "module": null, "notes": item.description }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`assignModule(item)` : Si un seul module, assigner ce module. Si plusieurs modules, chercher le module dont le nom ou les entites correspondent le mieux a l'item.
|
|
207
|
+
|
|
208
|
+
**Mapping des roles applicatifs :**
|
|
209
|
+
|
|
210
|
+
Deriver `cadrage.applicationRoles[]` a partir des profils stakeholders :
|
|
211
|
+
```
|
|
212
|
+
Pour chaque stakeholder unique par niveau d'acces :
|
|
213
|
+
{
|
|
214
|
+
"role": "{App} " + formatRole(access),
|
|
215
|
+
"description": stakeholder.function,
|
|
216
|
+
"level": access,
|
|
217
|
+
"permissionPattern": "business.{app}." + (access === "admin" ? "*" : "...")
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Ecriture :**
|
|
222
|
+
```
|
|
223
|
+
ba-writer.enrichSection({
|
|
224
|
+
featureId: {feature_id},
|
|
225
|
+
section: "cadrage",
|
|
226
|
+
data: { problem, asIs, toBe, trigger, stakeholders, globalScope, applicationRoles, risks, acceptanceCriteria, coverageMatrix, codebaseContext }
|
|
227
|
+
})
|
|
228
|
+
ba-writer.updateStatus({feature_id}, "framed")
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### 4. Mapper les modules
|
|
232
|
+
|
|
233
|
+
Pour chaque `modules[i]` du JSON exporte :
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"code": modules[i].code,
|
|
237
|
+
"description": modules[i].description,
|
|
238
|
+
"featureType": modules[i].featureType,
|
|
239
|
+
"dependencies": deriveDependencies(modules[i].code),
|
|
240
|
+
"dependents": deriveDependents(modules[i].code),
|
|
241
|
+
"status": "pending",
|
|
242
|
+
"featureJsonPath": null,
|
|
243
|
+
"priority": modules[i].priority,
|
|
244
|
+
"sortOrder": computeSortOrder(modules[i].code),
|
|
245
|
+
"entities": modules[i].entities,
|
|
246
|
+
"estimatedComplexity": estimateComplexity(modules[i].code)
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
`deriveDependencies(code)` : filtrer `dependencies[]` ou `from === code`, retourner les `to`
|
|
251
|
+
`deriveDependents(code)` : filtrer `dependencies[]` ou `to === code`, retourner les `from`
|
|
252
|
+
`computeSortOrder(code)` : depuis le tri topologique
|
|
253
|
+
`estimateComplexity(code)` : basee sur le nombre d'entites et de cas d'utilisation du module
|
|
254
|
+
|
|
255
|
+
**Construire le graphe de dependances :**
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"edges": dependencies.map(d => ({ "from": d.from, "to": d.to, "type": "FK", "description": d.description })),
|
|
259
|
+
"topologicalOrder": computeTopologicalOrder(),
|
|
260
|
+
"layers": computeLayers()
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Ecriture :**
|
|
265
|
+
```
|
|
266
|
+
ba-writer.enrichModuleRegistry({
|
|
267
|
+
featureId: {feature_id},
|
|
268
|
+
modules: [mapped modules],
|
|
269
|
+
dependencyGraph: { edges, topologicalOrder, layers }
|
|
270
|
+
})
|
|
271
|
+
ba-writer.updateStatus({feature_id}, "decomposed")
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 5. Mapper les specifications par module
|
|
275
|
+
|
|
276
|
+
Pour chaque module dans l'ordre topologique :
|
|
277
|
+
|
|
278
|
+
#### 5a. Creer le feature.json du module
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
ba-writer.create({
|
|
282
|
+
scope: "module",
|
|
283
|
+
applicationRef: {feature_id},
|
|
284
|
+
moduleCode: {module.code},
|
|
285
|
+
path: "docs/business/{app}/{module_code}/business-analyse/v1.0/feature.json"
|
|
286
|
+
})
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### 5b. Mapper la section discovery
|
|
290
|
+
|
|
291
|
+
Deriver de la cadrage, filtree pour ce module (meme logique que step-03 section 2-ter).
|
|
292
|
+
|
|
293
|
+
#### 5c. Mapper les cas d'utilisation
|
|
294
|
+
|
|
295
|
+
Pour chaque `moduleSpecifications[code].useCases[i]` :
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"id": "UC-{PREFIX}-" + String(i + 1).padStart(3, '0'),
|
|
299
|
+
"name": uc.name,
|
|
300
|
+
"primaryActor": uc.actor,
|
|
301
|
+
"permission": "business.{app}.{module}.{inferAction(uc.name)}",
|
|
302
|
+
"preconditions": [],
|
|
303
|
+
"postconditions": [],
|
|
304
|
+
"mainScenario": parseSteps(uc.steps),
|
|
305
|
+
"alternativeScenarios": uc.alternative ? [{ "name": "Cas alternatif", "steps": [uc.alternative] }] : [],
|
|
306
|
+
"errorScenarios": [],
|
|
307
|
+
"linkedRules": linkToBusinessRules(uc, moduleSpec.businessRules)
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
`parseSteps(text)` : Decouper par lignes, retourner en tableau.
|
|
312
|
+
`inferAction(name)` : Extraire le verbe (Creer→create, Modifier→update, Supprimer→delete, Consulter→read, Valider→approve, Exporter→export).
|
|
313
|
+
`linkToBusinessRules(uc, rules)` : Chercher les regles dont le statement mentionne des concepts similaires au nom du UC.
|
|
314
|
+
|
|
315
|
+
#### 5d. Mapper les regles metier
|
|
316
|
+
|
|
317
|
+
Pour chaque `moduleSpecifications[code].businessRules[i]` :
|
|
318
|
+
```json
|
|
319
|
+
{
|
|
320
|
+
"id": "BR-{CAT}-{PREFIX}-" + String(i + 1).padStart(3, '0'),
|
|
321
|
+
"name": br.name,
|
|
322
|
+
"category": br.category,
|
|
323
|
+
"statement": br.statement,
|
|
324
|
+
"priority": "must",
|
|
325
|
+
"conditions": extractConditions(br.statement),
|
|
326
|
+
"examples": br.example ? [{ "input": br.example, "expected": "Selon la regle" }] : [],
|
|
327
|
+
"testability": "Via test unitaire"
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
`{CAT}` derive de `category` : validation→VAL, calculation→CALC, workflow→WF, security→SEC, data→DATA
|
|
332
|
+
`extractConditions(statement)` : Extraire les conditions depuis le texte "Si..." en tableau.
|
|
333
|
+
|
|
334
|
+
#### 5e. Mapper les entites
|
|
335
|
+
|
|
336
|
+
Pour chaque `moduleSpecifications[code].entities[i]` :
|
|
337
|
+
```json
|
|
338
|
+
{
|
|
339
|
+
"name": toPascalCase(ent.name),
|
|
340
|
+
"description": ent.description,
|
|
341
|
+
"attributes": ent.attributes.map(a => ({
|
|
342
|
+
"name": toCamelCase(a.name),
|
|
343
|
+
"description": a.description,
|
|
344
|
+
"required": true,
|
|
345
|
+
"unique": false,
|
|
346
|
+
"validation": ""
|
|
347
|
+
})),
|
|
348
|
+
"relationships": parseRelationships(ent.relationships)
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
`parseRelationships(rels)` : Pour chaque relation texte "Nom - Description", extraire :
|
|
353
|
+
```json
|
|
354
|
+
{ "target": toPascalCase(nom), "type": "1:N", "description": description }
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### 5f. Mapper les permissions
|
|
358
|
+
|
|
359
|
+
Transformer le format `permissions: ["Role|Action"]` en matrice structuree :
|
|
360
|
+
```json
|
|
361
|
+
{
|
|
362
|
+
"permissions": derivePermissionPaths(code, actions),
|
|
363
|
+
"roleAssignments": deriveRoleAssignments(code, permissions)
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### 5g. Generer les sections, wireframes et seedDataCore
|
|
368
|
+
|
|
369
|
+
Inferer automatiquement a partir des entites et du type de module (meme logique que step-03 section 3a-infer).
|
|
370
|
+
|
|
371
|
+
#### 5h. Ecrire le feature.json du module
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
ba-writer.enrichSection({ featureId: moduleFeatureId, section: "analysis", data: { objectives, entities, businessRules, processFlow, dataLifecycle } })
|
|
375
|
+
ba-writer.enrichSection({ featureId: moduleFeatureId, section: "specification", data: { actors, useCases, functionalRequirements, permissionMatrix, navigation, seedDataCore, sections, uiWireframes } })
|
|
376
|
+
ba-writer.updateModuleStatus({feature_id}, {module.code}, "specified")
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### 6. Mapper la consolidation
|
|
380
|
+
|
|
381
|
+
Si plusieurs modules :
|
|
382
|
+
```
|
|
383
|
+
ba-writer.enrichSection({
|
|
384
|
+
featureId: {feature_id},
|
|
385
|
+
section: "consolidation",
|
|
386
|
+
data: {
|
|
387
|
+
crossModuleInteractions: dependencies.map(d => ({
|
|
388
|
+
"fromModule": d.from, "toModule": d.to,
|
|
389
|
+
"interactionType": "FK-reference",
|
|
390
|
+
"description": d.description,
|
|
391
|
+
"entities": []
|
|
392
|
+
})),
|
|
393
|
+
e2eFlows: consolidation.e2eFlows.map(flow => ({
|
|
394
|
+
"name": flow.name,
|
|
395
|
+
"modules": [...new Set(flow.steps.map(s => s.module))],
|
|
396
|
+
"steps": flow.steps.map(s => ({
|
|
397
|
+
"module": s.module,
|
|
398
|
+
"action": s.action,
|
|
399
|
+
"permission": "",
|
|
400
|
+
"dataFlow": ""
|
|
401
|
+
}))
|
|
402
|
+
})),
|
|
403
|
+
permissionCoherence: { rolesConsistent: true, pathFormatConsistent: true, hierarchyRespected: true, conflicts: [], warnings: [] },
|
|
404
|
+
decision: { approved: true, reason: "Extracted from interactive document", approvedBy: "Client", approvedAt: new Date().toISOString() }
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
ba-writer.updateStatus({feature_id}, "consolidated")
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### 7. Resume de l'extraction
|
|
411
|
+
|
|
412
|
+
Afficher un resume comparatif :
|
|
413
|
+
```
|
|
414
|
+
═══════════════════════════════════════════════════════════════
|
|
415
|
+
EXTRACTION TERMINEE - {application_name}
|
|
416
|
+
═══════════════════════════════════════════════════════════════
|
|
417
|
+
|
|
418
|
+
| Element | Document client | Feature.json |
|
|
419
|
+
|------------------------|----------------|--------------|
|
|
420
|
+
| Probleme | {oui/non} | cadrage.problem |
|
|
421
|
+
| Situation actuelle | {oui/non} | cadrage.asIs |
|
|
422
|
+
| Vision | {oui/non} | cadrage.toBe |
|
|
423
|
+
| Parties prenantes | {count} | cadrage.stakeholders |
|
|
424
|
+
| Perimetre (vital) | {count} | globalScope.mustHave |
|
|
425
|
+
| Perimetre (important) | {count} | globalScope.shouldHave |
|
|
426
|
+
| Perimetre (optionnel) | {count} | globalScope.couldHave |
|
|
427
|
+
| Risques | {count} | cadrage.risks |
|
|
428
|
+
| Criteres de reussite | {count} | acceptanceCriteria |
|
|
429
|
+
| Domaines fonctionnels | {count} | modules |
|
|
430
|
+
| Dependances | {count} | dependencyGraph.edges |
|
|
431
|
+
| Cas d'utilisation | {total} | specification.useCases |
|
|
432
|
+
| Regles metier | {total} | analysis.businessRules |
|
|
433
|
+
| Entites | {total} | analysis.entities |
|
|
434
|
+
| Parcours E2E | {count} | consolidation.e2eFlows |
|
|
435
|
+
|
|
436
|
+
Fichiers generes :
|
|
437
|
+
- docs/business/{app}/business-analyse/v1.0/feature.json (master)
|
|
438
|
+
- docs/business/{app}/{module}/business-analyse/v1.0/feature.json (par module)
|
|
439
|
+
|
|
440
|
+
═══════════════════════════════════════════════════════════════
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### 8. Choix de la suite
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
question: "L'extraction est terminee. Que souhaitez-vous faire ?"
|
|
447
|
+
header: "Suite"
|
|
448
|
+
options:
|
|
449
|
+
- label: "Enrichir avec le questionnaire"
|
|
450
|
+
description: "Lancer le cadrage approfondi (step-01) pour completer l'analyse avec des questions detaillees"
|
|
451
|
+
- label: "Passer au handoff"
|
|
452
|
+
description: "Generer directement le plan de developpement (step-05)"
|
|
453
|
+
- label: "Terminer"
|
|
454
|
+
description: "L'extraction suffit, je reprendrai manuellement"
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
SI "Enrichir" → charger step-01-cadrage.md (les donnees existantes seront preservees)
|
|
458
|
+
SI "Handoff" → charger step-05-handoff.md
|
|
459
|
+
SI "Terminer" → EXIT
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## FONCTIONS UTILITAIRES
|
|
464
|
+
|
|
465
|
+
### toPascalCase(text)
|
|
466
|
+
"gestion des commandes" → "GestionDesCommandes"
|
|
467
|
+
"commande" → "Commande"
|
|
468
|
+
|
|
469
|
+
### toCamelCase(text)
|
|
470
|
+
"Numero de commande" → "numeroDeCommande"
|
|
471
|
+
"Date" → "date"
|
|
472
|
+
|
|
473
|
+
### computePriority(probability, impact)
|
|
474
|
+
| probability | impact | priority |
|
|
475
|
+
|------------|--------|----------|
|
|
476
|
+
| high | high | critical |
|
|
477
|
+
| high | medium | critical |
|
|
478
|
+
| high | low | medium |
|
|
479
|
+
| medium | high | critical |
|
|
480
|
+
| medium | medium | medium |
|
|
481
|
+
| medium | low | low |
|
|
482
|
+
| low | high | medium |
|
|
483
|
+
| low | medium | low |
|
|
484
|
+
| low | low | low |
|
|
485
|
+
|
|
486
|
+
### inferAction(ucName)
|
|
487
|
+
Mots cles → action :
|
|
488
|
+
- creer, ajouter, nouveau → create
|
|
489
|
+
- modifier, editer, mettre a jour → update
|
|
490
|
+
- supprimer, retirer, annuler → delete
|
|
491
|
+
- consulter, voir, afficher, lister → read
|
|
492
|
+
- valider, approuver, confirmer → approve
|
|
493
|
+
- exporter, telecharger → export
|
|
494
|
+
- importer, charger → import
|
|
495
|
+
- defaut → read
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## VALIDATION
|
|
500
|
+
|
|
501
|
+
Avant d'ecrire dans feature.json, verifier :
|
|
502
|
+
- Chaque stakeholder a au minimum : role, function
|
|
503
|
+
- Chaque use case a au minimum : name, actor
|
|
504
|
+
- Chaque business rule a au minimum : name, statement
|
|
505
|
+
- Chaque entite a au minimum : name
|
|
506
|
+
- Les IDs sont uniques (pas de doublons UC, BR, RISK)
|
|
507
|
+
- Les modules references dans les dependances existent
|
|
508
|
+
|
|
509
|
+
SI une validation echoue → afficher l'erreur et demander correction.
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## GARANTIES
|
|
514
|
+
|
|
515
|
+
- **Zero perte** : chaque champ saisi dans le document HTML se retrouve dans le feature.json
|
|
516
|
+
- **Enrichissement** : les IDs, permissions et liens sont generes automatiquement
|
|
517
|
+
- **Conformite** : le feature.json resultant est conforme au schema
|
|
518
|
+
- **Reversibilite** : le JSON exporte original est conserve dans `metadata.sourceExport`
|
|
@@ -163,7 +163,7 @@ api-reference.html | vX.Y.Y | MISMATCH
|
|
|
163
163
|
|
|
164
164
|
<gitflow_integration>
|
|
165
165
|
|
|
166
|
-
This skill is automatically called during `/gitflow
|
|
166
|
+
This skill is automatically called during `/gitflow finish` for release branches.
|
|
167
167
|
|
|
168
168
|
If mismatches detected during release finish:
|
|
169
169
|
- Warning displayed
|
|
@@ -19,6 +19,16 @@ Apply pending EF Core migrations to the local database.
|
|
|
19
19
|
### 1. Environment Check
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
# Validate required variables from step-00-init
|
|
23
|
+
for VAR_NAME in DBCONTEXT DBCONTEXT_TYPE INFRA_PROJECT STARTUP_PROJECT SELECTED_ENV; do
|
|
24
|
+
eval VAR_VALUE=\$$VAR_NAME
|
|
25
|
+
if [ -z "$VAR_VALUE" ]; then
|
|
26
|
+
echo "ERROR: Required variable $VAR_NAME is not set"
|
|
27
|
+
echo "Run step-00-init first"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
done
|
|
31
|
+
|
|
22
32
|
echo "Deploy Configuration"
|
|
23
33
|
echo "===================="
|
|
24
34
|
echo ""
|
|
@@ -37,12 +47,20 @@ block_production
|
|
|
37
47
|
echo ""
|
|
38
48
|
echo "Checking pending migrations..."
|
|
39
49
|
|
|
50
|
+
EF_STDERR=$(mktemp)
|
|
40
51
|
PENDING=$(dotnet ef migrations list \
|
|
41
52
|
--context "$DBCONTEXT" \
|
|
42
53
|
--project "$INFRA_PROJECT" \
|
|
43
|
-
--startup-project "$STARTUP_PROJECT" 2
|
|
54
|
+
--startup-project "$STARTUP_PROJECT" 2>"$EF_STDERR" | \
|
|
44
55
|
grep -c "(Pending)" || echo "0")
|
|
45
56
|
|
|
57
|
+
# Check for real errors (not just build output)
|
|
58
|
+
if grep -qi "error\|exception\|failed" "$EF_STDERR" 2>/dev/null; then
|
|
59
|
+
echo "WARNING: EF Core reported errors:"
|
|
60
|
+
grep -i "error\|exception\|failed" "$EF_STDERR" | head -5
|
|
61
|
+
fi
|
|
62
|
+
rm -f "$EF_STDERR"
|
|
63
|
+
|
|
46
64
|
echo "Pending: $PENDING migration(s)"
|
|
47
65
|
|
|
48
66
|
if [ "$PENDING" -eq 0 ]; then
|
|
@@ -97,10 +115,11 @@ dotnet ef database update \
|
|
|
97
115
|
--project "$INFRA_PROJECT" \
|
|
98
116
|
--startup-project "$STARTUP_PROJECT" \
|
|
99
117
|
--verbose
|
|
118
|
+
EXIT_CODE=$?
|
|
100
119
|
|
|
101
|
-
if [
|
|
120
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
102
121
|
echo ""
|
|
103
|
-
echo "ERROR: Migration failed"
|
|
122
|
+
echo "ERROR: Migration failed (exit code: $EXIT_CODE)"
|
|
104
123
|
echo ""
|
|
105
124
|
echo "Troubleshooting:"
|
|
106
125
|
echo " - Check database connection"
|
|
@@ -33,6 +33,16 @@ Completely reset the database: drop, recreate, and apply all migrations.
|
|
|
33
33
|
### 1. Environment Check
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
+
# Validate required variables from step-00-init
|
|
37
|
+
for VAR_NAME in DBCONTEXT DBCONTEXT_TYPE INFRA_PROJECT STARTUP_PROJECT SELECTED_ENV; do
|
|
38
|
+
eval VAR_VALUE=\$$VAR_NAME
|
|
39
|
+
if [ -z "$VAR_VALUE" ]; then
|
|
40
|
+
echo "ERROR: Required variable $VAR_NAME is not set"
|
|
41
|
+
echo "Run step-00-init first"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
36
46
|
echo "Reset Configuration"
|
|
37
47
|
echo "==================="
|
|
38
48
|
echo ""
|
|
@@ -111,9 +121,10 @@ dotnet ef database drop \
|
|
|
111
121
|
--project "$INFRA_PROJECT" \
|
|
112
122
|
--startup-project "$STARTUP_PROJECT" \
|
|
113
123
|
--force
|
|
124
|
+
EXIT_CODE=$?
|
|
114
125
|
|
|
115
|
-
if [
|
|
116
|
-
echo "ERROR: Drop failed"
|
|
126
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
127
|
+
echo "ERROR: Drop failed (exit code: $EXIT_CODE)"
|
|
117
128
|
echo "Database may be in use. Close connections and retry."
|
|
118
129
|
exit 1
|
|
119
130
|
fi
|
|
@@ -132,10 +143,11 @@ dotnet ef database update \
|
|
|
132
143
|
--project "$INFRA_PROJECT" \
|
|
133
144
|
--startup-project "$STARTUP_PROJECT" \
|
|
134
145
|
--verbose
|
|
146
|
+
EXIT_CODE=$?
|
|
135
147
|
|
|
136
|
-
if [
|
|
148
|
+
if [ $EXIT_CODE -ne 0 ]; then
|
|
137
149
|
echo ""
|
|
138
|
-
echo "ERROR: Recreation failed"
|
|
150
|
+
echo "ERROR: Recreation failed (exit code: $EXIT_CODE)"
|
|
139
151
|
exit 1
|
|
140
152
|
fi
|
|
141
153
|
|
|
@@ -254,6 +266,17 @@ DBCONTEXT="ExtensionsDbContext"
|
|
|
254
266
|
|
|
255
267
|
---
|
|
256
268
|
|
|
269
|
+
## OPTIONS:
|
|
270
|
+
|
|
271
|
+
| Option | Description |
|
|
272
|
+
|--------|-------------|
|
|
273
|
+
| `--env {name}` | Use appsettings.{name}.json |
|
|
274
|
+
| `--no-backup` | Skip backup step |
|
|
275
|
+
| `--context {name}` | Specify DbContext |
|
|
276
|
+
| `--seed` | Auto-seed after reset |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
257
280
|
## COMPLETION:
|
|
258
281
|
|
|
259
282
|
Database reset complete. Fresh state with all migrations applied.
|