@atlashub/smartstack-cli 4.74.0 → 4.76.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/dist/index.js +152 -31
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +14 -3
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-reader.md +17 -15
- package/templates/agents/ba-writer.md +49 -51
- package/templates/skills/apex/SKILL.md +2 -2
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/backend-checks.sh +21 -7
- package/templates/skills/apex/references/checks/frontend-checks.sh +26 -0
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +47 -10
- package/templates/skills/apex/references/checks/seed-checks.sh +47 -7
- package/templates/skills/apex/references/core-seed-data.md +20 -18
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/apex/references/post-checks.md +23 -3
- package/templates/skills/apex/references/smartstack-api.md +4 -4
- package/templates/skills/apex/references/smartstack-frontend.md +54 -8
- package/templates/skills/apex/references/smartstack-layers.md +6 -6
- package/templates/skills/apex/steps/step-00-init.md +75 -1
- package/templates/skills/apex/steps/step-03-execute.md +16 -4
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +65 -6
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +50 -5
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +226 -4
- package/templates/skills/apex/steps/step-04-examine.md +163 -0
- package/templates/skills/apex-verify/SKILL.md +110 -0
- package/templates/skills/apex-verify/references/audit-rules.md +50 -0
- package/templates/skills/apex-verify/steps/step-00-init.md +119 -0
- package/templates/skills/apex-verify/steps/step-01-nav-audit.md +92 -0
- package/templates/skills/apex-verify/steps/step-02-crud-audit.md +127 -0
- package/templates/skills/apex-verify/steps/step-03-perm-audit.md +119 -0
- package/templates/skills/apex-verify/steps/step-04-route-audit.md +98 -0
- package/templates/skills/apex-verify/steps/step-05-report.md +110 -0
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/application/templates-frontend.md +2 -2
- package/templates/skills/business-analyse/SKILL.md +17 -3
- package/templates/skills/business-analyse/_shared.md +64 -0
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +34 -26
- package/templates/skills/business-analyse/questionnaire/01-context.md +13 -9
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +20 -27
- package/templates/skills/business-analyse/questionnaire.md +86 -9
- package/templates/skills/business-analyse/references/03-json-schemas.md +221 -0
- package/templates/skills/business-analyse/references/03-post-check-validation.md +208 -0
- package/templates/skills/business-analyse/references/03-smartstack-entity-guards.md +32 -0
- package/templates/skills/business-analyse/references/04-cross-module-validation.md +95 -0
- package/templates/skills/business-analyse/references/04-file-allocation.md +162 -0
- package/templates/skills/business-analyse/references/04-naming-audit-checks.md +174 -0
- package/templates/skills/business-analyse/references/04-semantic-validation-matrix.md +118 -0
- package/templates/skills/business-analyse/references/canonical-json-formats.md +7 -3
- package/templates/skills/business-analyse/references/domain-research-playbook.md +234 -0
- package/templates/skills/business-analyse/references/entity-sourcing-presentation.md +166 -0
- package/templates/skills/business-analyse/references/init-resume-logic.md +70 -0
- package/templates/skills/business-analyse/references/module-completeness-challenge.md +174 -0
- package/templates/skills/business-analyse/references/multi-app-detection.md +149 -0
- package/templates/skills/business-analyse/references/portal-classification.md +52 -0
- package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
- package/templates/skills/business-analyse/references/validation-checklist.md +35 -6
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +50 -6
- package/templates/skills/business-analyse/steps/step-00-init.md +22 -190
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +365 -269
- package/templates/skills/business-analyse/steps/step-02-structure.md +98 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +810 -229
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +509 -278
- package/templates/skills/business-analyse-design/SKILL.md +10 -0
- package/templates/skills/business-analyse-design/references/screens-post-check.md +221 -0
- package/templates/skills/business-analyse-design/references/screens-type-mapping.md +138 -0
- package/templates/skills/business-analyse-design/references/smartcomponents-templates.md +225 -0
- package/templates/skills/{business-analyse → business-analyse-design}/references/spec-auto-inference.md +117 -117
- package/templates/skills/business-analyse-design/steps/step-01-screens.md +36 -162
- package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +8 -7
- package/templates/skills/business-analyse-design/steps/step-03-navigation.md +89 -42
- package/templates/skills/business-analyse-develop/references/compact-loop.md +9 -0
- package/templates/skills/business-analyse-develop/references/handoff-quality-gate.md +132 -0
- package/templates/skills/business-analyse-develop/references/prd-v3-transformation.md +326 -0
- package/templates/skills/business-analyse-develop/references/report-reconciliation.md +140 -0
- package/templates/skills/business-analyse-develop/references/report-template.md +142 -0
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +5 -177
- package/templates/skills/business-analyse-develop/steps/step-02-execute.md +17 -4
- package/templates/skills/business-analyse-develop/steps/step-03-commit.md +6 -2
- package/templates/skills/business-analyse-develop/steps/step-04-check.md +6 -0
- package/templates/skills/business-analyse-develop/steps/step-05-report.md +3 -269
- package/templates/skills/business-analyse-handoff/SKILL.md +10 -0
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +211 -0
- package/templates/skills/business-analyse-handoff/references/context-isolation-pattern.md +47 -0
- package/templates/skills/business-analyse-handoff/references/handoff-file-inventory.md +49 -0
- package/templates/skills/business-analyse-handoff/references/handoff-global-validation.md +142 -0
- package/templates/skills/business-analyse-handoff/references/prd-validation-checks.md +125 -0
- package/templates/skills/business-analyse-handoff/references/project-index-update.md +98 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +9 -160
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +10 -99
- package/templates/skills/business-analyse-html/SKILL.md +10 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +504 -97
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +79 -2
- package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +6 -46
- package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +80 -11
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-consolidation.js +2 -2
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +94 -36
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +162 -0
- package/templates/skills/business-analyse-html/html/src/styles/10-diagrams.css +73 -0
- package/templates/skills/business-analyse-html/html/src/template.html +2 -0
- package/templates/skills/business-analyse-html/references/02-embedded-artifacts-building.md +144 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +143 -0
- package/templates/skills/business-analyse-html/references/02-mapping-tables.md +442 -0
- package/templates/skills/business-analyse-html/references/02-normalization-helpers.md +139 -0
- package/templates/skills/business-analyse-html/references/02-screen-format-detection.md +283 -0
- package/templates/skills/business-analyse-html/references/02-self-check-validation.md +199 -0
- package/templates/skills/business-analyse-html/references/data-build.md +24 -1
- package/templates/skills/business-analyse-html/references/data-mapping.md +119 -17
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +18 -555
- package/templates/skills/business-analyse-html/steps/step-04-verify.md +92 -3
- package/templates/skills/business-analyse-quick/SKILL.md +807 -0
- package/templates/skills/{sketch → business-analyse-quick}/references/domain-heuristics.md +59 -3
- package/templates/skills/business-analyse-quick/references/prd-schema.md +268 -0
- package/templates/skills/business-analyse-review/SKILL.md +10 -0
- package/templates/skills/business-analyse-review/references/review-data-mapping.md +6 -0
- package/templates/skills/business-analyse-status/SKILL.md +8 -0
- package/templates/skills/dev-start/SKILL.md +143 -307
- package/templates/skills/efcore/SKILL.md +13 -0
- package/templates/skills/sketch/SKILL.md +15 -153
- package/templates/skills/ui-components/SKILL.md +1 -1
- package/templates/skills/ui-components/patterns/data-table.md +1 -1
|
@@ -31,24 +31,142 @@ function resolveModuleDir(appCode, moduleCode) {
|
|
|
31
31
|
> **Module directory (ba-006):** `mod.dir = resolveModuleDir(applicationCode, module.code)`
|
|
32
32
|
> Example: `docs/projet-rh/v1.0/human-resources/employees/`
|
|
33
33
|
|
|
34
|
+
## ENFORCEMENT LANGUE (OBLIGATOIRE)
|
|
35
|
+
|
|
36
|
+
Toutes les valeurs textuelles générées dans les fichiers JSON de ce module DOIVENT être rédigées en `{language}` :
|
|
37
|
+
|
|
38
|
+
| Champ JSON | Langue | Exemple FR | Exemple EN |
|
|
39
|
+
|------------|--------|-----------|-----------|
|
|
40
|
+
| entity.description | `{language}` | "Représente un employé" | "Represents an employee" |
|
|
41
|
+
| attribute.description | `{language}` | "Code unique de l'employé" | "Unique employee code" |
|
|
42
|
+
| rule.statement | `{language}` | "Le code doit être unique" | "Code must be unique" |
|
|
43
|
+
| rule.examples[].input | `{language}` | "code='EMP-001', doublon" | "code='EMP-001', duplicate" |
|
|
44
|
+
| rule.examples[].expected | `{language}` | "Erreur : code déjà existant" | "Error: code already exists" |
|
|
45
|
+
| usecase.name | `{language}` | "Créer un employé" | "Create employee" |
|
|
46
|
+
| usecase.mainScenario[] | `{language}` | "L'utilisateur ouvre la page" | "User opens the page" |
|
|
47
|
+
| usecase.preconditions[] | `{language}` | "L'utilisateur est connecté" | "User is logged in" |
|
|
48
|
+
| permission.description | `{language}` | "Consulter la liste" | "View the list" |
|
|
49
|
+
|
|
50
|
+
**Identifiants techniques** (PascalCase) restent en anglais : `Employee`, `AbsenceBalance`, `status`, `BR-VAL-EMP-001`.
|
|
51
|
+
|
|
52
|
+
**VIOLATION = contenu rejeté à la consolidation (step-04).**
|
|
53
|
+
|
|
34
54
|
## Prerequisites
|
|
35
55
|
|
|
36
56
|
- Step 02 (structure) completed
|
|
37
57
|
- Applications, modules, sections, dependencies identified
|
|
38
58
|
|
|
59
|
+
## Scope Verification (BLOCKING — before any module processing)
|
|
60
|
+
|
|
61
|
+
Re-read `.business-analyse/config.json` and verify scope has not drifted:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
const config = readJSON('.business-analyse/config.json').currentFeature;
|
|
65
|
+
const expectedApps = config.candidateApplications?.length || 1;
|
|
66
|
+
const confirmedModules = /* read from step-02 output: application index.json modules[] */;
|
|
67
|
+
|
|
68
|
+
// BLOCKING if scope drifted
|
|
69
|
+
if (config.workflowMode === "project") {
|
|
70
|
+
const appIndexFiles = GLOB(`${config.docsDir}/*/index.json`);
|
|
71
|
+
if (appIndexFiles.length > expectedApps) {
|
|
72
|
+
BLOCKING_ERROR(`Scope drift: expected ${expectedApps} applications but found ${appIndexFiles.length}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Log confirmed scope for traceability
|
|
77
|
+
Display(`Scope locked: ${expectedApps} app(s), ${confirmedModules.length} module(s)`);
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## INTERDICTIONS ABSOLUES (step-03)
|
|
81
|
+
|
|
82
|
+
+==============================================================================+
|
|
83
|
+
| INTERDICTIONS — Violation = analyse invalide |
|
|
84
|
+
+==============================================================================+
|
|
85
|
+
| |
|
|
86
|
+
| 1. JAMAIS lancer ba-writer pour un module AVANT validation client |
|
|
87
|
+
| des entites, regles, use cases ET permissions de ce module. |
|
|
88
|
+
| |
|
|
89
|
+
| 2. JAMAIS lancer des ba-writer en PARALLELE pour des modules differents. |
|
|
90
|
+
| Chaque module est traite SEQUENTIELLEMENT avec interaction client. |
|
|
91
|
+
| |
|
|
92
|
+
| 3. JAMAIS persister des entites, regles, volumetries, filtres |
|
|
93
|
+
| ou notifications sans VALIDATION CLIENT (confirmation du lot propose). |
|
|
94
|
+
| L'auto-deduction avec confirmation groupee est une validation valide. |
|
|
95
|
+
| |
|
|
96
|
+
| 4. JAMAIS sauter la VALIDATION CLIENT meme si le domaine semble "evident". |
|
|
97
|
+
| Auto-deduction + confirmation groupee = OK. Pas de confirmation = KO. |
|
|
98
|
+
| |
|
|
99
|
+
| 5. SUBAGENT DISCIPLINE : |
|
|
100
|
+
| - MAX 1 ba-writer par module (ecriture finale apres validation) |
|
|
101
|
+
| - Total ba-writer pour step-03 = nombre_de_modules (pas plus) |
|
|
102
|
+
| - INTERDICTION de spawner des ba-writer pour des modules NON encore |
|
|
103
|
+
| valides par le client |
|
|
104
|
+
| |
|
|
105
|
+
| 6. JAMAIS "accelerer" en batchant des modules dans des sub-agents. |
|
|
106
|
+
| Sub-agents (Agent/Snipper) n'ont PAS acces au schema JSON canonique. |
|
|
107
|
+
| PREUVE: audit ba-012 → 4 dialectes JSON, conformite 95% → 35%. |
|
|
108
|
+
| Si > 10 modules: maintenir le sequentiel, le retravail coute plus. |
|
|
109
|
+
| |
|
|
110
|
+
+==============================================================================+
|
|
111
|
+
|
|
39
112
|
## Sequential Execution
|
|
40
113
|
|
|
41
114
|
**No team mode.** Each module receives 100% of LLM attention for maximum specification quality.
|
|
42
115
|
|
|
43
|
-
Process modules in
|
|
116
|
+
Process **application by application**, modules in dependency order within each app:
|
|
117
|
+
|
|
44
118
|
```
|
|
45
|
-
|
|
119
|
+
IF workflow_mode = "project" (multi-app):
|
|
120
|
+
// Group by application first, then topological sort within each app
|
|
121
|
+
// Cross-app dependencies: if Module A (App1) depends on Module B (App2),
|
|
122
|
+
// App2 must be processed before App1. Adjust application order accordingly.
|
|
123
|
+
|
|
124
|
+
applicationOrder = resolveApplicationOrder(modules, dependencies)
|
|
125
|
+
// e.g., [Rh, Crm, GestionDeProjet, Facturation, Portal]
|
|
126
|
+
|
|
127
|
+
For EACH application in applicationOrder:
|
|
128
|
+
Display application banner:
|
|
129
|
+
═══════════════════════════════════════════════════════
|
|
130
|
+
APPLICATION {appIndex}/{appTotal} : {appName}
|
|
131
|
+
═══════════════════════════════════════════════════════
|
|
132
|
+
|
|
133
|
+
appModules = modules.filter(m => m.applicationCode === app.code)
|
|
134
|
+
sortedAppModules = topologicalSort(appModules)
|
|
135
|
+
|
|
136
|
+
For EACH module in sortedAppModules:
|
|
137
|
+
specify(module) // Full cycle: A-bis → A-ter → B → C-pre → C → D → E → F → H
|
|
138
|
+
|
|
139
|
+
ELSE (single-app):
|
|
140
|
+
For module in topologicalSort(modules):
|
|
46
141
|
specify(module)
|
|
47
142
|
```
|
|
48
143
|
|
|
49
|
-
## Per-Module Specification Loop
|
|
144
|
+
## Per-Module Specification Loop — STRICT MODE
|
|
145
|
+
|
|
146
|
+
### VALIDATION MINIMALE (per module — ba-009 fix)
|
|
147
|
+
|
|
148
|
+
Chaque module metier (hors Portal et config) requiert AU MINIMUM 2 AskUserQuestion :
|
|
149
|
+
1. Entites (B-ter) : "Voici les entites pour {module}. Corrections ?"
|
|
150
|
+
2. Regles + UCs + Permissions (C-bis + E-ter groupes) : "Voici les regles, UCs et permissions pour {module}. Corrections ?"
|
|
151
|
+
|
|
152
|
+
Exceptions :
|
|
153
|
+
- Modules **Portal** (read-only, 0 entites propres) : 1 validation groupee suffit.
|
|
154
|
+
- Modules **config/lookup** (< 2 entites) : 1 validation groupee suffit.
|
|
155
|
+
|
|
156
|
+
**INTERDICTION** de tout bundler en 1 seule question "Module complet, validez-vous ?" pour les modules metier.
|
|
50
157
|
|
|
51
|
-
For each module, execute
|
|
158
|
+
For each module (in topological order), execute the complete cycle below.
|
|
159
|
+
|
|
160
|
+
### Banniere de progression
|
|
161
|
+
|
|
162
|
+
Afficher au debut de chaque module :
|
|
163
|
+
```
|
|
164
|
+
═══════════════════════════════════════════════════════════════
|
|
165
|
+
MODULE {index}/{total} : {moduleName} ({applicationName})
|
|
166
|
+
═══════════════════════════════════════════════════════════════
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Execute these sub-steps for the current module:
|
|
52
170
|
|
|
53
171
|
### A. Context Loading
|
|
54
172
|
|
|
@@ -57,20 +175,26 @@ Load via ba-reader:
|
|
|
57
175
|
- Application `cadrage.json` for stakeholder context (including `_preAnalysis.domain_research`)
|
|
58
176
|
- Completed modules' summaries (compact, <100 lines each)
|
|
59
177
|
|
|
60
|
-
### A-bis.
|
|
178
|
+
### A-bis. Module Domain Research (MANDATORY for modules with >= 2 entities)
|
|
61
179
|
|
|
62
|
-
> **
|
|
180
|
+
> **MANDATORY — BLOCKING** pour les modules metier (>= 2 entites).
|
|
181
|
+
> SKIP ONLY: Portal (0 entites propres), config (1 entite reference pure).
|
|
63
182
|
> Uses domain_research from step-01 as baseline, then does targeted searches for this specific module.
|
|
183
|
+
> → **Load** `references/domain-research-playbook.md` Level 2 for per-module search strategy.
|
|
184
|
+
> Si WebSearch indisponible: s'appuyer sur `references/module-completeness-challenge.md` comme fallback.
|
|
64
185
|
|
|
65
186
|
```
|
|
66
|
-
IF
|
|
67
|
-
→
|
|
187
|
+
IF module is Portal OR (module has exactly 1 config/lookup entity):
|
|
188
|
+
→ SKIP WebSearch (use step-01 domain_research only)
|
|
68
189
|
ELSE:
|
|
69
|
-
|
|
190
|
+
SHOULD WebSearch: "{module_domain} entity data model best practices"
|
|
191
|
+
(e.g., "invoice entity design ERP", "timesheet data model best practices")
|
|
192
|
+
|
|
193
|
+
IF cadrage._preAnalysis.domain_research exists:
|
|
194
|
+
→ Load as baseline complement
|
|
70
195
|
|
|
71
|
-
FOR
|
|
196
|
+
OPTIONAL: FOR complex entities (max 1-2 additional searches):
|
|
72
197
|
Query: "{entity_name} entity design pattern {domain}"
|
|
73
|
-
(e.g., "invoice entity design ERP", "timesheet data model best practices")
|
|
74
198
|
|
|
75
199
|
EXTRACT (ULTRATHINK — internal only):
|
|
76
200
|
- Standard attributes for this entity type
|
|
@@ -89,163 +213,422 @@ FOR each main entity in this module (max 2-3 searches):
|
|
|
89
213
|
> If web research suggests putting firstName on Employee, the B-bis guard still blocks it
|
|
90
214
|
> because SmartStack uses auth_Users for personal data.
|
|
91
215
|
|
|
216
|
+
**TRACK 2 — Section & View Completeness (MANDATORY):**
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
WebSearch: "{module_domain} management system features views screens UX"
|
|
220
|
+
(e.g., "absence management system features views screens",
|
|
221
|
+
"invoice management application features views UX")
|
|
222
|
+
|
|
223
|
+
EXTRACT (ULTRATHINK — internal only):
|
|
224
|
+
- Standard views/sections for this module type
|
|
225
|
+
- Contextual filtered views (open requests, rejected, my X, history)
|
|
226
|
+
- Dashboard/reporting expectations
|
|
227
|
+
- Standard UX patterns (approval queue, batch actions, etc.)
|
|
228
|
+
|
|
229
|
+
CROSS-CHECK against anticipatedSections from step-02:
|
|
230
|
+
- List sections found in research but NOT in anticipatedSections
|
|
231
|
+
- For each missing section: prepare proposal for A-ter validation
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### A-ter. Section Completeness Validation (MANDATORY)
|
|
235
|
+
|
|
236
|
+
> **Ensure this module has all the sections a user would expect.**
|
|
237
|
+
> Workflow modules without contextual views (open-requests, rejected, history) are incomplete.
|
|
238
|
+
> → **Load** `references/module-completeness-challenge.md` for section archetypes per pattern.
|
|
239
|
+
|
|
240
|
+
Compare module's `anticipatedSections` against:
|
|
241
|
+
1. Domain research (Track 2 above)
|
|
242
|
+
2. Module archetype from `module-completeness-challenge.md`
|
|
243
|
+
3. Section archetypes per module pattern (workflow vs data-centric)
|
|
244
|
+
|
|
245
|
+
Display comparison table:
|
|
246
|
+
```
|
|
247
|
+
### Sections pour {moduleName}
|
|
248
|
+
|
|
249
|
+
| Section actuelle | Section standard (recherche/archetype) | Statut |
|
|
250
|
+
|-----------------|---------------------------------------|--------|
|
|
251
|
+
| list | list | ✓ OK |
|
|
252
|
+
| detail | detail | ✓ OK |
|
|
253
|
+
| approve | approve | ✓ OK |
|
|
254
|
+
| calendar | calendar | ✓ OK |
|
|
255
|
+
| — | open-requests | ✗ MANQUANTE — vue filtree des demandes en attente |
|
|
256
|
+
| — | rejected | ✗ MANQUANTE — vue filtree des demandes rejetees |
|
|
257
|
+
| — | history | ✗ MANQUANTE — historique des absences passees |
|
|
258
|
+
| — | my-balance | ✗ MANQUANTE — solde personnel de l'employe |
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
AskUserQuestion (multiSelect: true):
|
|
262
|
+
```
|
|
263
|
+
question: "{language == 'fr'
|
|
264
|
+
? 'Voici les sections standards trouvees pour un module {moduleType}. Quelles sections manquantes souhaitez-vous ajouter ?'
|
|
265
|
+
: 'Here are the standard sections found for a {moduleType} module. Which missing sections would you like to add?'}"
|
|
266
|
+
header: "Sections {moduleName}"
|
|
267
|
+
multiSelect: true
|
|
268
|
+
options:
|
|
269
|
+
- For each missing section: label: "{section_code}", description: "{description}"
|
|
270
|
+
- label: "{language == 'fr' ? 'Aucune' : 'None'}"
|
|
271
|
+
description: "{language == 'fr' ? 'Garder les sections actuelles' : 'Keep current sections'}"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Update `anticipatedSections` with accepted additions. For each added section:
|
|
275
|
+
- Determine `sectionType` (functional for filtered views, embedded for dashboards)
|
|
276
|
+
- Determine `permissionMode` (read-only for history/reporting, custom for approval queues)
|
|
277
|
+
- Add appropriate resources
|
|
278
|
+
|
|
92
279
|
### B. Entities
|
|
93
280
|
|
|
94
281
|
For each entity identified in step 02:
|
|
95
282
|
|
|
96
|
-
|
|
97
|
-
{
|
|
98
|
-
"name": "Employee",
|
|
99
|
-
"description": "Représente un employé de l'entreprise",
|
|
100
|
-
"personRoleConfig": { "variant": "mandatory", "userFields": ["firstName", "lastName", "email"] },
|
|
101
|
-
"attributes": [
|
|
102
|
-
{ "name": "code", "type": "string", "required": true, "description": "Identifiant unique auto-généré" },
|
|
103
|
-
{ "name": "userId", "type": "string", "required": true, "description": "FK vers auth_Users (ASP.NET Identity — type string, NOT guid)" },
|
|
104
|
-
{ "name": "departmentId", "type": "guid", "required": true, "description": "Département d'affectation" },
|
|
105
|
-
{ "name": "hireDate", "type": "date", "required": true, "description": "Date d'embauche" },
|
|
106
|
-
{ "name": "position", "type": "string", "description": "Poste occupé" },
|
|
107
|
-
{ "name": "status", "type": "enum", "options": ["Active", "Inactive", "OnLeave", "Terminated"], "defaultValue": "Active", "description": "Statut de l'employé" }
|
|
108
|
-
],
|
|
109
|
-
"versionedAttributes": [
|
|
110
|
-
{ "entity": "Salary", "attributes": ["grossAmount", "netAmount", "effectiveDate", "currency"], "reason": "Historique salarial versionné" }
|
|
111
|
-
],
|
|
112
|
-
"estimatedVolume": { "monthly": 50, "total2y": 1200 },
|
|
113
|
-
"searchableFields": ["code", "position", "status"],
|
|
114
|
-
"defaultFilters": ["status"],
|
|
115
|
-
"relationships": [
|
|
116
|
-
{ "target": "Department", "type": "ManyToOne", "description": "Appartient à un département" },
|
|
117
|
-
{ "target": "Contract", "type": "OneToMany", "description": "Possède plusieurs contrats" },
|
|
118
|
-
{ "target": "Salary", "type": "OneToMany", "description": "Historique de salaires versionnés" }
|
|
119
|
-
]
|
|
120
|
-
}
|
|
121
|
-
```
|
|
283
|
+
> → **Load** `references/03-json-schemas.md` section "Entity Schema Format" for the canonical JSON format.
|
|
122
284
|
|
|
123
285
|
### B-bis. SmartStack Entity Convention Guards (MANDATORY)
|
|
124
286
|
|
|
125
|
-
|
|
287
|
+
> → **Load** `references/03-smartstack-entity-guards.md` for all convention rules before finalizing each entity.
|
|
288
|
+
|
|
289
|
+
### B-ter. Client Validation — Entities (OBLIGATOIRE)
|
|
290
|
+
|
|
291
|
+
**Mode : Auto-déduction + Confirmation groupée**
|
|
292
|
+
|
|
293
|
+
> L'IA propose les entités basées sur le cadrage + recherche domaine (A-bis).
|
|
294
|
+
> Le client valide PAR LOT au lieu de répondre aux questions individuellement.
|
|
295
|
+
> Les questions détaillées (Q3.1-Q3.5) ne sont posées QUE si le cadrage est ambigu.
|
|
296
|
+
|
|
297
|
+
1. **Construire la proposition d'entités** à partir de :
|
|
298
|
+
- `cadrage.json` (coverageMatrix, stakeholders, globalScope)
|
|
299
|
+
- Recherche domaine (A-bis : standard attributes, versioning patterns)
|
|
300
|
+
- Modules déjà spécifiés (dépendances, entités partagées)
|
|
301
|
+
|
|
302
|
+
2. **Présenter la proposition COMPLÈTE** (markdown PUIS AskUserQuestion) :
|
|
303
|
+
```
|
|
304
|
+
### Entités proposées pour {moduleName}
|
|
305
|
+
|
|
306
|
+
| Entité | Attributs clés | Relations | Volume estimé |
|
|
307
|
+
|--------|---------------|-----------|---------------|
|
|
308
|
+
| {entity} | {top 5 attrs with flags} | {relations} | {monthly/total} |
|
|
309
|
+
```
|
|
310
|
+
AskUserQuestion : "Voici les entités que je propose pour {moduleName}. Corrections ?"
|
|
311
|
+
|
|
312
|
+
3. SI le client corrige → intégrer et re-présenter
|
|
313
|
+
4. SI le client valide → continuer vers C
|
|
314
|
+
|
|
315
|
+
5. **SI le cadrage est ambigu** sur un point spécifique → poser la question ciblée :
|
|
316
|
+
- Q3.1 si les entités ne sont pas claires
|
|
317
|
+
- Q3.5 si la stratégie de code est ambiguë
|
|
126
318
|
|
|
127
|
-
|
|
128
|
-
IF the entity matches a person role (Employee, Customer, Manager, Consultant, etc.):
|
|
129
|
-
- **DO NOT** add firstName, lastName, email, phoneNumber as direct attributes
|
|
130
|
-
- **DO** add `userId` (type: `string`, FK to auth_Users — ASP.NET Identity uses string IDs)
|
|
131
|
-
- **DO** add `personRoleConfig` metadata with variant (mandatory/optional)
|
|
132
|
-
- Personal fields come from User, not from the domain entity
|
|
319
|
+
6. APRES validation entites, AVANT passage aux regles (C) — poser en 2 batches max :
|
|
133
320
|
|
|
134
|
-
**
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
- **DO** extract into a versioned satellite table (e.g., Employee → Salary with effectiveDate)
|
|
138
|
-
- Mark with `"versionedAttributes"` in entity spec
|
|
321
|
+
**Batch recherche/filtres** (Q3.19 + Q3.20) :
|
|
322
|
+
- Q3.19 : "Par quels criteres cherchez-vous un {entite} ? (nom, date, statut, code...)"
|
|
323
|
+
- Q3.20 : "Quels filtres rapides sont indispensables dans la liste ?"
|
|
139
324
|
|
|
140
|
-
**
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
- Departments → `ref_Departments` or `rh_Departments` (check if exists in target DB)
|
|
325
|
+
**RACCOURCI module 3+ :** Proposer "Meme logique de recherche/filtres que {module_precedent} ?"
|
|
326
|
+
→ Si le client confirme, copier searchableFields et defaultFilters du module precedent.
|
|
327
|
+
→ Sinon, poser les questions normalement.
|
|
144
328
|
|
|
145
|
-
**
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
- FK to domain entities MUST use type `guid`
|
|
329
|
+
**SKIP si:** module Portal (pas d'entites propres) ou module config (filtres evidents : name, code).
|
|
330
|
+
|
|
331
|
+
INTERDICTION de passer à C (Business Rules) tant que le client n'a pas validé les entités ET les champs recherche/filtres.
|
|
149
332
|
|
|
150
333
|
### C. Business Rules
|
|
151
334
|
|
|
152
335
|
For each entity/process, identify rules. **Each rule MUST specify `sectionCode`** matching a code from `anticipatedSections[]`:
|
|
153
336
|
|
|
154
|
-
|
|
155
|
-
{
|
|
156
|
-
"id": "BR-VAL-EMPLOYEES-001",
|
|
157
|
-
"name": "Validation date embauche",
|
|
158
|
-
"category": "validation",
|
|
159
|
-
"sectionCode": "list",
|
|
160
|
-
"statement": "La date d'embauche ne peut pas être dans le futur",
|
|
161
|
-
"example": "Date embauche = 2027-01-01 → erreur car > date du jour",
|
|
162
|
-
"entities": ["Employee"],
|
|
163
|
-
"severity": "blocking"
|
|
164
|
-
}
|
|
165
|
-
```
|
|
337
|
+
> → **Load** `references/03-json-schemas.md` section "Business Rules Schema Format" for the canonical JSON format and all validation requirements.
|
|
166
338
|
|
|
167
|
-
|
|
339
|
+
### C-pre. Business Rules Domain Research (MANDATORY for workflow modules)
|
|
168
340
|
|
|
169
|
-
> **
|
|
341
|
+
> **Domain-specific business rules are what separate a 2/10 analysis from a 9/10 analysis.**
|
|
342
|
+
> Generic rules (date coherence, required fields) are the MINIMUM. Domain rules are the VALUE.
|
|
343
|
+
> → **Load** `references/module-completeness-challenge.md` for domain-specific rule examples.
|
|
170
344
|
|
|
171
|
-
|
|
345
|
+
```
|
|
346
|
+
IF module has workflow states OR approval patterns:
|
|
347
|
+
WebSearch: "{module_domain} business rules constraints validation best practices"
|
|
348
|
+
(e.g., "absence leave management business rules HR constraints",
|
|
349
|
+
"invoice billing business rules validation constraints",
|
|
350
|
+
"CRM opportunity management business rules")
|
|
172
351
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
352
|
+
EXTRACT (ULTRATHINK — internal only):
|
|
353
|
+
- Domain-specific validation rules (NOT just date coherence / required fields)
|
|
354
|
+
- Calculation rules with formulas
|
|
355
|
+
- Workflow constraints (capacity limits, notice periods, deadlines)
|
|
356
|
+
- Edge cases (half-day, probation, carry-over, expiry, partial payments)
|
|
357
|
+
- Regulatory constraints (legal leave types, mandatory approvals, numbering)
|
|
358
|
+
- Separation of duties rules (cannot approve own request)
|
|
359
|
+
|
|
360
|
+
CROSS-CHECK proposed rules (from B-ter entity analysis):
|
|
361
|
+
For each rule found in research but NOT already proposed:
|
|
362
|
+
→ Add to proposal with source: "domain-research"
|
|
363
|
+
→ Category: detected category (VAL, CALC, WF, SEC, DATA)
|
|
364
|
+
→ Mark with domainSpecific: true
|
|
365
|
+
|
|
366
|
+
Example enrichments for Absences module:
|
|
367
|
+
Current generic rules: date coherence, no overlap, balance check, workflow transitions
|
|
368
|
+
Research-based additions:
|
|
369
|
+
- BR-VAL-ABS-004: "Half-day absence (morning/afternoon)" [domainSpecific]
|
|
370
|
+
- BR-VAL-ABS-005: "Minimum 48h notice for planned absences" [domainSpecific]
|
|
371
|
+
- BR-VAL-ABS-006: "Max 30% of team can be absent simultaneously" [domainSpecific]
|
|
372
|
+
- BR-VAL-ABS-007: "Restricted leave types during probation period" [domainSpecific]
|
|
373
|
+
- BR-DATA-ABS-001: "Carry-over days expire after March 31" [domainSpecific]
|
|
374
|
+
- BR-VAL-ABS-008: "Medical certificate required for absences > 3 days" [domainSpecific]
|
|
375
|
+
- BR-SEC-ABS-001: "Manager cannot approve their own absences" [domainSpecific]
|
|
376
|
+
|
|
377
|
+
ELSE (non-workflow module with >= 2 entities):
|
|
378
|
+
SHOULD WebSearch: "{module_domain} data validation rules best practices"
|
|
379
|
+
→ Use entity patterns from A-bis for validation rules
|
|
380
|
+
→ Load archetype rules from module-completeness-challenge.md
|
|
381
|
+
→ For each archetype rule relevant to this module type, ADD to proposal
|
|
382
|
+
→ Mark rules from research with domainSpecific: true
|
|
182
383
|
```
|
|
183
384
|
|
|
385
|
+
### C-bis. Client Validation — Business Rules (OBLIGATOIRE)
|
|
386
|
+
|
|
387
|
+
**Mode : Auto-déduction + Confirmation groupée**
|
|
388
|
+
|
|
389
|
+
1. **Construire les règles métier** à partir de :
|
|
390
|
+
- Entités validées en B-ter (attributs, types, contraintes)
|
|
391
|
+
- Patterns domaine (A-bis) : validations standards, calculs attendus
|
|
392
|
+
- Cadrage : errorFlows, processus décrits
|
|
393
|
+
|
|
394
|
+
> **Schema:** ALL fields defined in `schemas/sections/analysis-schema.json` property `businessRules`. Use EXACT canonical field names (`id`, `name`, `category`, `statement`, `severity`, `entities`, `examples`, `sectionCode`, `domainSpecific`).
|
|
395
|
+
|
|
396
|
+
**ENRICHISSEMENT OBLIGATOIRE pour chaque règle :**
|
|
397
|
+
|
|
398
|
+
Pour chaque BR proposée, inclure ces champs :
|
|
399
|
+
- `severity` : TOUJOURS spécifier (blocking/warning/info)
|
|
400
|
+
- `sectionCode` : TOUJOURS spécifier (section où la règle s'applique)
|
|
401
|
+
- `examples[]` : OBLIGATOIRE — format **test-ready** `{scenario, description, given, when, then}`
|
|
402
|
+
Chaque exemple est un **jeu de test** avec des valeurs concrètes (pas de prose).
|
|
403
|
+
Minimum **2 exemples** par règle : `happy_path` + `error` (ou `calculation` + `boundary`).
|
|
404
|
+
|
|
405
|
+
**Format par catégorie :**
|
|
406
|
+
- `validation` :
|
|
407
|
+
```json
|
|
408
|
+
{ "scenario": "happy_path", "description": "Code unique accepté",
|
|
409
|
+
"given": { "Employee.code": "EMP-00042", "existingCodes": [] },
|
|
410
|
+
"when": "create",
|
|
411
|
+
"then": { "result": "success" } }
|
|
412
|
+
{ "scenario": "error", "description": "Code dupliqué rejeté",
|
|
413
|
+
"given": { "Employee.code": "EMP-00001", "existingCodes": ["EMP-00001"] },
|
|
414
|
+
"when": "create",
|
|
415
|
+
"then": { "result": "error", "message": "Code déjà existant", "field": "code" } }
|
|
416
|
+
```
|
|
417
|
+
- `calculation` :
|
|
418
|
+
```json
|
|
419
|
+
{ "scenario": "calculation", "description": "Solde avec report",
|
|
420
|
+
"given": { "AbsenceBalance.entitled": 25, "AbsenceBalance.carriedForward": 3, "AbsenceBalance.taken": 12 },
|
|
421
|
+
"when": "calculate_remaining",
|
|
422
|
+
"then": { "AbsenceBalance.remaining": 16, "formula": "25 + 3 - 12 = 16" } }
|
|
423
|
+
{ "scenario": "boundary", "description": "Solde à zéro",
|
|
424
|
+
"given": { "AbsenceBalance.entitled": 10, "AbsenceBalance.carriedForward": 0, "AbsenceBalance.taken": 10 },
|
|
425
|
+
"when": "calculate_remaining",
|
|
426
|
+
"then": { "AbsenceBalance.remaining": 0 } }
|
|
427
|
+
```
|
|
428
|
+
- `workflow` :
|
|
429
|
+
```json
|
|
430
|
+
{ "scenario": "happy_path", "description": "Transition Draft→Submitted",
|
|
431
|
+
"given": { "Absence.status": "Draft" },
|
|
432
|
+
"when": "submit",
|
|
433
|
+
"then": { "Absence.status": "Submitted", "result": "success" } }
|
|
434
|
+
{ "scenario": "error", "description": "Transition interdite Approved→Draft",
|
|
435
|
+
"given": { "Absence.status": "Approved" },
|
|
436
|
+
"when": "submit",
|
|
437
|
+
"then": { "result": "error", "message": "Transition non autorisée" } }
|
|
438
|
+
```
|
|
439
|
+
- `security` :
|
|
440
|
+
```json
|
|
441
|
+
{ "scenario": "happy_path", "description": "Admin accède à toutes les fiches",
|
|
442
|
+
"given": { "user.role": "RH Admin", "Employee.departmentId": "any" },
|
|
443
|
+
"when": "read",
|
|
444
|
+
"then": { "result": "success", "scope": "all" } }
|
|
445
|
+
{ "scenario": "error", "description": "Employé accède uniquement à sa fiche",
|
|
446
|
+
"given": { "user.role": "Employé", "target.employeeId": "other-user" },
|
|
447
|
+
"when": "read",
|
|
448
|
+
"then": { "result": "error", "message": "Accès limité à votre fiche" } }
|
|
449
|
+
```
|
|
450
|
+
**Fallback** : `{input, expected}` accepté mais marqué WARNING "format non test-ready".
|
|
451
|
+
- `conditions[]` : OBLIGATOIRE pour les règles conditionnelles (IF/THEN) — structuré `{entity, field, operator, value}`
|
|
452
|
+
Ex: `[{ entity: "Absence", field: "type", operator: "==", value: "Maladie" }, { entity: "Absence", field: "duration", operator: ">", value: 3 }]`
|
|
453
|
+
- `consequences[]` : OBLIGATOIRE pour les règles avec effets de bord
|
|
454
|
+
Ex: `[{ type: "notification", target: "RH Manager", description: "Certificat médical requis" }]`
|
|
455
|
+
- `formula` : OBLIGATOIRE pour les BR-CALC
|
|
456
|
+
- `domainSpecific: true` si la règle vient de la recherche domaine (C-pre)
|
|
457
|
+
|
|
458
|
+
**Minimums par module métier (hors Portal/config) :**
|
|
459
|
+
- 100% des règles avec `examples[]` non vide (minimum 2 par règle : happy_path + error)
|
|
460
|
+
- >= 4 règles avec exemples test-ready `{scenario, given, when, then}`
|
|
461
|
+
- >= 2 règles avec `conditions[]` structurés
|
|
462
|
+
- >= 1 règle avec `consequences[]`
|
|
463
|
+
- Toute BR-CALC avec un exemple `calculation` contenant des valeurs numériques chiffrées
|
|
464
|
+
|
|
465
|
+
**Self-check AVANT présentation client :**
|
|
466
|
+
```
|
|
467
|
+
domainCount = rules.filter(r => r.domainSpecific === true).length
|
|
468
|
+
IF domainCount < 2 AND module is NOT config/lookup/Portal:
|
|
469
|
+
SELF-CHECK: "Only {domainCount} domain-specific rules."
|
|
470
|
+
→ Re-examine module-completeness-challenge.md archetypes for this module type
|
|
471
|
+
→ Add at least 2 domain-specific rules before presenting to client
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
2. **Présenter le LOT complet** (markdown PUIS AskUserQuestion) :
|
|
475
|
+
```
|
|
476
|
+
### Règles métier proposées pour {moduleName}
|
|
477
|
+
|
|
478
|
+
| ID | Catégorie | Règle | Sévérité |
|
|
479
|
+
|----|-----------|-------|----------|
|
|
480
|
+
| BR-VAL-... | validation | {statement} | blocking |
|
|
481
|
+
| BR-CALC-... | calculation | {statement} (formula: {formula}) | blocking |
|
|
482
|
+
```
|
|
483
|
+
AskUserQuestion : "Voici les {N} règles métier pour {moduleName}. Manques/corrections ?"
|
|
484
|
+
|
|
485
|
+
3. SI le cadrage est ambigu → poser les questions ciblées :
|
|
486
|
+
- Q3.7 si les validations ne sont pas claires
|
|
487
|
+
- Q3.8 si les relations inter-champs sont complexes
|
|
488
|
+
- Q3.9 si les données sensibles ne sont pas identifiées
|
|
489
|
+
|
|
490
|
+
4. **POST-VALIDATION : Qualité test-ready des exemples (OBLIGATOIRE)**
|
|
491
|
+
|
|
492
|
+
Après validation client des règles métier, vérifier la qualité des exemples AVANT écriture :
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
// 1. Règles sans aucun exemple
|
|
496
|
+
const rulesWithoutExamples = module.rules.filter(r =>
|
|
497
|
+
!r.examples || r.examples.length === 0
|
|
498
|
+
);
|
|
499
|
+
if (rulesWithoutExamples.length > 0) {
|
|
500
|
+
// Auto-générer des exemples test-ready à partir du statement et des conditions
|
|
501
|
+
for (const rule of rulesWithoutExamples) {
|
|
502
|
+
rule.examples = generateTestReadyExamples(rule);
|
|
503
|
+
// Génère minimum: 1 happy_path + 1 error avec given/when/then
|
|
504
|
+
}
|
|
505
|
+
Display(`${rulesWithoutExamples.length} règle(s) complétée(s) avec exemples test-ready auto-générés.`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// 2. Règles avec exemples en prose (ancien format {input, expected} sans given/when/then)
|
|
509
|
+
const proseExamples = module.rules.filter(r =>
|
|
510
|
+
r.examples?.length > 0 && !r.examples.some(e => e.given && e.when && e.then)
|
|
511
|
+
);
|
|
512
|
+
if (proseExamples.length > 0) {
|
|
513
|
+
// Convertir les exemples prose en format test-ready
|
|
514
|
+
for (const rule of proseExamples) {
|
|
515
|
+
rule.examples = rule.examples.map(e => convertToTestReady(e, rule));
|
|
516
|
+
}
|
|
517
|
+
Display(`${proseExamples.length} règle(s) converties du format prose au format test-ready.`);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// 3. BR-CALC sans exemple chiffré
|
|
521
|
+
const calcWithoutNumbers = module.rules.filter(r =>
|
|
522
|
+
r.category === 'calculation' &&
|
|
523
|
+
!r.examples?.some(e => e.scenario === 'calculation' || (e.then && Object.values(e.then).some(v => typeof v === 'number')))
|
|
524
|
+
);
|
|
525
|
+
if (calcWithoutNumbers.length > 0) {
|
|
526
|
+
Display(`⚠ ${calcWithoutNumbers.length} BR-CALC sans exemple chiffré — ajouter des valeurs numériques.`);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// 4. Vérification minimale
|
|
530
|
+
const testReady = module.rules.filter(r =>
|
|
531
|
+
r.examples?.some(e => e.given && e.when && e.then)
|
|
532
|
+
);
|
|
533
|
+
if (testReady.length < 4 && module.featureType !== 'portal') {
|
|
534
|
+
Display(`⚠ ${testReady.length}/4 règles au format test-ready {given, when, then}. Enrichir.`);
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**Minimum requis par module métier (hors Portal/config) :**
|
|
539
|
+
- 100% des règles avec `examples[]` non vide (minimum 2 par règle)
|
|
540
|
+
- >= 4 règles avec exemples test-ready `{scenario, given, when, then}`
|
|
541
|
+
- Toute BR-CALC avec un exemple `calculation` contenant des valeurs numériques
|
|
542
|
+
- Zéro exemple en prose vague (tout doit être en format `given/when/then`)
|
|
543
|
+
|
|
544
|
+
INTERDICTION de passer à D (Use Cases) tant que le client n'a pas validé les règles.
|
|
545
|
+
|
|
184
546
|
### D. Use Cases
|
|
185
547
|
|
|
186
|
-
|
|
548
|
+
> **Note (v3) :** Les questions parcours/decisions/erreurs (ex-Q2.16-Q2.18) sont desormais capturees ICI
|
|
549
|
+
> lors de la specification des use cases, et non plus en step-01 cadrage. Cela evite la duplication
|
|
550
|
+
> et produit des donnees directement exploitables par module.
|
|
187
551
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
>
|
|
191
|
-
>
|
|
192
|
-
> - Alternatives: `"alternativeScenarios"` (object[] with `{name, steps}`, NOT "alternative" as flat string)
|
|
193
|
-
> - This matches specification-schema.json. Deviation causes normalization overhead in 4+ downstream skills.
|
|
552
|
+
**D-pre. Capture du parcours utilisateur (1 question par module si pertinent)**
|
|
553
|
+
|
|
554
|
+
> Avant de construire les UCs, comprendre le parcours type pour CE module.
|
|
555
|
+
> SKIP si le module est un module config/lookup ou Portal (pas de parcours propre).
|
|
194
556
|
|
|
195
|
-
```json
|
|
196
|
-
{
|
|
197
|
-
"useCases": [
|
|
198
|
-
{
|
|
199
|
-
"id": "UC-EMPLOYEES-001",
|
|
200
|
-
"name": "Créer un employé",
|
|
201
|
-
"sectionCode": "list",
|
|
202
|
-
"primaryActor": "Responsable RH",
|
|
203
|
-
"preconditions": ["L'utilisateur a la permission HumanResources.Employees.Create"],
|
|
204
|
-
"mainScenario": [
|
|
205
|
-
"L'utilisateur ouvre la page de création",
|
|
206
|
-
"Il remplit les champs obligatoires (nom, département, date embauche)",
|
|
207
|
-
"Il valide le formulaire",
|
|
208
|
-
"Le système vérifie les règles métier (BR-VAL-EMPLOYEES-001)",
|
|
209
|
-
"Le système crée l'employé et affiche la fiche"
|
|
210
|
-
],
|
|
211
|
-
"alternativeScenarios": [
|
|
212
|
-
{
|
|
213
|
-
"name": "Données invalides",
|
|
214
|
-
"steps": ["Le système affiche les erreurs de validation", "L'utilisateur corrige et re-soumet"]
|
|
215
|
-
}
|
|
216
|
-
],
|
|
217
|
-
"businessRules": ["BR-VAL-EMPLOYEES-001"],
|
|
218
|
-
"result": "L'employé est créé avec le statut 'Actif'"
|
|
219
|
-
}
|
|
220
|
-
]
|
|
221
|
-
}
|
|
222
557
|
```
|
|
558
|
+
IF module is NOT config/lookup AND NOT Portal:
|
|
559
|
+
AskUserQuestion (1 question):
|
|
560
|
+
"{language == 'fr'
|
|
561
|
+
? 'Pour le module {moduleName} : décrivez le parcours typique. L\'utilisateur arrive, que fait-il ? Quand quelque chose ne se passe pas comme prévu, que se passe-t-il ?'
|
|
562
|
+
: 'For the {moduleName} module: describe the typical journey. The user arrives, what do they do? When something doesn't go as planned, what happens?'}"
|
|
563
|
+
|
|
564
|
+
Record answer as:
|
|
565
|
+
- mainScenario steps → feed UC mainScenario
|
|
566
|
+
- decision points → feed UC alternativeScenarios
|
|
567
|
+
- error cases → feed UC errorScenarios + BR-WF rules
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
For each stakeholder action. **Each use case MUST specify `sectionCode`** matching a code from `anticipatedSections[]` — this links the UC to the screen/page where it happens:
|
|
571
|
+
|
|
572
|
+
> → **Load** `references/03-json-schemas.md` section "Use Cases Schema Format" for the canonical JSON format.
|
|
223
573
|
|
|
224
574
|
### E. Permissions
|
|
225
575
|
|
|
226
576
|
Define the permission matrix:
|
|
227
577
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
"HumanResources.Employees.Export"
|
|
242
|
-
]
|
|
243
|
-
}
|
|
244
|
-
```
|
|
578
|
+
> → **Load** `references/03-json-schemas.md` section "Permissions Schema Format" for the canonical JSON format.
|
|
579
|
+
|
|
580
|
+
### E-bis. Notifications et Dashboards (OBLIGATOIRE)
|
|
581
|
+
|
|
582
|
+
> **Regle : 2 questions max par AskUserQuestion.**
|
|
583
|
+
|
|
584
|
+
**Batch E-bis-1** — Notifications :
|
|
585
|
+
- Q3.21 : "Quels evenements doivent declencher une notification dans {moduleName} ?"
|
|
586
|
+
- Q3.22 : "Qui doit etre notifie ? Par quel canal ? (in-app, email)" (conditionnel si Q3.21 = oui)
|
|
587
|
+
|
|
588
|
+
**Batch E-bis-2** — Dashboards (SI pertinent pour ce module) :
|
|
589
|
+
- Q3.14 : "Des tableaux de bord ou indicateurs sont-ils requis ?"
|
|
590
|
+
- Q3.15 : "Si oui, quels KPIs afficher ?" (conditionnel si Q3.14 = oui)
|
|
245
591
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
592
|
+
### E-ter. Client Validation — Use Cases & Permissions (OBLIGATOIRE)
|
|
593
|
+
|
|
594
|
+
**Mode : Auto-déduction + Confirmation groupée**
|
|
595
|
+
|
|
596
|
+
1. **Construire UCs et permissions** à partir des entités + règles validées :
|
|
597
|
+
- CRUD UCs dérivés des entités (Create, Read, Update, Delete)
|
|
598
|
+
- Export UC si cadrage mentionne export/Excel/CSV
|
|
599
|
+
- Import UC si cadrage mentionne import/upload
|
|
600
|
+
- Workflow UCs si entité a des états (enum status)
|
|
601
|
+
|
|
602
|
+
**ENRICHISSEMENT OBLIGATOIRE pour chaque Use Case :**
|
|
603
|
+
|
|
604
|
+
Pour chaque UC proposé, inclure ces champs :
|
|
605
|
+
- `postconditions[]` : OBLIGATOIRE — effets après le UC
|
|
606
|
+
Ex: `["Absence.status = Approved", "AbsenceBalance.taken += duration", "Notification envoyee a l'employe"]`
|
|
607
|
+
- `errorScenarios[]` : OBLIGATOIRE pour les UCs workflow (>= 1 par UC workflow)
|
|
608
|
+
Ex: `{ name: "Solde insuffisant", steps: ["Systeme affiche le solde restant", "Systeme bloque la soumission", "Employe peut modifier les dates"] }`
|
|
609
|
+
- `mainScenario[]` : MINIMUM 5 steps pour les UCs workflow (3 suffisent pour list/read)
|
|
610
|
+
- `alternativeScenarios[]` : MINIMUM 1 pour les UCs avec branchements
|
|
611
|
+
|
|
612
|
+
**Minimums par module métier :**
|
|
613
|
+
- >= 3 UCs avec `errorScenarios[]` non vides
|
|
614
|
+
- >= 4 UCs avec `postconditions[]` non vides
|
|
615
|
+
- Moyenne mainScenario >= 4 steps
|
|
616
|
+
|
|
617
|
+
2. **Présenter les deux lots en 1 seule interaction** (markdown PUIS AskUserQuestion) :
|
|
618
|
+
```
|
|
619
|
+
### Use Cases proposés pour {moduleName}
|
|
620
|
+
| ID | Nom | Acteur | Règles liées |
|
|
621
|
+
...
|
|
622
|
+
|
|
623
|
+
### Permissions proposées
|
|
624
|
+
| Rôle | Permissions |
|
|
625
|
+
...
|
|
626
|
+
```
|
|
627
|
+
AskUserQuestion : "Voici les UCs et permissions pour {moduleName}. Corrections ?"
|
|
628
|
+
|
|
629
|
+
3. SI le cadrage est ambigu → poser les questions ciblées du lot E-bis (notifications, dashboards)
|
|
630
|
+
|
|
631
|
+
INTERDICTION de passer à F (Seed Data) / H (Write) tant que le client n'a pas validé use cases ET permissions.
|
|
249
632
|
|
|
250
633
|
### F. Seed Data pour tables de référence
|
|
251
634
|
|
|
@@ -265,13 +648,288 @@ Define the permission matrix:
|
|
|
265
648
|
}
|
|
266
649
|
```
|
|
267
650
|
|
|
651
|
+
### F-bis. LifeCycle State Machine (MANDATORY for workflow entities)
|
|
652
|
+
|
|
653
|
+
> Les lifeCycles sont déjà dans le schema (`specification-schema.json` l.317-383).
|
|
654
|
+
> Ils doivent être générés pour CHAQUE entité ayant un attribut status de type enum.
|
|
655
|
+
> Ces données alimentent les diagrammes d'état Mermaid ET le code généré.
|
|
656
|
+
|
|
657
|
+
Pour CHAQUE entité avec attribut `type: "enum"` contenant "status" dans ses `options[]` :
|
|
658
|
+
|
|
659
|
+
1. Extraire les états depuis `options[]` de l'attribut enum
|
|
660
|
+
2. Identifier les transitions depuis les règles BR-WF-*
|
|
661
|
+
3. Lier chaque transition à :
|
|
662
|
+
- `permission` : depuis permissions.json
|
|
663
|
+
- `guards[]` : BR-VAL-* qui doivent passer avant la transition
|
|
664
|
+
- `effects[]` : BR-NOTIF-* et BR-CALC-* déclenchées par la transition
|
|
665
|
+
|
|
666
|
+
Générer le `lifeCycle` complet :
|
|
667
|
+
```json
|
|
668
|
+
{
|
|
669
|
+
"entity": "Absence",
|
|
670
|
+
"field": "status",
|
|
671
|
+
"initialState": "Draft",
|
|
672
|
+
"states": [
|
|
673
|
+
{ "id": "Draft", "displayName": "Brouillon", "color": "gray", "allowedTransitions": ["Submitted"], "isTerminal": false },
|
|
674
|
+
{ "id": "Submitted", "displayName": "Soumis", "color": "blue", "allowedTransitions": ["Approved", "Rejected"], "isTerminal": false },
|
|
675
|
+
{ "id": "Approved", "displayName": "Approuvé", "color": "green", "allowedTransitions": [], "isTerminal": true },
|
|
676
|
+
{ "id": "Rejected", "displayName": "Refusé", "color": "red", "allowedTransitions": [], "isTerminal": true }
|
|
677
|
+
],
|
|
678
|
+
"transitions": [
|
|
679
|
+
{ "from": "Draft", "to": "Submitted", "action": "submit", "permission": "Rh.Absences.Create",
|
|
680
|
+
"guards": ["BR-VAL-ABS-001", "BR-VAL-ABS-002", "BR-VAL-ABS-003"],
|
|
681
|
+
"effects": [{ "type": "notification", "target": "RH Manager", "template": "absence-submitted" }] },
|
|
682
|
+
{ "from": "Submitted", "to": "Approved", "action": "approve", "permission": "Rh.Absences.Approve",
|
|
683
|
+
"guards": [],
|
|
684
|
+
"effects": [
|
|
685
|
+
{ "type": "field-update", "target": "AbsenceBalance.taken", "template": "+= duration" },
|
|
686
|
+
{ "type": "notification", "target": "employee", "template": "absence-approved" }
|
|
687
|
+
] }
|
|
688
|
+
]
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Présenter le lifecycle au client dans le lot E-ter (avec UCs et permissions).
|
|
693
|
+
|
|
694
|
+
**Écriture :** Stocker dans `usecases.json` sous la clé `lifeCycles[]` (déjà dans le schema).
|
|
695
|
+
|
|
696
|
+
### F-ter. Gherkin Auto-Generation from Enriched UCs (MANDATORY)
|
|
697
|
+
|
|
698
|
+
> **Les Gherkin doivent être DERIVES des UCs enrichis, pas inventés séparément.**
|
|
699
|
+
> Chaque `mainScenario` → 1 Gherkin happy path.
|
|
700
|
+
> Chaque `errorScenario` → 1 Gherkin error path.
|
|
701
|
+
> Chaque `alternativeScenario` → 1 Gherkin alternative path.
|
|
702
|
+
> Les `examples[]{input, expected}` des BRs alimentent les `Examples:` tables Gherkin.
|
|
703
|
+
|
|
704
|
+
**Process :**
|
|
705
|
+
|
|
706
|
+
```
|
|
707
|
+
For EACH UC in module:
|
|
708
|
+
// 1. Happy path from mainScenario + postconditions
|
|
709
|
+
Generate Gherkin:
|
|
710
|
+
Feature: {UC.name}
|
|
711
|
+
Scenario: {UC.name} - happy path
|
|
712
|
+
Given {UC.preconditions[] joined as Given/And}
|
|
713
|
+
When {UC.mainScenario[] mapped to When/And steps}
|
|
714
|
+
Then {UC.postconditions[] mapped to Then/And assertions}
|
|
715
|
+
|
|
716
|
+
// 2. Error paths from errorScenarios
|
|
717
|
+
For EACH errorScenario in UC.errorScenarios:
|
|
718
|
+
Scenario: {UC.name} - {errorScenario.name}
|
|
719
|
+
Given {UC.preconditions[] + error setup conditions}
|
|
720
|
+
When {trigger action from mainScenario step 1}
|
|
721
|
+
Then {errorScenario.steps[] mapped to Then/And}
|
|
722
|
+
|
|
723
|
+
// 3. Alternative paths from alternativeScenarios
|
|
724
|
+
For EACH alt in UC.alternativeScenarios:
|
|
725
|
+
Scenario: {UC.name} - {alt.name}
|
|
726
|
+
Given {modified preconditions}
|
|
727
|
+
When {alt trigger}
|
|
728
|
+
Then {alt.steps[] mapped to Then/And}
|
|
729
|
+
|
|
730
|
+
// 4. Data-driven examples from linked BR examples
|
|
731
|
+
IF UC.linkedRules references BRs with structured examples[]:
|
|
732
|
+
Scenario Outline: {UC.name} - validation rules
|
|
733
|
+
Given a {entity} with <field> = <value>
|
|
734
|
+
When the user submits the form
|
|
735
|
+
Then the system shows <expected>
|
|
736
|
+
Examples:
|
|
737
|
+
| field | value | expected |
|
|
738
|
+
{for each BR example: | {input} | {expected} |}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
**Exemple concret (Absence - Soumission) :**
|
|
742
|
+
|
|
743
|
+
```gherkin
|
|
744
|
+
Feature: Soumettre une demande d'absence (UC-ABS-001)
|
|
745
|
+
|
|
746
|
+
Scenario: Soumission reussie
|
|
747
|
+
Given un employe avec la permission Rh.Absences.Create
|
|
748
|
+
And un solde de CP >= duree demandee
|
|
749
|
+
When il selectionne le type CP, dates 15/03 au 19/03
|
|
750
|
+
And le systeme calcule la duree en jours ouvres (5j)
|
|
751
|
+
And le systeme verifie les dates, chevauchements et solde
|
|
752
|
+
And il soumet la demande
|
|
753
|
+
Then Absence.status = Submitted
|
|
754
|
+
And AbsenceBalance.taken reste inchange (pas encore approuve)
|
|
755
|
+
And notification envoyee au RH Manager
|
|
756
|
+
|
|
757
|
+
Scenario: Soumission echouee - solde insuffisant
|
|
758
|
+
Given un employe avec 2 jours de CP restants
|
|
759
|
+
When il soumet une absence de 5 jours de type CP
|
|
760
|
+
Then le systeme affiche le solde restant (2 jours)
|
|
761
|
+
And la soumission est bloquee
|
|
762
|
+
|
|
763
|
+
Scenario: Soumission echouee - chevauchement
|
|
764
|
+
Given un employe avec une absence approuvee du 15/03 au 19/03
|
|
765
|
+
When il soumet une absence du 17/03 au 21/03
|
|
766
|
+
Then le systeme affiche l'absence existante en conflit
|
|
767
|
+
And la soumission est bloquee
|
|
768
|
+
|
|
769
|
+
Scenario Outline: Validation des dates
|
|
770
|
+
Given un employe connecte
|
|
771
|
+
When il saisit debut=<debut> fin=<fin>
|
|
772
|
+
Then le systeme affiche <resultat>
|
|
773
|
+
Examples:
|
|
774
|
+
| debut | fin | resultat |
|
|
775
|
+
| 15/03 | 12/03 | Erreur : date de fin avant date de debut |
|
|
776
|
+
| 15/03 | 15/03 | OK (1 jour) |
|
|
777
|
+
| 15/03 | 19/03 | OK (5 jours ouvres) |
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
**Minimums :** >= 3 scnarios Gherkin par module mtier (1 happy + 2 error/alt minimum).
|
|
781
|
+
|
|
782
|
+
**criture :** Stocker dans `usecases.json` sous la cl `gherkinScenarios[]`.
|
|
783
|
+
|
|
784
|
+
### F-quater. Field-Level Validations Auto-Generation (MANDATORY)
|
|
785
|
+
|
|
786
|
+
> **Gnrer les validations field-level depuis les attributs d'entits + rgles mtier.**
|
|
787
|
+
> Ces validations alimentent directement les validators frontend (FluentValidation backend + form validation frontend).
|
|
788
|
+
|
|
789
|
+
```
|
|
790
|
+
For EACH entity in module:
|
|
791
|
+
For EACH attribute in entity.attributes:
|
|
792
|
+
|
|
793
|
+
validations = []
|
|
794
|
+
|
|
795
|
+
// From attribute metadata
|
|
796
|
+
IF attribute.required: validations.push({ rule: "required", errorMessageKey: "{module}.{entity}.{attr}.required" })
|
|
797
|
+
IF attribute.type === "string" AND attribute.maxLength: validations.push({ rule: "maxLength", params: { max: attribute.maxLength }, errorMessageKey: "..." })
|
|
798
|
+
IF attribute.type === "string" AND attribute.unique: validations.push({ rule: "unique", errorMessageKey: "..." })
|
|
799
|
+
IF attribute.type === "email": validations.push({ rule: "email", errorMessageKey: "..." })
|
|
800
|
+
IF attribute.type === "decimal" AND (context is amount/price): validations.push({ rule: "min", params: { min: 0 }, errorMessageKey: "..." })
|
|
801
|
+
IF attribute.type === "int": validations.push({ rule: "integer", errorMessageKey: "..." })
|
|
802
|
+
IF attribute.type === "date": validations.push({ rule: "date", errorMessageKey: "..." })
|
|
803
|
+
|
|
804
|
+
// From linked business rules (BR-VAL-*)
|
|
805
|
+
IF exists BR-VAL referencing this attribute:
|
|
806
|
+
For EACH matching BR:
|
|
807
|
+
validations.push({ rule: "custom", brRef: BR.id, description: BR.statement, errorMessageKey: "..." })
|
|
808
|
+
|
|
809
|
+
Store: { entity: entity.name, field: attribute.name, rules: validations }
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
**Exemple concret (Absence) :**
|
|
813
|
+
|
|
814
|
+
```json
|
|
815
|
+
[
|
|
816
|
+
{ "entity": "Absence", "field": "startDate", "rules": [
|
|
817
|
+
{ "rule": "required", "errorMessageKey": "absences.absence.startDate.required" },
|
|
818
|
+
{ "rule": "date", "errorMessageKey": "absences.absence.startDate.date" },
|
|
819
|
+
{ "rule": "custom", "brRef": "BR-VAL-ABS-001", "description": "startDate <= endDate", "errorMessageKey": "absences.absence.startDate.beforeEnd" }
|
|
820
|
+
]},
|
|
821
|
+
{ "entity": "Absence", "field": "endDate", "rules": [
|
|
822
|
+
{ "rule": "required", "errorMessageKey": "absences.absence.endDate.required" },
|
|
823
|
+
{ "rule": "date", "errorMessageKey": "absences.absence.endDate.date" }
|
|
824
|
+
]},
|
|
825
|
+
{ "entity": "Absence", "field": "reason", "rules": [
|
|
826
|
+
{ "rule": "maxLength", "params": { "max": 500 }, "errorMessageKey": "absences.absence.reason.maxLength" }
|
|
827
|
+
]}
|
|
828
|
+
]
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**criture :** Stocker dans `usecases.json` sous la cl `validations[]` (dj dans le schema specification-schema.json).
|
|
832
|
+
|
|
268
833
|
### G. Interface Specs — Delegated to /business-analyse-design
|
|
269
834
|
|
|
270
835
|
> **Screen specifications are NOT produced in this step.**
|
|
271
836
|
> Interface design (SmartTable columns, SmartForm fields, wireframes, navigation) is handled by Phase 2: `/business-analyse-design`.
|
|
272
837
|
> This separation allows iterating on UI design without replaying the full analysis cycle.
|
|
273
838
|
|
|
274
|
-
###
|
|
839
|
+
### G-bis. API Endpoint Schema Enrichment (MANDATORY)
|
|
840
|
+
|
|
841
|
+
> **Gnrer les request/response schemas pour chaque API endpoint depuis les entits.**
|
|
842
|
+
> Les apiEndpoints[] existent dj dans le schema mais manquent les DTOs.
|
|
843
|
+
> Ce sont ces DTOs qui permettent au develop de gnrer le bon code du premier coup.
|
|
844
|
+
|
|
845
|
+
```
|
|
846
|
+
For EACH apiEndpoint in module:
|
|
847
|
+
// Derive requestSchema from entity attributes
|
|
848
|
+
IF method in ["POST", "PUT", "PATCH"]:
|
|
849
|
+
requestSchema = {}
|
|
850
|
+
For EACH attribute in entity.attributes:
|
|
851
|
+
IF attribute is NOT computed AND attribute is NOT auto-generated:
|
|
852
|
+
requestSchema[attribute.name] = {
|
|
853
|
+
type: attribute.type,
|
|
854
|
+
required: attribute.required || false,
|
|
855
|
+
description: attribute.description
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// Derive responseSchema from entity attributes + computed fields
|
|
859
|
+
responseSchema = { id: "guid" }
|
|
860
|
+
For EACH attribute in entity.attributes:
|
|
861
|
+
responseSchema[attribute.name] = {
|
|
862
|
+
type: attribute.type,
|
|
863
|
+
computed: attribute.computed || false
|
|
864
|
+
}
|
|
865
|
+
// Add navigation properties for relationships
|
|
866
|
+
For EACH relationship in entity.relationships:
|
|
867
|
+
IF relationship.type === "ManyToOne":
|
|
868
|
+
responseSchema[relationship.target + "Name"] = { type: "string", computed: true }
|
|
869
|
+
|
|
870
|
+
// Derive errorCodes from linked BRs
|
|
871
|
+
errorCodes = []
|
|
872
|
+
For EACH linkedRule in UC.linkedRules:
|
|
873
|
+
IF rule.severity === "blocking":
|
|
874
|
+
errorCodes.push({ code: 400, reason: rule.id, description: rule.statement })
|
|
875
|
+
errorCodes.push({ code: 403, reason: "Forbidden", description: "Missing permission: " + endpoint.permission })
|
|
876
|
+
errorCodes.push({ code: 404, reason: "NotFound", description: entity.name + " not found" })
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
**Exemple concret (POST /api/rh/absences) :**
|
|
880
|
+
|
|
881
|
+
```json
|
|
882
|
+
{
|
|
883
|
+
"method": "POST",
|
|
884
|
+
"path": "/api/rh/absences",
|
|
885
|
+
"permission": "Rh.Absences.Create",
|
|
886
|
+
"linkedUC": "UC-ABS-001",
|
|
887
|
+
"requestSchema": {
|
|
888
|
+
"employeeId": { "type": "guid", "required": true },
|
|
889
|
+
"absenceTypeId": { "type": "guid", "required": true },
|
|
890
|
+
"startDate": { "type": "date", "required": true },
|
|
891
|
+
"endDate": { "type": "date", "required": true },
|
|
892
|
+
"reason": { "type": "string", "required": false }
|
|
893
|
+
},
|
|
894
|
+
"responseSchema": {
|
|
895
|
+
"id": { "type": "guid" },
|
|
896
|
+
"code": { "type": "string" },
|
|
897
|
+
"status": { "type": "enum", "computed": false },
|
|
898
|
+
"duration": { "type": "decimal", "computed": true },
|
|
899
|
+
"employeeName": { "type": "string", "computed": true }
|
|
900
|
+
},
|
|
901
|
+
"errorCodes": [
|
|
902
|
+
{ "code": 400, "reason": "BR-VAL-ABS-001", "description": "Date de debut apres date de fin" },
|
|
903
|
+
{ "code": 400, "reason": "BR-VAL-ABS-002", "description": "Chevauchement avec absence existante" },
|
|
904
|
+
{ "code": 400, "reason": "BR-VAL-ABS-003", "description": "Solde insuffisant" },
|
|
905
|
+
{ "code": 403, "reason": "Forbidden", "description": "Permission Rh.Absences.Create requise" },
|
|
906
|
+
{ "code": 404, "reason": "NotFound", "description": "Employee not found" }
|
|
907
|
+
]
|
|
908
|
+
}
|
|
909
|
+
```
|
|
910
|
+
|
|
911
|
+
**criture :** Stocker dans `usecases.json` sous la cl `apiEndpoints[]` (enrichi).
|
|
912
|
+
|
|
913
|
+
### H-pre. Schema Refresh (OBLIGATOIRE avant chaque ecriture)
|
|
914
|
+
|
|
915
|
+
AVANT d'ecrire les JSON pour le module courant :
|
|
916
|
+
→ **Relire** `references/03-json-schemas.md` section "Business Rules Schema Format"
|
|
917
|
+
→ Verifier que CHAQUE rule dans le buffer utilise les champs canoniques :
|
|
918
|
+
- `id` (pas `code`), `name` (pas `label`), `statement` (pas `description`/`rule`),
|
|
919
|
+
`category` (pas `type`), `severity` (blocking/warning/info, pas Error/error),
|
|
920
|
+
`examples[]` (array d'`{input, expected}`, pas string), `entities[]`, `sectionCode`
|
|
921
|
+
→ SI un champ deprecated est detecte : corriger AVANT ecriture
|
|
922
|
+
→ Ce refresh prend ~30 secondes et previent 100% des derives de schema
|
|
923
|
+
|
|
924
|
+
**POURQUOI ce refresh :** Apres 5+ modules, le contexte est compacte et les exemples
|
|
925
|
+
JSON du debut de conversation sont perdus. Ce refresh garantit que chaque module
|
|
926
|
+
est ecrit avec le format canonique, meme si le contexte a ete compresse.
|
|
927
|
+
|
|
928
|
+
### H. Write & Advance (SEULEMENT apres validation complete)
|
|
929
|
+
|
|
930
|
+
> **GATE:** ba-writer ne peut etre lance QUE si le client a valide :
|
|
931
|
+
> entites (B-ter) + regles (C-bis) + use cases/permissions (E-ter).
|
|
932
|
+
> Si un lot n'est pas valide → RETOUR au lot concerne.
|
|
275
933
|
|
|
276
934
|
After completing all sub-steps for a module:
|
|
277
935
|
|
|
@@ -295,6 +953,15 @@ After completing all sub-steps for a module:
|
|
|
295
953
|
|
|
296
954
|
3. Advance to next module in topological order
|
|
297
955
|
|
|
956
|
+
### H-bis. Module Transition Summary
|
|
957
|
+
|
|
958
|
+
Afficher un resume compact du module termine :
|
|
959
|
+
```
|
|
960
|
+
✓ {moduleName} — {entityCount} entites, {ruleCount} regles, {ucCount} UCs, {permCount} permissions
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
Passer au module suivant. INTERDICTION de lancer des ba-writer en parallele pour des modules differents.
|
|
964
|
+
|
|
298
965
|
### I. Module Completion Check
|
|
299
966
|
|
|
300
967
|
After all modules are specified:
|
|
@@ -303,102 +970,16 @@ After all modules are specified:
|
|
|
303
970
|
- Remind user: "Run /business-analyse-design to design interfaces for these modules"
|
|
304
971
|
- Transition to step 04
|
|
305
972
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
Before advancing to step 04, run these validations for EACH module:
|
|
309
|
-
|
|
310
|
-
```javascript
|
|
311
|
-
const errors = [];
|
|
312
|
-
const warnings = [];
|
|
313
|
-
|
|
314
|
-
for (const mod of modules) {
|
|
315
|
-
// mod.dir = resolveModuleDir(applicationCode, mod.code)
|
|
316
|
-
// e.g., docs/projet-rh/v1.0/human-resources/employees/
|
|
317
|
-
const ent = READ(mod.dir + '/entities.json')?.entities || [];
|
|
318
|
-
const ucs = READ(mod.dir + '/usecases.json')?.useCases || [];
|
|
319
|
-
const brs = READ(mod.dir + '/rules.json')?.rules || [];
|
|
320
|
-
const perms = READ(mod.dir + '/permissions.json');
|
|
321
|
-
const sections = mod.anticipatedSections || [];
|
|
322
|
-
const sectionCodes = new Set(sections.map(s => s.code));
|
|
323
|
-
|
|
324
|
-
// Mandatory checks (BLOCKING)
|
|
325
|
-
if (ent.length === 0) errors.push(mod.code + ": 0 entities");
|
|
326
|
-
if (ucs.length === 0) errors.push(mod.code + ": 0 use cases");
|
|
327
|
-
if (brs.length === 0) errors.push(mod.code + ": 0 business rules");
|
|
328
|
-
if (!perms?.permissionPaths?.length) errors.push(mod.code + ": no permissions");
|
|
329
|
-
|
|
330
|
-
// sectionCode validation
|
|
331
|
-
for (const uc of ucs) {
|
|
332
|
-
if (!uc.sectionCode) errors.push(mod.code + ": UC '" + uc.id + "' missing sectionCode");
|
|
333
|
-
else if (!sectionCodes.has(uc.sectionCode)) errors.push(mod.code + ": UC '" + uc.id + "' sectionCode '" + uc.sectionCode + "' not in anticipatedSections");
|
|
334
|
-
}
|
|
335
|
-
for (const br of brs) {
|
|
336
|
-
if (!br.sectionCode) errors.push(mod.code + ": BR '" + br.id + "' missing sectionCode");
|
|
337
|
-
else if (!sectionCodes.has(br.sectionCode)) errors.push(mod.code + ": BR '" + br.id + "' sectionCode '" + br.sectionCode + "' not in anticipatedSections");
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// Entity attribute checks
|
|
341
|
-
for (const e of ent) {
|
|
342
|
-
for (const a of (e.attributes || [])) {
|
|
343
|
-
if (!a.type) warnings.push(mod.code + ": entity " + e.name + " attr '" + a.name + "' missing type");
|
|
344
|
-
if (a.type === 'enum' && !a.defaultValue) errors.push(mod.code + ": enum attr '" + a.name + "' missing defaultValue");
|
|
345
|
-
// FK naming convention: must end with "Id"
|
|
346
|
-
if ((a.type === 'guid' || a.type === 'string') && a.foreignKey && !a.name.endsWith('Id'))
|
|
347
|
-
warnings.push(mod.code + ": entity " + e.name + " FK attr '" + a.name + "' should end with 'Id'");
|
|
348
|
-
}
|
|
349
|
-
// Person Extension Pattern check
|
|
350
|
-
const personFields = ['firstName', 'lastName', 'email', 'phoneNumber', 'phone'];
|
|
351
|
-
const foundPersonFields = (e.attributes || []).filter(a => personFields.includes(a.name));
|
|
352
|
-
if (foundPersonFields.length >= 3 && !e.personRoleConfig) {
|
|
353
|
-
errors.push(mod.code + ": entity '" + e.name + "' has " + foundPersonFields.length +
|
|
354
|
-
" person fields (" + foundPersonFields.map(f => f.name).join(", ") +
|
|
355
|
-
") but no personRoleConfig — use Person Extension Pattern (entity-architecture-decision.md section 0). " +
|
|
356
|
-
"Person fields (firstName, lastName, email) belong on auth_Users, not on the domain entity.");
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// Canonical usecases key check
|
|
361
|
-
const rawUCFile = READ(mod.dir + '/usecases.json');
|
|
362
|
-
if (rawUCFile && !rawUCFile.useCases && rawUCFile.usecases) {
|
|
363
|
-
errors.push(mod.code + ": usecases.json uses 'usecases' key instead of canonical 'useCases' — fix before proceeding");
|
|
364
|
-
}
|
|
365
|
-
// Check steps serialization format
|
|
366
|
-
for (const uc of ucs) {
|
|
367
|
-
if (uc.steps && Array.isArray(uc.steps) && uc.steps.length > 0 && typeof uc.steps[0] === 'object') {
|
|
368
|
-
errors.push(mod.code + ": UC '" + uc.id + "' uses steps[] with objects — must use mainScenario[] with strings");
|
|
369
|
-
}
|
|
370
|
-
if (uc.actor && !uc.primaryActor) {
|
|
371
|
-
warnings.push(mod.code + ": UC '" + uc.id + "' uses 'actor' instead of canonical 'primaryActor'");
|
|
372
|
-
}
|
|
373
|
-
}
|
|
973
|
+
### I-bis. Cross-Module Questions (apres tous les modules)
|
|
374
974
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (!brs.find(br => br.id === brRef)) warnings.push(mod.code + ": UC '" + uc.id + "' references non-existent BR '" + brRef + "'");
|
|
379
|
-
}
|
|
380
|
-
}
|
|
975
|
+
SI des dependances cross-module existent (identifiees en step-02) :
|
|
976
|
+
→ Charger questionnaire/05-cross-module.md et poser les questions pertinentes via AskUserQuestion.
|
|
977
|
+
→ Integrer les reponses dans les modules concernes via ba-writer.
|
|
381
978
|
|
|
382
|
-
|
|
383
|
-
for (const section of sections) {
|
|
384
|
-
if (section.sectionType === 'view') {
|
|
385
|
-
const viewPerms = (perms?.permissionPaths || []).filter(p => p.includes('.' + section.code + '.'));
|
|
386
|
-
if (viewPerms.length > 0) errors.push(mod.code + ": view section '" + section.code + "' has " + viewPerms.length + " permissions (should inherit)");
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
979
|
+
## POST-CHECK (EXECUTABLE — BLOCKING)
|
|
390
980
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
errors.forEach(e => Display(" ✗ " + e));
|
|
394
|
-
BLOCKING_ERROR("Fix all errors before advancing to step 04");
|
|
395
|
-
}
|
|
396
|
-
if (warnings.length > 0) {
|
|
397
|
-
Display("POST-CHECK warnings (" + warnings.length + "):");
|
|
398
|
-
warnings.forEach(w => Display(" ⚠ " + w));
|
|
399
|
-
}
|
|
400
|
-
Display("POST-CHECK PASS: " + modules.length + " modules validated");
|
|
401
|
-
```
|
|
981
|
+
> → **Load** `references/03-post-check-validation.md` and execute ALL checks.
|
|
982
|
+
> Any BLOCKING check failure must be resolved before proceeding to step 04.
|
|
402
983
|
|
|
403
984
|
## Transition
|
|
404
985
|
|