@atlashub/smartstack-cli 3.18.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/index.js +3 -0
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/agents/gitflow/cleanup.md +5 -1
  5. package/templates/agents/gitflow/finish.md +2 -0
  6. package/templates/agents/gitflow/init-clone.md +13 -0
  7. package/templates/agents/gitflow/init-validate.md +14 -0
  8. package/templates/agents/gitflow/start.md +2 -2
  9. package/templates/agents/gitflow/status.md +6 -0
  10. package/templates/skills/business-analyse/SKILL.md +1 -1
  11. package/templates/skills/business-analyse/_shared.md +46 -20
  12. package/templates/skills/business-analyse/html/ba-interactive.html +57 -107
  13. package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +13 -0
  14. package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +1 -1
  15. package/templates/skills/business-analyse/html/src/scripts/03-render-cadrage.js +11 -20
  16. package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +1 -3
  17. package/templates/skills/business-analyse/html/src/template.html +31 -83
  18. package/templates/skills/business-analyse/patterns/suggestion-catalog.md +71 -3
  19. package/templates/skills/business-analyse/references/cadrage-pre-analysis.md +11 -8
  20. package/templates/skills/business-analyse/references/cadrage-structure-cards.md +7 -5
  21. package/templates/skills/business-analyse/references/deploy-data-build.md +42 -14
  22. package/templates/skills/business-analyse/references/deploy-modes.md +1 -1
  23. package/templates/skills/business-analyse/references/entity-architecture-decision.md +218 -0
  24. package/templates/skills/business-analyse/references/robustness-checks.md +2 -1
  25. package/templates/skills/business-analyse/references/spec-auto-inference.md +70 -16
  26. package/templates/skills/business-analyse/references/ui-resource-cards.md +149 -0
  27. package/templates/skills/business-analyse/steps/step-01-cadrage.md +220 -32
  28. package/templates/skills/business-analyse/steps/step-02-decomposition.md +51 -29
  29. package/templates/skills/business-analyse/steps/step-03a1-setup.md +122 -32
  30. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +8 -0
  31. package/templates/skills/business-analyse/steps/step-03b-ui.md +68 -5
  32. package/templates/skills/business-analyse/steps/step-05a-handoff.md +99 -2
  33. package/templates/skills/business-analyse/steps/step-05b-deploy.md +35 -1
  34. package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +4 -1
  35. package/templates/skills/business-analyse/steps/step-06-review.md +2 -1
  36. package/templates/skills/business-analyse/templates/tpl-handoff.md +5 -4
  37. package/templates/skills/business-analyse/templates/tpl-launch-displays.md +4 -1
  38. package/templates/skills/business-analyse/templates-frd.md +5 -4
  39. package/templates/skills/gitflow/_shared.md +65 -17
  40. package/templates/skills/gitflow/phases/status.md +8 -3
  41. package/templates/skills/gitflow/references/start-local-config.md +6 -3
  42. package/templates/skills/gitflow/steps/step-start.md +5 -2
@@ -29,24 +29,78 @@
29
29
  | datetime | DatePicker | entity.required | — |
30
30
  | bool | Toggle | — | default: false |
31
31
 
32
- ## Auto-Generated Sections by featureType
33
-
34
- | featureType | Sections generated |
35
- |---|---|
36
- | data-centric | list, create, detail |
37
- | workflow | list, create, detail, edit |
38
- | integration | list, detail, config |
39
- | reporting | dashboard |
40
- | full-module | list, create, detail, edit, dashboard |
41
-
42
- ## Section Generation Rules
43
-
44
- 1. **list section:** SmartTable with all non-long-text attributes as columns, actions = [view, edit, delete], defaultSort = { createdAt, desc }
45
- 2. **create section:** SmartForm with all writable attributes as fields, component inferred from type
46
- 3. **detail section:** DetailCard with all attributes + child SmartTable for each 1:N relationship
47
- 4. **edit section:** Same as create but pre-filled (mode: edit)
32
+ ## Auto-Generated UI Components by featureType
33
+
34
+ > **RULE:** Sections = functional zones only. `create`/`edit` are actions within `list`. `detail` is a tabbed page reached from `list`.
35
+
36
+ | featureType | Sections (functional zones) | List page includes | Detail page tabs |
37
+ |---|---|---|---|
38
+ | data-centric | list | grid, filters, create form (modal) | Infos, {relations} |
39
+ | workflow | list, approve | grid, filters, create form (modal) | Infos, {relations}, Historique |
40
+ | integration | list | grid, filters, config form | Infos, Config, Logs |
41
+ | reporting | dashboard | — | — |
42
+ | full-module | list, dashboard | grid, filters, create form (modal) | Infos, {relations}, Historique |
43
+
44
+ ## Component Generation Rules
45
+
46
+ 1. **list section:** SmartTable with all non-long-text attributes as columns, actions = [view, edit, delete], defaultSort = { createdAt, desc }. Create action opens SmartForm in modal/drawer.
47
+ 2. **create form (in list):** SmartForm with all writable attributes as fields, component inferred from type. Opens as modal/drawer from the list page.
48
+ 3. **detail page (from list click):** TabPanel with: Info tab (all attributes), relation tabs (child SmartTable for each 1:N relationship), History tab (if auditable). See "Detail Page Tab Auto-Inference" below for exact rules.
49
+ 4. **edit (in detail):** Same form as create but pre-filled (mode: edit). Inline in the detail page Info tab.
48
50
  5. **dashboard section:** Trigger 3d (dashboard specification)
49
51
 
52
+ ## Detail Page Tab Auto-Inference
53
+
54
+ > **RULE:** Every module with a `list` section MUST have a companion detail page. Tabs are inferred from multiple sources.
55
+
56
+ ### Tab sources (merged in order)
57
+
58
+ | Priority | Source | Tabs generated |
59
+ |----------|--------|----------------|
60
+ | 1 | `coverageMatrix[].detailTabs` (from cadrage) | Exact tab names as specified by client |
61
+ | 2 | Entity `relationships[]` where `type = "1:N"` | One tab per child relationship (SmartTable) |
62
+ | 3 | Entity has `lifeCycles[]` | History tab (Timeline) |
63
+ | 4 | Always present | Info tab (first position) |
64
+
65
+ ### Merge algorithm
66
+
67
+ ```
68
+ detailTabs = []
69
+
70
+ # 1. Always add Info tab first
71
+ detailTabs.push({ code: "info", label: "Informations", content: DetailCard })
72
+
73
+ # 2. If cadrage specified detailTabs, use those names
74
+ IF coverageMatrix[module].detailTabs EXISTS:
75
+ FOR EACH tabName IN detailTabs:
76
+ IF tabName matches a 1:N relationship entity → SmartTable tab
77
+ ELIF tabName == "Historique"/"History" → Timeline tab
78
+ ELSE → custom DetailCard tab (contents TBD in step-03b)
79
+
80
+ # 3. If no cadrage tabs, auto-infer from relationships
81
+ ELSE:
82
+ FOR EACH rel IN entity.relationships WHERE rel.type == "1:N":
83
+ detailTabs.push({ code: rel.target (kebab-case), label: rel.target (plural), content: SmartTable })
84
+
85
+ # 4. Add History tab if auditable
86
+ IF entity has lifeCycles:
87
+ detailTabs.push({ code: "history", label: "Historique", content: Timeline })
88
+ ```
89
+
90
+ ### Detail section auto-generation
91
+
92
+ When auto-generating the detail section, create:
93
+ - `specification.sections[]` entry with `code: "detail"`, `navigation: "hidden"`, route `/business/{app}/{module}/detail/:id`
94
+ - `specification.uiWireframes[]` entry with `section: "detail"` and ASCII mockup showing all tabs
95
+ - Resources: `{module}-detail-header` (DetailHeader), `{module}-detail-tabs` (TabPanel), `{module}-info-card` (DetailCard), one `{module}-{relation}-grid` per relation tab, `{module}-history` (Timeline if auditable)
96
+
97
+ ### Detail page navigation wiring
98
+
99
+ The detail page is NOT a sidebar entry. Navigation is handled by:
100
+ - **From list**: row click action `navigate:detail` → `/business/{app}/{module}/detail/{id}`
101
+ - **Back button**: detail header → `/business/{app}/{module}/list`
102
+ - **Route registration**: route MUST be registered in frontend routing with `:id` parameter
103
+
50
104
  ## Status/Lifecycle Enhancement
51
105
 
52
106
  If entity has a status/enum field AND lifeCycles exists:
@@ -73,6 +73,98 @@
73
73
 
74
74
  **MANDATORY for SmartForm:** `fields` with `component` type, `formLayout`
75
75
 
76
+ ## Detail Page section (reached from list click)
77
+
78
+ > **RULE:** The detail page is NOT a sidebar navigation entry. It is reached by clicking a row in the `list` section. Its route includes `:id` parameter. Every module with a `list` section MUST have a companion detail page.
79
+
80
+ ```json
81
+ {
82
+ "code": "detail",
83
+ "labels": { "fr": "Détail", "en": "Detail", "it": "Dettaglio", "de": "Detail" },
84
+ "route": "/business/{app}/{module}/detail/:id",
85
+ "icon": "file-text",
86
+ "permission": "business.{app}.{module}.read",
87
+ "wireframe": "{module}-detail",
88
+ "navigation": "hidden",
89
+ "useCases": ["UC-{PREFIX}-002"],
90
+ "businessRules": ["BR-VAL-{PREFIX}-001"],
91
+ "resources": [
92
+ {
93
+ "code": "{module}-detail-header",
94
+ "type": "DetailHeader",
95
+ "entity": "{MainEntity}",
96
+ "permission": "business.{app}.{module}.read",
97
+ "fields": ["code", "name", "status"],
98
+ "actions": [
99
+ { "action": "edit", "icon": "edit", "permission": "business.{app}.{module}.update", "showWhen": {"status": ["draft"]} },
100
+ { "action": "delete", "icon": "trash", "permission": "business.{app}.{module}.delete", "confirm": true }
101
+ ],
102
+ "statusBadge": { "field": "status", "colorMap": "stateMachine:{Entity}" }
103
+ },
104
+ {
105
+ "code": "{module}-detail-tabs",
106
+ "type": "TabPanel",
107
+ "entity": "{MainEntity}",
108
+ "permission": "business.{app}.{module}.read",
109
+ "tabs": [
110
+ {
111
+ "code": "info",
112
+ "label": {"fr": "Informations", "en": "Information", "it": "Informazioni", "de": "Informationen"},
113
+ "icon": "info",
114
+ "default": true,
115
+ "content": {
116
+ "type": "DetailCard",
117
+ "resourceRef": "{module}-info-card",
118
+ "fields": ["code", "name", "type", "description", "startDate", "createdAt"],
119
+ "editMode": {
120
+ "enabled": true,
121
+ "formRef": "{module}-form",
122
+ "permission": "business.{app}.{module}.update"
123
+ }
124
+ }
125
+ },
126
+ {
127
+ "code": "{relation}",
128
+ "label": {"fr": "{RelationLabel}", "en": "{RelationLabel}"},
129
+ "icon": "list",
130
+ "content": {
131
+ "type": "SmartTable",
132
+ "resourceRef": "{module}-{relation}-grid",
133
+ "entity": "{RelatedEntity}",
134
+ "parentFilter": "{MainEntity}Id"
135
+ }
136
+ },
137
+ {
138
+ "code": "history",
139
+ "label": {"fr": "Historique", "en": "History", "it": "Storico", "de": "Verlauf"},
140
+ "icon": "clock",
141
+ "showWhen": "auditable",
142
+ "content": {
143
+ "type": "Timeline",
144
+ "resourceRef": "{module}-history",
145
+ "source": "auditLog"
146
+ }
147
+ }
148
+ ]
149
+ }
150
+ ]
151
+ }
152
+ ```
153
+
154
+ **MANDATORY for detail section:**
155
+ - `navigation: "hidden"` — detail page is NOT shown in sidebar, reached by row click from list
156
+ - `route` MUST contain `:id` parameter
157
+ - At least one `TabPanel` resource with `tabs[]`
158
+ - First tab MUST be "info" with `DetailCard` + `editMode`
159
+ - One tab per 1:N relationship (auto-inferred from entity relationships)
160
+ - History tab if entity is auditable (has lifeCycles)
161
+
162
+ **Tab auto-generation rules:**
163
+ 1. **Info tab** (always) — all entity attributes displayed as read-only fields, with edit toggle
164
+ 2. **Relation tabs** (per 1:N relationship) — SmartTable filtered by `parentFilter`
165
+ 3. **History tab** (if auditable) — Timeline from audit log
166
+ 4. **Custom tabs** (from cadrage `detailTabs[]`) — any additional tabs specified during cadrage
167
+
76
168
  ## specification.uiWireframes[]
77
169
 
78
170
  ```json
@@ -108,3 +200,60 @@
108
200
  **REQUIRED fields:** `screen`, `mockup`, `elements`, `section`, `componentMapping`, `layout` are ALL mandatory.
109
201
  A wireframe without `componentMapping` or `layout` will FAIL validation in step 9.
110
202
  **layout.regions[].components[].resourceRef** MUST match a `sections[].resources[].code`.
203
+
204
+ ## Detail Page Wireframe
205
+
206
+ > **RULE:** For every `list` section, a companion detail wireframe MUST exist with `section: "detail"`.
207
+
208
+ ```json
209
+ {
210
+ "screen": "{module}-detail",
211
+ "section": "detail",
212
+ "description": "Page de détail avec onglets — accessible depuis la liste par clic sur une ligne",
213
+ "mockupFormat": "ascii",
214
+ "mockup": "╔═══════════════════════════════════════════════════════════╗\n║ ← Retour à la liste ║\n╠═══════════════════════════════════════════════════════════╣\n║ {Entity} : {code} — {name} ● Statut [✏️] [🗑️] ║\n╠═══════════════════════════════════════════════════════════╣\n║ [ Informations ] [ {Relation} ] [ Historique ] ║\n╠═══════════════════════════════════════════════════════════╣\n║ ┌─────────────────────────────────────────────────────┐ ║\n║ │ Code: {code} │ ║\n║ │ Nom: {name} │ ║\n║ │ Type: {type} [Modifier] │ ║\n║ │ Description: {description} │ ║\n║ │ Créé le: {createdAt} │ ║\n║ └─────────────────────────────────────────────────────┘ ║\n╚═══════════════════════════════════════════════════════════╝",
215
+ "elements": [
216
+ { "id": "elem-back", "type": "BackButton", "label": "Retour à la liste" },
217
+ { "id": "elem-header", "type": "DetailHeader", "label": "En-tête entité" },
218
+ { "id": "elem-status", "type": "StatusBadge", "label": "Badge statut" },
219
+ { "id": "elem-tabs", "type": "TabPanel", "label": "Onglets de détail" },
220
+ { "id": "elem-info", "type": "DetailCard", "label": "Carte informations" },
221
+ { "id": "elem-edit", "type": "SmartForm", "label": "Formulaire d'édition" }
222
+ ],
223
+ "actions": [
224
+ { "trigger": "Click back", "action": "Navigate to list" },
225
+ { "trigger": "Click edit", "action": "Toggle edit mode on info tab" },
226
+ { "trigger": "Click tab", "action": "Switch tab content" },
227
+ { "trigger": "Click status action", "action": "Trigger state transition (if lifeCycles)" }
228
+ ],
229
+ "componentMapping": [
230
+ { "wireframeElement": "BackButton", "reactComponent": "BackButton" },
231
+ { "wireframeElement": "DetailHeader", "reactComponent": "EntityDetailHeader" },
232
+ { "wireframeElement": "StatusBadge", "reactComponent": "StatusBadge" },
233
+ { "wireframeElement": "TabPanel", "reactComponent": "Tabs" },
234
+ { "wireframeElement": "DetailCard", "reactComponent": "EntityDetailCard" },
235
+ { "wireframeElement": "SmartForm", "reactComponent": "SmartForm" }
236
+ ],
237
+ "layout": {
238
+ "type": "page",
239
+ "regions": [
240
+ { "id": "header", "position": "top", "components": [
241
+ { "type": "BackButton", "target": "/business/{app}/{module}/list" },
242
+ { "type": "DetailHeader", "resourceRef": "{module}-detail-header" },
243
+ { "type": "StatusBadge", "resourceRef": "{module}-status" }
244
+ ]},
245
+ { "id": "tabs", "position": "main", "span": 12, "components": [
246
+ { "type": "TabPanel", "resourceRef": "{module}-detail-tabs" }
247
+ ]}
248
+ ]
249
+ },
250
+ "permissionsRequired": ["business.{app}.{module}.read"]
251
+ }
252
+ ```
253
+
254
+ **Detail wireframe adaptation rules:**
255
+ - **Tabs** must match `sections[code=detail].resources[type=TabPanel].tabs[]`
256
+ - **Relation tabs** show a SmartTable of child entities filtered by parent ID
257
+ - **History tab** only included if entity has `lifeCycles` defined
258
+ - **Edit button** only shown if user has `update` permission
259
+ - **Status actions** only shown if entity has state machine transitions from current state
@@ -6,6 +6,7 @@ next_step: steps/step-02-decomposition.md
6
6
  ---
7
7
 
8
8
  > **Context files:** `_shared.md` | `_elicitation.md` | `_architecture.md` | `_suggestions.md`
9
+ > **Reference (4d-bis):** `references/entity-architecture-decision.md` — Entity scoring, domain coherence, section patterns
9
10
 
10
11
  # Step 1: Cadrage (Framing)
11
12
 
@@ -135,11 +136,12 @@ pre_analysis:
135
136
 
136
137
  **Modules identifiés :**
137
138
  - **{Module 1}** : {functional description}
138
- - Sections pressenties : {list, detail, create, edit...}
139
- - Resources clés : {grid, form, card, chart...}
139
+ - Section **list** : {entity}-grid, {entity}-filters, {entity}-form (création en modale)
140
+ - Page détail (onglets) : {Infos, {relation_tabs}...}
141
+ - {IF dashboard needed:} Section **dashboard** : {kpi-cards, charts...}
140
142
  - **{Module 2}** : {functional description}
141
- - Sections pressenties : {list, create...}
142
- - Resources clés : {grid, form...}
143
+ - Section **list** : {entity}-grid, {entity}-filters, {entity}-form
144
+ - Page détail (onglets) : {Infos, ...}
143
145
 
144
146
  **Points que j'ai notés :**
145
147
  - {specific point 1 from the brief, quoted verbatim when possible}
@@ -209,10 +211,31 @@ Ask in 1-2 batches. After each batch:
209
211
  **Mandatory minimum:** Q3.2 (must-have), Q3.4 (exclusions), Q3.5 (main journey).
210
212
 
211
213
  Ask in 1-2 batches. After each batch:
212
- - If everything is "must-have" → apply priority test: "If you could only keep 3 features, which ones?"
214
+ - If everything is "must-have" → **BLOCKING**: apply MoSCoW prioritization question (see POST-CHECK below)
213
215
  - If no exclusions → probe: "What should this system explicitly NOT do?"
214
216
  - If journey is too simple → detail: "What happens when something goes wrong? When someone cancels?"
215
217
 
218
+ > **BLOCKING RULE — MoSCoW DISTRIBUTION:**
219
+ > If the client classifies ALL features as "must-have", you MUST challenge this BEFORE proceeding.
220
+ > Ask via AskUserQuestion:
221
+ > ```
222
+ > question: "{language == 'fr'
223
+ > ? 'Toutes les fonctionnalités sont marquées indispensables. Si vous ne pouviez livrer que 60% du périmètre en v1, lesquelles pourraient attendre la v2 ?'
224
+ > : 'All features are marked must-have. If you could only deliver 60% of scope in v1, which ones could wait for v2?'}"
225
+ > header: "Priorisation"
226
+ > multiSelect: true
227
+ > options:
228
+ > - label: "{feature_1}"
229
+ > description: "{language == 'fr' ? 'Pourrait passer en Important (v1.x)' : 'Could move to Important (v1.x)'}"
230
+ > - label: "{feature_2}"
231
+ > description: "{language == 'fr' ? 'Pourrait passer en Optionnel (v2)' : 'Could move to Optional (v2)'}"
232
+ > - label: "{feature_3}"
233
+ > description: "{language == 'fr' ? 'Pourrait passer en Important (v1.x)' : 'Could move to Important (v1.x)'}"
234
+ > - label: "{language == 'fr' ? 'Tout est vraiment indispensable' : 'Everything is truly must-have'}"
235
+ > description: "{language == 'fr' ? 'Je confirme que toutes les fonctionnalités sont critiques pour la v1' : 'I confirm all features are critical for v1'}"
236
+ > ```
237
+ > If client moves items → update categories. If client confirms ALL mustHave → accept but log in changelog.
238
+
216
239
  #### 4d. Challenge Implicit Assumptions (CRITICAL)
217
240
 
218
241
  > **Apply elicitation techniques to challenge what the client considers "obvious".**
@@ -243,46 +266,174 @@ Ask challenge questions via AskUserQuestion (1-2 batches of max 4).
243
266
 
244
267
  #### 4d-bis. Entity Sourcing Pattern (MANDATORY for detected dependencies)
245
268
 
246
- > **When the analysis detects a referenced entity/concept (e.g., "Projets" referenced by activities, "Clients" referenced by orders), ALWAYS ask how this entity is sourced.**
247
- > This question detects potential new modules that were not mentioned in the original brief.
269
+ > **When the analysis detects a referenced entity/concept (e.g., "Projets" referenced by activities, "Clients" referenced by orders), ALWAYS analyze and recommend BEFORE asking the client.**
270
+ > This pattern detects potential new modules not mentioned in the original brief.
271
+ > **Reference:** Load [references/entity-architecture-decision.md](../references/entity-architecture-decision.md) for scoring grid, decision tree, and section patterns.
248
272
 
249
273
  For EACH referenced entity/concept detected during phases 2-4 that is NOT already covered by an identified module:
250
274
 
251
- Ask via AskUserQuestion:
275
+ ##### PHASE 1 — ULTRATHINK: Silent Architecture Analysis (NO output to client)
276
+
277
+ > **The AI reasons about the entity BEFORE presenting options. This is internal thinking only.**
278
+
279
+ ```
280
+ ULTRATHINK — Entity Architecture Analysis for {entity_name}:
281
+
282
+ 1. DOMAIN COHERENCE (from decision tree in reference)
283
+ - Application domain: {app_description}
284
+ - Entity fit: CORE | SUPPORT | PERIPHERAL
285
+ - Justification: {1 sentence — why this entity is/isn't core to the app}
286
+ - Example: "Projets" in a time management app = CORE (without projects, time entries have no target)
287
+ - Example: "Codes d'imputation" in a time management app = SUPPORT (useful for accounting, but not central)
288
+
289
+ 2. ENTITY SCORING (5 criteria, 0-3 each — from scoring grid in reference)
290
+ - Lifecycle: {score}/3 — {brief justification}
291
+ - Actors: {score}/3 — {brief justification}
292
+ - Relations: {score}/3 — {brief justification}
293
+ - Volume: {score}/3 — {brief justification}
294
+ - Autonomy: {score}/3 — {brief justification}
295
+ - TOTAL: {total}/15 → {classification: config_list | in_app | light_module | full_module}
296
+
297
+ 3. PRE-CLASSIFICATION CHECK (from entity patterns in reference)
298
+ - Does {entity_name} match a known pattern? → {yes: which one | no: use scoring}
299
+ - Override needed? → {yes: why | no}
300
+
301
+ 4. RECOMMENDATION
302
+ - Option: {config_list | in_app_section | new_module | external_system}
303
+ - Confidence: HIGH | MEDIUM | LOW
304
+ - Reasoning: {1-2 sentences}
305
+ - Risk if wrong choice: {what goes wrong if user picks a different option}
306
+
307
+ 5. IF recommendation = new_module → PRE-BUILD ARCHITECTURE
308
+ - Module code: {PascalCase}
309
+ - Section `list`: {main entity grid + create action + navigation to detail}
310
+ - Detail page tabs: [{tab_name: content}] (accessible by clicking a row in list)
311
+ - Additional sections: [{code: justification}] (ONLY functional zones: dashboard, approve, import, rapport...)
312
+ - Dependencies: [{which modules reference/are referenced by this entity}]
313
+ - Topological position: layer {N} (foundation if no dependencies)
314
+ ```
315
+
316
+ ##### PHASE 2 — Present Analysis & Recommendation to Client
317
+
318
+ **BEFORE the AskUserQuestion, display the analysis as markdown:**
319
+
320
+ ```
321
+ ### {language == "fr" ? "Analyse" : "Analysis"} : {entity_plural}
322
+
323
+ {language == "fr"
324
+ ? "Les **{entity_plural}** sont référencés par {parent_module} ({relationship_description})."
325
+ : "**{entity_plural}** are referenced by {parent_module} ({relationship_description})."}
326
+
327
+ {language == "fr" ? "**Mon analyse :**" : "**My analysis:**"}
328
+ - {language == "fr" ? "Cohérence domaine" : "Domain coherence"} : **{CORE|SUPPORT|PERIPHERAL}** — {justification}
329
+ - {language == "fr" ? "Score de complexité" : "Complexity score"} : **{score}/15** ({classification})
330
+ - {language == "fr" ? "Recommandation" : "Recommendation"} : **{recommended_option}** — {reasoning}
331
+ ```
332
+
333
+ **IF recommendation = new_module AND confidence >= MEDIUM, ALSO display:**
334
+
335
+ ```
336
+ {language == "fr" ? "**Architecture proposée :**" : "**Proposed architecture:**"}
337
+
338
+ | {language == "fr" ? "Niveau" : "Level"} | {language == "fr" ? "Valeur" : "Value"} | {language == "fr" ? "Justification" : "Rationale"} |
339
+ |--------|--------|---------------|
340
+ | Context | `business` | {language == "fr" ? "Contexte métier standard" : "Standard business context"} |
341
+ | Application | `{app_code}` | {app_name} |
342
+ | Module | `{ModuleCode}` | {language == "fr" ? "{pourquoi ce découpage}" : "{why this decomposition}"} |
343
+
344
+ | Section | {language == "fr" ? "Justification" : "Rationale"} | Resources |
345
+ |---------|---------------|-----------|
346
+ | `list` | {language == "fr" ? "Page principale : grille, création, navigation vers détail" : "Main page: grid, create action, navigate to detail"} | {entity}-grid, {entity}-filters, {entity}-form |
347
+ | {additional_section} | {justification} | {resources} |
348
+
349
+ {language == "fr"
350
+ ? "**Page détail** (onglets accessibles depuis la liste) :"
351
+ : "**Detail page** (tabs accessible from list):"}
352
+
353
+ | {language == "fr" ? "Onglet" : "Tab"} | {language == "fr" ? "Contenu" : "Content"} |
354
+ |--------|---------|
355
+ | {language == "fr" ? "Informations" : "Information"} | {language == "fr" ? "Fiche principale" : "Main record"} |
356
+ | {tab_name} | {tab_content} |
357
+
358
+ {language == "fr"
359
+ ? "**Impact :** {ModuleName} deviendra une dépendance de {parent_module} (couche {N} du graphe)."
360
+ : "**Impact:** {ModuleName} will become a dependency of {parent_module} (layer {N} in the graph)."}
361
+ ```
362
+
363
+ ##### PHASE 3 — Ask with Recommended Option First
364
+
365
+ **Order the options with the recommendation FIRST, marked "(Recommandé)" / "(Recommended)":**
366
+
252
367
  ```
253
368
  question: "{language == 'fr'
254
- ? 'Les {entity_plural} auxquel(le)s les {parent_entity_plural} sont lié(e)s : comment sont-ils gérés ?'
255
- : 'The {entity_plural} that {parent_entity_plural} are linked to: how are they managed?'}"
369
+ ? 'Comment souhaitez-vous gérer les {entity_plural} ?'
370
+ : 'How do you want to manage {entity_plural}?'}"
256
371
  header: "{entity_name}"
257
372
  options:
258
- - label: "{language == 'fr' ? 'Gérés dans l\'app' : 'Managed in app'}"
373
+ (ORDER: recommended option FIRST, then the 3 remaining options in logical order)
374
+
375
+ IF recommendation = new_module:
376
+ - label: "{language == 'fr' ? 'Nouveau module dédié (Recommandé)' : 'New dedicated module (Recommended)'}"
377
+ description: "{language == 'fr'
378
+ ? 'Module {ModuleCode} avec page liste, détail par onglets, permissions dédiées'
379
+ : '{ModuleCode} module with list page, tabbed detail, dedicated permissions'}"
380
+ - label: "{language == 'fr' ? 'Géré dans l\'app' : 'Managed in app'}"
381
+ description: "..."
382
+ - label: "{language == 'fr' ? 'Système externe' : 'External system'}"
383
+ description: "..."
384
+ - label: "{language == 'fr' ? 'Liste simple en config' : 'Simple config list'}"
385
+ description: "..."
386
+
387
+ IF recommendation = config_list:
388
+ - label: "{language == 'fr' ? 'Liste simple en config (Recommandé)' : 'Simple config list (Recommended)'}"
259
389
  description: "{language == 'fr'
260
- ? 'Les {entity_plural} sont créés et gérés dans cette application (liste simple)'
261
- : '{entity_plural} are created and managed in this application (simple list)'}"
390
+ ? 'Table de référence administrable, pas de module dédié'
391
+ : 'Admin-managed reference table, no dedicated module'}"
392
+ - label: "{language == 'fr' ? 'Géré dans l\'app' : 'Managed in app'}"
393
+ description: "..."
262
394
  - label: "{language == 'fr' ? 'Nouveau module dédié' : 'New dedicated module'}"
395
+ description: "..."
396
+ - label: "{language == 'fr' ? 'Système externe' : 'External system'}"
397
+ description: "..."
398
+
399
+ IF recommendation = in_app_section:
400
+ - label: "{language == 'fr' ? 'Géré dans l\'app (Recommandé)' : 'Managed in app (Recommended)'}"
263
401
  description: "{language == 'fr'
264
- ? 'Les {entity_plural} méritent leur propre module avec CRUD complet, permissions et navigation'
265
- : '{entity_plural} deserve their own module with full CRUD, permissions and navigation'}"
402
+ ? 'Accessible via un onglet dans la page détail de {parent_module}'
403
+ : 'Accessible via a tab in {parent_module} detail page'}"
404
+ - label: "{language == 'fr' ? 'Nouveau module dédié' : 'New dedicated module'}"
405
+ description: "..."
406
+ - label: "{language == 'fr' ? 'Liste simple en config' : 'Simple config list'}"
407
+ description: "..."
266
408
  - label: "{language == 'fr' ? 'Système externe' : 'External system'}"
409
+ description: "..."
410
+
411
+ IF recommendation = external_system:
412
+ - label: "{language == 'fr' ? 'Système externe (Recommandé)' : 'External system (Recommended)'}"
267
413
  description: "{language == 'fr'
268
414
  ? 'Les {entity_plural} viennent d\'un autre système (import ou API)'
269
415
  : '{entity_plural} come from another system (import or API)'}"
416
+ - label: "{language == 'fr' ? 'Nouveau module dédié' : 'New dedicated module'}"
417
+ description: "..."
418
+ - label: "{language == 'fr' ? 'Géré dans l\'app' : 'Managed in app'}"
419
+ description: "..."
270
420
  - label: "{language == 'fr' ? 'Liste simple en config' : 'Simple config list'}"
271
- description: "{language == 'fr'
272
- ? 'Juste une liste configurable par l\'admin, pas un module complet'
273
- : 'Just a configurable list managed by admin, not a full module'}"
421
+ description: "..."
422
+
423
+ IF confidence = LOW (no clear recommendation):
424
+ (all 4 options in neutral order, NO "(Recommandé)" tag)
274
425
  ```
275
426
 
276
- **Processing each answer:**
427
+ ##### PHASE 4 — Process Answer
277
428
 
278
429
  | Choice | Action |
279
430
  |--------|--------|
280
- | **Gérés dans l'app** | Entity stays as a child/section of the current module. Note in coverageMatrix. |
281
- | **Nouveau module dédié** | **Add new module to `{pre_analysis}.detected_modules[]`**. Flag for inclusion in decomposition (step-02). Add to `coverageMatrix` as mustHave with anticipated sections (list, detail, create, edit). This module becomes a dependency of the referencing module. |
431
+ | **Géré dans l'app** | Entity becomes a sub-entity of the parent module. Add as a **tab in the detail page** of the referencing module. Note in coverageMatrix with `parentModule` field. |
432
+ | **Nouveau module dédié** | **Add new module to `{pre_analysis}.detected_modules[]`** with the proposed architecture (sections, detail tabs, dependencies). Add to `coverageMatrix` as mustHave. The `list` section is ALWAYS the main section. Additional sections ONLY for distinct functional zones (dashboard, approve, import...). `create` and `edit` are ACTIONS within `list` and detail pages, NEVER standalone sections. |
282
433
  | **Système externe** | Flag for integration specification. Add to `coverageMatrix` as integration. Load `questionnaire/05-integrations.md` if not already loaded. |
283
- | **Liste simple en config** | Entity becomes a lookup/reference table (no dedicated module). Note in coverageMatrix as config data. |
434
+ | **Liste simple en config** | Entity becomes a lookup/reference table (no dedicated module, no section). Note in coverageMatrix as config data. |
284
435
 
285
- > **CRITICAL:** The "Nouveau module dédié" option is essential for detecting modules not mentioned in the original brief. Without it, complex entities get reduced to simple config lists when they deserve full CRUD management.
436
+ > **CRITICAL:** The intelligence of this step is in the ULTRATHINK analysis. The AI must REASON about domain coherence, score the entity, and recommend not just present 4 neutral options. The client can always override the recommendation, but they should benefit from expert architectural guidance.
286
437
 
287
438
  #### 4e. Risks & Success Criteria (ALWAYS — from `questionnaire/14-risk-assumptions.md` and `questionnaire/15-success-metrics.md`)
288
439
 
@@ -445,12 +596,17 @@ BEFORE transitioning to step-02:
445
596
  a. Create an entry in `cadrage.coverageMatrix[]`
446
597
  b. Assign it to mustHave, shouldHave, couldHave, or outOfScope
447
598
  c. Assign the module that will cover it (or null if cross-cutting)
448
- d. **List anticipated sections** (Level 4) based on module type and feature needs
599
+ d. **List anticipated sections** (Level 4) ONLY functional zones (see `references/entity-architecture-decision.md` section 4)
449
600
  e. **List anticipated resources** (Level 5) for each section
601
+ f. **List detail page tabs** — for entities accessible via click from `list`
602
+
603
+ > **SECTION RULE:** Sections are functional zones (list, dashboard, approve, import, rapport...).
604
+ > `create` and `edit` are ACTIONS within the `list` page (modal/drawer).
605
+ > `detail` is a page with tabs accessible by clicking a row in `list`, NOT a standalone section.
450
606
 
451
607
  4. **OUTPUT the matrix as text** (do NOT put it inside AskUserQuestion — it won't render):
452
608
 
453
- Print a markdown table with columns: **Fonctionnalité | Priorité | Module | Sections pressenties | Resources clés**
609
+ Print a markdown table with columns: **Fonctionnalité | Priorité | Module | Section | Resources clés | Onglets détail**
454
610
 
455
611
  Example:
456
612
  ```
@@ -458,13 +614,15 @@ Example:
458
614
  ? "Voici la matrice de couverture enrichie. J'ai identifié {N} fonctionnalités :"
459
615
  : "Here is the enriched coverage matrix. I identified {N} features:"}
460
616
 
461
- | Fonctionnalité | Priorité | Module | Sections pressenties | Resources clés |
462
- |---|---|---|---|---|
463
- | Gestion des employés | mustHave | Employees | list, detail, create, edit | employee-grid, employee-form, employee-card |
464
- | Saisie d'activités | mustHave | TimeTracking | list, create, edit | activity-grid, activity-form |
465
- | Saisie d'absences | mustHave | TimeTracking | list, create | absence-grid, absence-form, absence-calendar |
466
- | Rapports temps | mustHave | TimeTracking | dashboard, export | time-summary-chart, time-export-panel |
467
- | Soldes de congés | shouldHave | TimeTracking | detail | leave-balance-card |
617
+ | Fonctionnalité | Priorité | Module | Section | Resources clés | Onglets détail |
618
+ |---|---|---|---|---|---|
619
+ | Gestion des employés | mustHave | Employees | list | employee-grid, employee-filters, employee-form | Infos, Contrats, Documents |
620
+ | Suivi des activités | mustHave | TimeTracking | list | activity-grid, activity-filters, activity-form | Infos, Imputations |
621
+ | Saisie d'absences | mustHave | TimeTracking | list | absence-grid, absence-form, absence-calendar | Infos, Justificatifs |
622
+ | Rapports temps | shouldHave | TimeTracking | dashboard | time-kpi-cards, time-summary-chart | — |
623
+ | Validation absences | shouldHave | TimeTracking | approve | approval-queue, status-timeline | — |
624
+ | Export PDF/Excel | couldHave | TimeTracking | rapport | export-panel | — |
625
+ | Intégration paie | outOfScope | — | — | — | — |
468
626
  ```
469
627
 
470
628
  5. **THEN** (after the table is displayed) ask via AskUserQuestion:
@@ -487,6 +645,36 @@ options:
487
645
  - If a feature is in mustHave → it MUST have at least one anticipated section.
488
646
  - Accepted suggestions from Phase 4 must appear in the matrix.
489
647
 
648
+ **POST-CHECK — PRIORITY DISTRIBUTION (BLOCKING):**
649
+
650
+ ```
651
+ coverageItems = cadrage.coverageMatrix[]
652
+ mustHaveCount = coverageItems.filter(i => i.category === "mustHave").length
653
+ shouldHaveCount = coverageItems.filter(i => i.category === "shouldHave").length
654
+ couldHaveCount = coverageItems.filter(i => i.category === "couldHave").length
655
+ outOfScopeCount = coverageItems.filter(i => i.category === "outOfScope").length
656
+
657
+ IF shouldHaveCount === 0 AND couldHaveCount === 0 AND outOfScopeCount === 0:
658
+ → FAIL: ALL {mustHaveCount} items are mustHave — no distribution.
659
+ → ACTION: Return to Phase 3 section 4c and apply MoSCoW question.
660
+ → DO NOT write cadrage until at least shouldHave OR outOfScope has ≥ 1 item.
661
+ → EXCEPTION: If client explicitly confirmed "tout est indispensable" during
662
+ Phase 3 section 4c, accept but ADD a changelog entry:
663
+ "Client confirmed all {N} features as mustHave after MoSCoW challenge"
664
+ ```
665
+
666
+ **POST-CHECK — CROSS-CUTTING COVERAGE (WARNING):**
667
+
668
+ ```
669
+ FOR each item in coverageMatrix WHERE item.module === null:
670
+ IF item.category === "mustHave":
671
+ → WARNING: "{item.item}" is mustHave but has no assigned module.
672
+ → Ensure it is covered by infrastructure or a cross-cutting concern.
673
+ → Add a note explaining HOW it will be implemented (e.g., "handled by platform notification service").
674
+ IF item.anticipatedSections.length === 0 AND item.category !== "outOfScope":
675
+ → WARNING: "{item.item}" has no anticipated sections — will it be implemented?
676
+ ```
677
+
490
678
  ---
491
679
 
492
680
  ## WRITE & SUMMARY