@atlashub/smartstack-cli 4.23.0 → 4.24.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 (27) hide show
  1. package/package.json +1 -1
  2. package/templates/skills/ba-generate-html/html/ba-interactive.html +950 -1055
  3. package/templates/skills/ba-generate-html/html/src/scripts/01-data-init.js +1 -2
  4. package/templates/skills/ba-generate-html/html/src/scripts/02-navigation.js +0 -1
  5. package/templates/skills/ba-generate-html/html/src/scripts/03-render-cadrage.js +0 -39
  6. package/templates/skills/ba-generate-html/html/src/scripts/05-render-specs.js +0 -1
  7. package/templates/skills/ba-generate-html/html/src/scripts/07-render-handoff.js +0 -1
  8. package/templates/skills/ba-generate-html/html/src/scripts/08-editing.js +133 -135
  9. package/templates/skills/ba-generate-html/html/src/scripts/10-comments.js +199 -199
  10. package/templates/skills/ba-generate-html/html/src/scripts/11-review-panel.js +165 -166
  11. package/templates/skills/ba-generate-html/html/src/styles/05-modules.css +444 -454
  12. package/templates/skills/ba-generate-html/html/src/template.html +0 -49
  13. package/templates/skills/ba-generate-html/references/data-build.md +176 -182
  14. package/templates/skills/ba-generate-html/references/data-mapping.md +295 -301
  15. package/templates/skills/ba-generate-html/steps/step-01-collect.md +1 -1
  16. package/templates/skills/ba-generate-html/steps/step-02-build-data.md +0 -9
  17. package/templates/skills/derive-prd/SKILL.md +9 -9
  18. package/templates/skills/derive-prd/references/acceptance-criteria.md +166 -116
  19. package/templates/skills/derive-prd/references/entity-domain-mapping.md +5 -5
  20. package/templates/skills/derive-prd/references/handoff-file-templates.md +12 -12
  21. package/templates/skills/derive-prd/references/handoff-mappings.md +13 -14
  22. package/templates/skills/derive-prd/references/handoff-seeddata-generation.md +1 -1
  23. package/templates/skills/derive-prd/references/readiness-scoring.md +41 -50
  24. package/templates/skills/derive-prd/schemas/handoff-schema.json +2 -2
  25. package/templates/skills/derive-prd/steps/step-00-validate.md +73 -52
  26. package/templates/skills/derive-prd/steps/step-01-transform.md +86 -43
  27. package/templates/skills/ba-generate-html/html/src/partials/cadrage-risks.html +0 -48
@@ -1,301 +1,295 @@
1
- # HTML Data Mapping Reference
2
-
3
- > **Used by:** `/ba-generate-html` skill (step-02-build-data)
4
- > **Purpose:** Exact mapping from module JSON files to HTML FEATURE_DATA and EMBEDDED_ARTIFACTS objects
5
-
6
- ---
7
-
8
- ## FEATURE_DATA Mapping
9
-
10
- Build a JSON object following this **exact mapping** from index.json to the HTML data model:
11
-
12
- ```javascript
13
- {
14
- metadata: {
15
- applicationName: master.metadata.application, // e.g. "RH"
16
- applicationId: master.id, // e.g. "FEAT-001"
17
- version: master.version, // e.g. "1.0"
18
- createdAt: master.metadata.createdAt,
19
- lastModified: master.metadata.updatedAt,
20
- analysisMode: master.metadata.analysisMode || "interactive" // always "interactive" in JSON format
21
- },
22
- cadrage: {
23
- // CONTEXT SECTION — lean format (merged from problem/asIs/toBe)
24
- // NOTE: 01-data-init.js has backward compat for old problem/current/vision format
25
- context: {
26
- problem: master.cadrage.problem || "", // flat string from index.json
27
- trigger: master.cadrage.trigger || "", // flat string from index.json
28
- currentSituation: master.cadrage.asIs || "", // flat string from index.json
29
- desiredSituation: master.cadrage.toBe || "", // flat string from index.json
30
- painPoints: (master.cadrage.stakeholders || [])
31
- .flatMap(s => s.painPoints || []).join("\n"), // aggregate all painPoints
32
- acceptanceCriteria: (master.cadrage.acceptanceCriteria || [])
33
- .map(ac => ac.criterion).join("\n") // AC → newline-separated string
34
- },
35
- stakeholders: master.cadrage.stakeholders.map(s => ({
36
- role: s.role,
37
- function: s.function || "",
38
- tasks: s.tasks || [],
39
- frequency: mapFrequency(s.frequency), // "Quotidien"→"daily", etc.
40
- access: mapAccess(s.involvement), // "decision-maker"→"admin", "end-user"→"contributor"
41
- frustrations: (s.painPoints || []).join("\n")
42
- })),
43
- scope: {
44
- vital: (master.cadrage.globalScope.mustHave || [])
45
- .map(item => ({ name: item, description: "" })), // string[] → {name,description}[]
46
- important: (master.cadrage.globalScope.shouldHave || [])
47
- .map(item => ({ name: item, description: "" })),
48
- optional: (master.cadrage.globalScope.couldHave || [])
49
- .map(item => ({ name: item, description: "" })),
50
- excluded: (master.cadrage.globalScope.outOfScope || [])
51
- .map(item => ({ name: item, description: "" }))
52
- },
53
- risks: (master.cadrage.risks || []).map(r => ({
54
- description: r.description,
55
- probability: r.probability, // "high" | "medium" | "low"
56
- impact: r.impact,
57
- mitigation: r.mitigation || ""
58
- })),
59
- criteria: (master.cadrage.acceptanceCriteria || []).map(ac => ({
60
- text: ac.criterion,
61
- validated: ac.validated || false
62
- }))
63
- },
64
- modules: master.modules.map(m => ({
65
- code: m.code,
66
- name: m.name || m.code, // display name (MANDATORY, separate from code)
67
- description: m.description || "",
68
- featureType: m.featureType || "data-centric",
69
- priority: m.priority || "must",
70
- entities: m.entities || [],
71
- anticipatedSections: m.anticipatedSections || [], // [{code, description, resources[]}]
72
- dependencies: m.dependencies || [],
73
- dependents: m.dependents || [],
74
- estimatedComplexity: m.estimatedComplexity || "medium",
75
- status: m.status || "handed-off"
76
- })),
77
- dependencies: (master.dependencyGraph?.edges || []).map(e => ({
78
- from: e.from,
79
- to: e.to,
80
- description: e.description || ""
81
- })),
82
- moduleSpecs: {
83
- // FOR EACH module: read module index.json, then map:
84
- // [moduleCode]: { useCases, businessRules, entities, permissions, notes, mockupNotes }
85
- },
86
- consolidation: {
87
- interactions: (master.consolidation?.crossModuleInteractions || []).map(i => ({
88
- from: i.fromModule,
89
- to: i.toModule,
90
- description: i.description || ""
91
- })),
92
- e2eFlows: (master.consolidation?.e2eFlows || []).map(f => ({
93
- name: f.name,
94
- steps: (f.steps || []).map(s => ({ module: s.module, action: s.action })),
95
- actors: (f.steps || []).map(s => s.permission).join(", ")
96
- }))
97
- },
98
- handoff: master.handoff || {}
99
- }
100
- ```
101
-
102
- ### Module Specs Mapping
103
-
104
- For EACH module in `master.modules[]`:
105
-
106
- 1. Read the module index.json at `master.modules[i].featureJsonPath`
107
- 2. Map to `moduleSpecs[moduleCode]`:
108
-
109
- ```javascript
110
- moduleSpecs[moduleCode] = {
111
- useCases: (moduleFeature.specification?.useCases || []).map(uc => ({
112
- name: uc.name,
113
- actor: uc.primaryActor,
114
- steps: (uc.mainScenario || []).join("\n"), // array → newline-separated string
115
- alternative: (uc.alternativeScenarios || [])
116
- .map(a => a.name + ": " + (a.steps || []).join(", ")).join("\n")
117
- })),
118
- businessRules: (moduleFeature.analysis?.businessRules || []).map(br => ({
119
- name: br.name,
120
- category: br.category, // "validation"|"calculation"|"workflow"|"security"|"data"
121
- statement: br.statement,
122
- example: (br.examples || []).map(e => e.input + " → " + e.expected).join("; ")
123
- })),
124
- entities: (moduleFeature.analysis?.entities || []).map(ent => ({
125
- name: ent.name,
126
- description: ent.description || "",
127
- attributes: (ent.attributes || []).map(a => ({
128
- name: a.name,
129
- type: a.type || "string", // string, int, decimal, date, datetime, bool, enum, guid, text
130
- required: a.required || false,
131
- description: a.description || ""
132
- })),
133
- relationships: (ent.relationships || []).map(r =>
134
- r.target + " (" + r.type + ") - " + (r.description || "")
135
- )
136
- })),
137
- permissions: buildPermissionKeys(moduleFeature), // see below
138
- notes: "",
139
- mockupNotes: "" // Deprecated: wireframes now embedded separately in EMBEDDED_ARTIFACTS
140
- }
141
- ```
142
-
143
- ### Permission Keys Function
144
-
145
- The HTML uses `"Role|Action"` format (e.g. `"RH Admin|Consulter"`):
146
-
147
- ```javascript
148
- function buildPermissionKeys(moduleFeature) {
149
- const keys = [];
150
- const matrix = moduleFeature.specification?.permissionMatrix;
151
- if (!matrix) return keys;
152
- const actionMap = { read: "Consulter", create: "Creer", update: "Modifier",
153
- delete: "Supprimer", validate: "Valider", export: "Exporter",
154
- submit: "Valider", import: "Creer" };
155
- (matrix.roleAssignments || []).forEach(ra => {
156
- (ra.permissions || []).forEach(permPath => {
157
- const action = permPath.split(".").pop(); // last segment = action
158
- if (action === "*") {
159
- // Wildcard: expand to all standard actions
160
- Object.values(actionMap).forEach(uiAction => {
161
- const key = ra.role + "|" + uiAction;
162
- if (!keys.includes(key)) keys.push(key);
163
- });
164
- } else {
165
- const uiAction = actionMap[action] || action;
166
- keys.push(ra.role + "|" + uiAction);
167
- }
168
- });
169
- });
170
- return keys;
171
- }
172
- ```
173
-
174
- ### Frequency Mapping
175
-
176
- ```
177
- "Quotidien" → "daily", "Hebdomadaire" → "weekly", "Mensuel" → "monthly"
178
- Default: "daily"
179
- ```
180
-
181
- ### Access Mapping (involvement → access)
182
-
183
- ```
184
- "decision-maker" → "admin", "end-user" with manager-like tasks → "manager"
185
- "end-user" "contributor", "observer" → "viewer"
186
- Default: "contributor"
187
- ```
188
-
189
- ---
190
-
191
- ## EMBEDDED_ARTIFACTS Mapping
192
-
193
- > **FIELD RENAME WARNING:** Module JSON files store wireframes with `mockupFormat` and `mockup` fields.
194
- > The HTML renderer reads `format` and `content`. You MUST rename: `mockupFormat` → `format`, `mockup` → `content`.
195
- > Failure to rename = empty mockup display in the browser.
196
-
197
- Build a JSON object containing ALL visual artifacts from module JSON files (index.json):
198
-
199
- ```javascript
200
- {
201
- wireframes: {
202
- // FOR EACH module: extract all wireframes from module index.json
203
- // [moduleCode]: [ {screen, format, content, elements, componentMapping, layout, description} ]
204
- },
205
- e2eFlows: [
206
- // Extract from master consolidation.e2eFlows[]
207
- // { name, diagram, steps, actors }
208
- ],
209
- dependencyGraph: {
210
- // Extract from master dependencyGraph
211
- // nodes: [ {id, label, type} ], edges: [ {from, to, description} ]
212
- }
213
- }
214
- ```
215
-
216
- ### Wireframes Mapping
217
-
218
- For EACH module in `master.modules[]`:
219
-
220
- ```javascript
221
- // Read the module index.json file
222
- const moduleFeature = readModuleFeature(moduleCode);
223
- const wireframes = (moduleFeature.specification?.uiWireframes || []).map(wf => ({
224
- screen: wf.screen, // e.g. "UM-list", "UM-form"
225
- section: wf.section, // e.g. "list", "form"
226
- format: wf.mockupFormat || "ascii", // "ascii" | "svg"
227
- content: wf.mockup, // ASCII art or SVG markup
228
- description: wf.description || "",
229
- elements: wf.elements || [], // ["DataGrid", "FilterBar", ...]
230
- actions: wf.actions || [], // ["filter", "sort", "create", ...]
231
- componentMapping: wf.componentMapping || [], // [{ wireframeElement, reactComponent }]
232
- layout: wf.layout || null, // { type, regions: [...] }
233
- permissionsRequired: wf.permissionsRequired || []
234
- }));
235
-
236
- // Store in artifacts object
237
- EMBEDDED_ARTIFACTS.wireframes[moduleCode] = wireframes;
238
- ```
239
-
240
- ### E2E Flows Mapping
241
-
242
- From master consolidation:
243
-
244
- ```javascript
245
- EMBEDDED_ARTIFACTS.e2eFlows = (master.consolidation?.e2eFlows || []).map(flow => ({
246
- name: flow.name,
247
- diagram: generateE2EDiagram(flow), // ASCII diagram from flow.steps[]
248
- steps: flow.steps || [], // [{ module, action, permission }]
249
- actors: Array.from(new Set((flow.steps || [])
250
- .map(s => s.permission?.split(".")[0]) // Extract role from permission path
251
- .filter(Boolean))).join(", "),
252
- modules: Array.from(new Set((flow.steps || [])
253
- .map(s => s.module))).join(" ")
254
- }));
255
-
256
- function generateE2EDiagram(flow) {
257
- // Generate ASCII diagram from flow.steps[]
258
- // Example output:
259
- // "Customer ──[read]──→ Order ──[create]──→ Invoice ──[send]──→"
260
- // " (Orders) (Orders) (Invoices)"
261
- // " Contributor Manager System"
262
-
263
- const stepDiagrams = (flow.steps || []).map(s =>
264
- `${s.action}(${s.module})`
265
- ).join(" ──→ ");
266
-
267
- return stepDiagrams;
268
- }
269
- ```
270
-
271
- ### Dependency Graph Mapping
272
-
273
- From master dependencyGraph:
274
-
275
- ```javascript
276
- EMBEDDED_ARTIFACTS.dependencyGraph = {
277
- nodes: (master.modules || []).map(m => ({
278
- id: m.code,
279
- label: m.code,
280
- type: m.featureType || "data-centric"
281
- })),
282
- edges: (master.dependencyGraph?.edges || []).map(e => ({
283
- from: e.from,
284
- to: e.to,
285
- description: e.description || ""
286
- }))
287
- };
288
- ```
289
-
290
- ---
291
-
292
- ## Usage in step-05-deploy
293
-
294
- 1. Serialize the FEATURE_DATA object as JSON (with 2-space indentation for readability)
295
- 2. Serialize the EMBEDDED_ARTIFACTS object as JSON (with 2-space indentation)
296
- 3. Replace `{{FEATURE_DATA}}` with the serialized FEATURE_DATA JSON
297
- 4. Replace `{{EMBEDDED_ARTIFACTS}}` with the serialized EMBEDDED_ARTIFACTS JSON
298
- 5. Replace `{{APPLICATION_NAME}}` → `{application_name}` (still used in `<title>` and header)
299
- 6. Replace `{{APPLICATION_ID}}` → `{feature_id}` (still used in `APP_KEY`)
300
- 7. Replace `{{VERSION}}` → `{version}`
301
- 8. Replace `{{CREATED_AT}}` → `{ISO timestamp}`
1
+ # HTML Data Mapping Reference
2
+
3
+ > **Used by:** `/ba-generate-html` skill (step-02-build-data)
4
+ > **Purpose:** Exact mapping from module JSON files to HTML FEATURE_DATA and EMBEDDED_ARTIFACTS objects
5
+
6
+ ---
7
+
8
+ ## FEATURE_DATA Mapping
9
+
10
+ Build a JSON object following this **exact mapping** from index.json to the HTML data model:
11
+
12
+ ```javascript
13
+ {
14
+ metadata: {
15
+ applicationName: master.metadata.application, // e.g. "RH"
16
+ applicationId: master.id, // e.g. "FEAT-001"
17
+ version: master.version, // e.g. "1.0"
18
+ createdAt: master.metadata.createdAt,
19
+ lastModified: master.metadata.updatedAt,
20
+ analysisMode: master.metadata.analysisMode || "interactive" // always "interactive" in JSON format
21
+ },
22
+ cadrage: {
23
+ // CONTEXT SECTION — lean format (merged from problem/asIs/toBe)
24
+ // NOTE: 01-data-init.js has backward compat for old problem/current/vision format
25
+ context: {
26
+ problem: master.cadrage.problem || "", // flat string from index.json
27
+ trigger: master.cadrage.trigger || "", // flat string from index.json
28
+ currentSituation: master.cadrage.asIs || "", // flat string from index.json
29
+ desiredSituation: master.cadrage.toBe || "", // flat string from index.json
30
+ painPoints: (master.cadrage.stakeholders || [])
31
+ .flatMap(s => s.painPoints || []).join("\n"), // aggregate all painPoints
32
+ acceptanceCriteria: (master.cadrage.acceptanceCriteria || [])
33
+ .map(ac => ac.criterion).join("\n") // AC → newline-separated string
34
+ },
35
+ stakeholders: master.cadrage.stakeholders.map(s => ({
36
+ role: s.role,
37
+ function: s.function || "",
38
+ tasks: s.tasks || [],
39
+ frequency: mapFrequency(s.frequency), // "Quotidien"→"daily", etc.
40
+ access: mapAccess(s.involvement), // "decision-maker"→"admin", "end-user"→"contributor"
41
+ frustrations: (s.painPoints || []).join("\n")
42
+ })),
43
+ scope: {
44
+ vital: (master.cadrage.globalScope.mustHave || [])
45
+ .map(item => ({ name: item, description: "" })), // string[] → {name,description}[]
46
+ important: (master.cadrage.globalScope.shouldHave || [])
47
+ .map(item => ({ name: item, description: "" })),
48
+ optional: (master.cadrage.globalScope.couldHave || [])
49
+ .map(item => ({ name: item, description: "" })),
50
+ excluded: (master.cadrage.globalScope.outOfScope || [])
51
+ .map(item => ({ name: item, description: "" }))
52
+ },
53
+ criteria: (master.cadrage.acceptanceCriteria || []).map(ac => ({
54
+ text: ac.criterion,
55
+ validated: ac.validated || false
56
+ }))
57
+ },
58
+ modules: master.modules.map(m => ({
59
+ code: m.code,
60
+ name: m.name || m.code, // display name (MANDATORY, separate from code)
61
+ description: m.description || "",
62
+ featureType: m.featureType || "data-centric",
63
+ priority: m.priority || "must",
64
+ entities: m.entities || [],
65
+ anticipatedSections: m.anticipatedSections || [], // [{code, description, resources[]}]
66
+ dependencies: m.dependencies || [],
67
+ dependents: m.dependents || [],
68
+ estimatedComplexity: m.estimatedComplexity || "medium",
69
+ status: m.status || "handed-off"
70
+ })),
71
+ dependencies: (master.dependencyGraph?.edges || []).map(e => ({
72
+ from: e.from,
73
+ to: e.to,
74
+ description: e.description || ""
75
+ })),
76
+ moduleSpecs: {
77
+ // FOR EACH module: read module index.json, then map:
78
+ // [moduleCode]: { useCases, businessRules, entities, permissions, notes, mockupNotes }
79
+ },
80
+ consolidation: {
81
+ interactions: (master.consolidation?.crossModuleInteractions || []).map(i => ({
82
+ from: i.fromModule,
83
+ to: i.toModule,
84
+ description: i.description || ""
85
+ })),
86
+ e2eFlows: (master.consolidation?.e2eFlows || []).map(f => ({
87
+ name: f.name,
88
+ steps: (f.steps || []).map(s => ({ module: s.module, action: s.action })),
89
+ actors: (f.steps || []).map(s => s.permission).join(", ")
90
+ }))
91
+ },
92
+ handoff: master.handoff || {}
93
+ }
94
+ ```
95
+
96
+ ### Module Specs Mapping
97
+
98
+ For EACH module in `master.modules[]`:
99
+
100
+ 1. Read the module index.json at `master.modules[i].featureJsonPath`
101
+ 2. Map to `moduleSpecs[moduleCode]`:
102
+
103
+ ```javascript
104
+ moduleSpecs[moduleCode] = {
105
+ useCases: (moduleFeature.specification?.useCases || []).map(uc => ({
106
+ name: uc.name,
107
+ actor: uc.primaryActor,
108
+ steps: (uc.mainScenario || []).join("\n"), // array → newline-separated string
109
+ alternative: (uc.alternativeScenarios || [])
110
+ .map(a => a.name + ": " + (a.steps || []).join(", ")).join("\n")
111
+ })),
112
+ businessRules: (moduleFeature.analysis?.businessRules || []).map(br => ({
113
+ name: br.name,
114
+ category: br.category, // "validation"|"calculation"|"workflow"|"security"|"data"
115
+ statement: br.statement,
116
+ example: (br.examples || []).map(e => e.input + " " + e.expected).join("; ")
117
+ })),
118
+ entities: (moduleFeature.analysis?.entities || []).map(ent => ({
119
+ name: ent.name,
120
+ description: ent.description || "",
121
+ attributes: (ent.attributes || []).map(a => ({
122
+ name: a.name,
123
+ type: a.type || "string", // string, int, decimal, date, datetime, bool, enum, guid, text
124
+ required: a.required || false,
125
+ description: a.description || ""
126
+ })),
127
+ relationships: (ent.relationships || []).map(r =>
128
+ r.target + " (" + r.type + ") - " + (r.description || "")
129
+ )
130
+ })),
131
+ permissions: buildPermissionKeys(moduleFeature), // see below
132
+ notes: "",
133
+ mockupNotes: "" // Deprecated: wireframes now embedded separately in EMBEDDED_ARTIFACTS
134
+ }
135
+ ```
136
+
137
+ ### Permission Keys Function
138
+
139
+ The HTML uses `"Role|Action"` format (e.g. `"RH Admin|Consulter"`):
140
+
141
+ ```javascript
142
+ function buildPermissionKeys(moduleFeature) {
143
+ const keys = [];
144
+ const matrix = moduleFeature.specification?.permissionMatrix;
145
+ if (!matrix) return keys;
146
+ const actionMap = { read: "Consulter", create: "Creer", update: "Modifier",
147
+ delete: "Supprimer", validate: "Valider", export: "Exporter",
148
+ submit: "Valider", import: "Creer" };
149
+ (matrix.roleAssignments || []).forEach(ra => {
150
+ (ra.permissions || []).forEach(permPath => {
151
+ const action = permPath.split(".").pop(); // last segment = action
152
+ if (action === "*") {
153
+ // Wildcard: expand to all standard actions
154
+ Object.values(actionMap).forEach(uiAction => {
155
+ const key = ra.role + "|" + uiAction;
156
+ if (!keys.includes(key)) keys.push(key);
157
+ });
158
+ } else {
159
+ const uiAction = actionMap[action] || action;
160
+ keys.push(ra.role + "|" + uiAction);
161
+ }
162
+ });
163
+ });
164
+ return keys;
165
+ }
166
+ ```
167
+
168
+ ### Frequency Mapping
169
+
170
+ ```
171
+ "Quotidien" → "daily", "Hebdomadaire" → "weekly", "Mensuel" → "monthly"
172
+ Default: "daily"
173
+ ```
174
+
175
+ ### Access Mapping (involvement → access)
176
+
177
+ ```
178
+ "decision-maker" "admin", "end-user" with manager-like tasks → "manager"
179
+ "end-user" → "contributor", "observer" → "viewer"
180
+ Default: "contributor"
181
+ ```
182
+
183
+ ---
184
+
185
+ ## EMBEDDED_ARTIFACTS Mapping
186
+
187
+ > **FIELD RENAME WARNING:** Module JSON files store wireframes with `mockupFormat` and `mockup` fields.
188
+ > The HTML renderer reads `format` and `content`. You MUST rename: `mockupFormat` → `format`, `mockup` → `content`.
189
+ > Failure to rename = empty mockup display in the browser.
190
+
191
+ Build a JSON object containing ALL visual artifacts from module JSON files (index.json):
192
+
193
+ ```javascript
194
+ {
195
+ wireframes: {
196
+ // FOR EACH module: extract all wireframes from module index.json
197
+ // [moduleCode]: [ {screen, format, content, elements, componentMapping, layout, description} ]
198
+ },
199
+ e2eFlows: [
200
+ // Extract from master consolidation.e2eFlows[]
201
+ // { name, diagram, steps, actors }
202
+ ],
203
+ dependencyGraph: {
204
+ // Extract from master dependencyGraph
205
+ // nodes: [ {id, label, type} ], edges: [ {from, to, description} ]
206
+ }
207
+ }
208
+ ```
209
+
210
+ ### Wireframes Mapping
211
+
212
+ For EACH module in `master.modules[]`:
213
+
214
+ ```javascript
215
+ // Read the module index.json file
216
+ const moduleFeature = readModuleFeature(moduleCode);
217
+ const wireframes = (moduleFeature.specification?.uiWireframes || []).map(wf => ({
218
+ screen: wf.screen, // e.g. "UM-list", "UM-form"
219
+ section: wf.section, // e.g. "list", "form"
220
+ format: wf.mockupFormat || "ascii", // "ascii" | "svg"
221
+ content: wf.mockup, // ASCII art or SVG markup
222
+ description: wf.description || "",
223
+ elements: wf.elements || [], // ["DataGrid", "FilterBar", ...]
224
+ actions: wf.actions || [], // ["filter", "sort", "create", ...]
225
+ componentMapping: wf.componentMapping || [], // [{ wireframeElement, reactComponent }]
226
+ layout: wf.layout || null, // { type, regions: [...] }
227
+ permissionsRequired: wf.permissionsRequired || []
228
+ }));
229
+
230
+ // Store in artifacts object
231
+ EMBEDDED_ARTIFACTS.wireframes[moduleCode] = wireframes;
232
+ ```
233
+
234
+ ### E2E Flows Mapping
235
+
236
+ From master consolidation:
237
+
238
+ ```javascript
239
+ EMBEDDED_ARTIFACTS.e2eFlows = (master.consolidation?.e2eFlows || []).map(flow => ({
240
+ name: flow.name,
241
+ diagram: generateE2EDiagram(flow), // ASCII diagram from flow.steps[]
242
+ steps: flow.steps || [], // [{ module, action, permission }]
243
+ actors: Array.from(new Set((flow.steps || [])
244
+ .map(s => s.permission?.split(".")[0]) // Extract role from permission path
245
+ .filter(Boolean))).join(", "),
246
+ modules: Array.from(new Set((flow.steps || [])
247
+ .map(s => s.module))).join(" ")
248
+ }));
249
+
250
+ function generateE2EDiagram(flow) {
251
+ // Generate ASCII diagram from flow.steps[]
252
+ // Example output:
253
+ // "Customer ──[read]──→ Order ──[create]──→ Invoice ──[send]──→"
254
+ // " (Orders) (Orders) (Invoices)"
255
+ // " Contributor Manager System"
256
+
257
+ const stepDiagrams = (flow.steps || []).map(s =>
258
+ `${s.action}(${s.module})`
259
+ ).join(" ──→ ");
260
+
261
+ return stepDiagrams;
262
+ }
263
+ ```
264
+
265
+ ### Dependency Graph Mapping
266
+
267
+ From master dependencyGraph:
268
+
269
+ ```javascript
270
+ EMBEDDED_ARTIFACTS.dependencyGraph = {
271
+ nodes: (master.modules || []).map(m => ({
272
+ id: m.code,
273
+ label: m.code,
274
+ type: m.featureType || "data-centric"
275
+ })),
276
+ edges: (master.dependencyGraph?.edges || []).map(e => ({
277
+ from: e.from,
278
+ to: e.to,
279
+ description: e.description || ""
280
+ }))
281
+ };
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Usage in step-05-deploy
287
+
288
+ 1. Serialize the FEATURE_DATA object as JSON (with 2-space indentation for readability)
289
+ 2. Serialize the EMBEDDED_ARTIFACTS object as JSON (with 2-space indentation)
290
+ 3. Replace `{{FEATURE_DATA}}` with the serialized FEATURE_DATA JSON
291
+ 4. Replace `{{EMBEDDED_ARTIFACTS}}` with the serialized EMBEDDED_ARTIFACTS JSON
292
+ 5. Replace `{{APPLICATION_NAME}}` → `{application_name}` (still used in `<title>` and header)
293
+ 6. Replace `{{APPLICATION_ID}}` → `{feature_id}` (still used in `APP_KEY`)
294
+ 7. Replace `{{VERSION}}` `{version}`
295
+ 8. Replace `{{CREATED_AT}}` `{ISO timestamp}`
@@ -57,7 +57,7 @@ ELSE:
57
57
  collected_data = {
58
58
  master: {
59
59
  index: READ(index.json), // metadata, modules[], consolidation, handoff
60
- cadrage: READ(cadrage.json) // context, stakeholders, scope, risks
60
+ cadrage: READ(cadrage.json) // context, stakeholders, scope
61
61
  },
62
62
  modules: {}
63
63
  }
@@ -69,15 +69,6 @@ scope: {
69
69
 
70
70
  > Safety net: also check `master.cadrage.coverageMatrix` as alternative source for scope items.
71
71
 
72
- **cadrage.risks:**
73
- ```javascript
74
- risks: (master.cadrage.risks || []).map(r => ({
75
- description: r.description,
76
- probability: r.probability,
77
- impact: r.impact,
78
- mitigation: r.mitigation || ""
79
- }))
80
- ```
81
72
 
82
73
  **modules[]:**
83
74
  ```javascript