@atlashub/smartstack-cli 4.22.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 (36) hide show
  1. package/package.json +1 -1
  2. package/templates/skills/ba-design-ui/SKILL.md +91 -0
  3. package/templates/skills/ba-design-ui/steps/step-01-screens.md +177 -0
  4. package/templates/skills/ba-design-ui/steps/step-02-wireframes.md +140 -0
  5. package/templates/skills/ba-design-ui/steps/step-03-navigation.md +134 -0
  6. package/templates/skills/ba-generate-html/SKILL.md +0 -1
  7. package/templates/skills/ba-generate-html/html/ba-interactive.html +950 -1055
  8. package/templates/skills/ba-generate-html/html/src/scripts/01-data-init.js +1 -2
  9. package/templates/skills/ba-generate-html/html/src/scripts/02-navigation.js +0 -1
  10. package/templates/skills/ba-generate-html/html/src/scripts/03-render-cadrage.js +0 -39
  11. package/templates/skills/ba-generate-html/html/src/scripts/05-render-specs.js +0 -1
  12. package/templates/skills/ba-generate-html/html/src/scripts/07-render-handoff.js +0 -1
  13. package/templates/skills/ba-generate-html/html/src/scripts/08-editing.js +133 -135
  14. package/templates/skills/ba-generate-html/html/src/scripts/10-comments.js +199 -199
  15. package/templates/skills/ba-generate-html/html/src/scripts/11-review-panel.js +165 -166
  16. package/templates/skills/ba-generate-html/html/src/styles/05-modules.css +444 -454
  17. package/templates/skills/ba-generate-html/html/src/template.html +0 -49
  18. package/templates/skills/ba-generate-html/references/data-build.md +176 -182
  19. package/templates/skills/ba-generate-html/references/data-mapping.md +295 -299
  20. package/templates/skills/ba-generate-html/steps/step-01-collect.md +4 -22
  21. package/templates/skills/ba-generate-html/steps/step-02-build-data.md +2 -11
  22. package/templates/skills/ba-review/SKILL.md +16 -1
  23. package/templates/skills/ba-review/steps/step-01-apply.md +60 -10
  24. package/templates/skills/business-analyse/SKILL.md +19 -15
  25. package/templates/skills/business-analyse/steps/step-03-specify.md +9 -38
  26. package/templates/skills/derive-prd/SKILL.md +9 -9
  27. package/templates/skills/derive-prd/references/acceptance-criteria.md +166 -116
  28. package/templates/skills/derive-prd/references/entity-domain-mapping.md +5 -5
  29. package/templates/skills/derive-prd/references/handoff-file-templates.md +12 -12
  30. package/templates/skills/derive-prd/references/handoff-mappings.md +13 -14
  31. package/templates/skills/derive-prd/references/handoff-seeddata-generation.md +1 -1
  32. package/templates/skills/derive-prd/references/readiness-scoring.md +41 -50
  33. package/templates/skills/derive-prd/schemas/handoff-schema.json +2 -2
  34. package/templates/skills/derive-prd/steps/step-00-validate.md +73 -52
  35. package/templates/skills/derive-prd/steps/step-01-transform.md +86 -43
  36. package/templates/skills/ba-generate-html/html/src/partials/cadrage-risks.html +0 -48
@@ -1,299 +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
- description: a.description || ""
130
- })),
131
- relationships: (ent.relationships || []).map(r =>
132
- r.target + " (" + r.type + ") - " + (r.description || "")
133
- )
134
- })),
135
- permissions: buildPermissionKeys(moduleFeature), // see below
136
- notes: "",
137
- mockupNotes: "" // Deprecated: wireframes now embedded separately in EMBEDDED_ARTIFACTS
138
- }
139
- ```
140
-
141
- ### Permission Keys Function
142
-
143
- The HTML uses `"Role|Action"` format (e.g. `"RH Admin|Consulter"`):
144
-
145
- ```javascript
146
- function buildPermissionKeys(moduleFeature) {
147
- const keys = [];
148
- const matrix = moduleFeature.specification?.permissionMatrix;
149
- if (!matrix) return keys;
150
- const actionMap = { read: "Consulter", create: "Creer", update: "Modifier",
151
- delete: "Supprimer", validate: "Valider", export: "Exporter",
152
- submit: "Valider", import: "Creer" };
153
- (matrix.roleAssignments || []).forEach(ra => {
154
- (ra.permissions || []).forEach(permPath => {
155
- const action = permPath.split(".").pop(); // last segment = action
156
- if (action === "*") {
157
- // Wildcard: expand to all standard actions
158
- Object.values(actionMap).forEach(uiAction => {
159
- const key = ra.role + "|" + uiAction;
160
- if (!keys.includes(key)) keys.push(key);
161
- });
162
- } else {
163
- const uiAction = actionMap[action] || action;
164
- keys.push(ra.role + "|" + uiAction);
165
- }
166
- });
167
- });
168
- return keys;
169
- }
170
- ```
171
-
172
- ### Frequency Mapping
173
-
174
- ```
175
- "Quotidien" "daily", "Hebdomadaire""weekly", "Mensuel" → "monthly"
176
- Default: "daily"
177
- ```
178
-
179
- ### Access Mapping (involvementaccess)
180
-
181
- ```
182
- "decision-maker" → "admin", "end-user" with manager-like tasks → "manager"
183
- "end-user" → "contributor", "observer" → "viewer"
184
- Default: "contributor"
185
- ```
186
-
187
- ---
188
-
189
- ## EMBEDDED_ARTIFACTS Mapping
190
-
191
- > **FIELD RENAME WARNING:** Module JSON files store wireframes with `mockupFormat` and `mockup` fields.
192
- > The HTML renderer reads `format` and `content`. You MUST rename: `mockupFormat` → `format`, `mockup` → `content`.
193
- > Failure to rename = empty mockup display in the browser.
194
-
195
- Build a JSON object containing ALL visual artifacts from module JSON files (index.json):
196
-
197
- ```javascript
198
- {
199
- wireframes: {
200
- // FOR EACH module: extract all wireframes from module index.json
201
- // [moduleCode]: [ {screen, format, content, elements, componentMapping, layout, description} ]
202
- },
203
- e2eFlows: [
204
- // Extract from master consolidation.e2eFlows[]
205
- // { name, diagram, steps, actors }
206
- ],
207
- dependencyGraph: {
208
- // Extract from master dependencyGraph
209
- // nodes: [ {id, label, type} ], edges: [ {from, to, description} ]
210
- }
211
- }
212
- ```
213
-
214
- ### Wireframes Mapping
215
-
216
- For EACH module in `master.modules[]`:
217
-
218
- ```javascript
219
- // Read the module index.json file
220
- const moduleFeature = readModuleFeature(moduleCode);
221
- const wireframes = (moduleFeature.specification?.uiWireframes || []).map(wf => ({
222
- screen: wf.screen, // e.g. "UM-list", "UM-form"
223
- section: wf.section, // e.g. "list", "form"
224
- format: wf.mockupFormat || "ascii", // "ascii" | "svg"
225
- content: wf.mockup, // ASCII art or SVG markup
226
- description: wf.description || "",
227
- elements: wf.elements || [], // ["DataGrid", "FilterBar", ...]
228
- actions: wf.actions || [], // ["filter", "sort", "create", ...]
229
- componentMapping: wf.componentMapping || [], // [{ wireframeElement, reactComponent }]
230
- layout: wf.layout || null, // { type, regions: [...] }
231
- permissionsRequired: wf.permissionsRequired || []
232
- }));
233
-
234
- // Store in artifacts object
235
- EMBEDDED_ARTIFACTS.wireframes[moduleCode] = wireframes;
236
- ```
237
-
238
- ### E2E Flows Mapping
239
-
240
- From master consolidation:
241
-
242
- ```javascript
243
- EMBEDDED_ARTIFACTS.e2eFlows = (master.consolidation?.e2eFlows || []).map(flow => ({
244
- name: flow.name,
245
- diagram: generateE2EDiagram(flow), // ASCII diagram from flow.steps[]
246
- steps: flow.steps || [], // [{ module, action, permission }]
247
- actors: Array.from(new Set((flow.steps || [])
248
- .map(s => s.permission?.split(".")[0]) // Extract role from permission path
249
- .filter(Boolean))).join(", "),
250
- modules: Array.from(new Set((flow.steps || [])
251
- .map(s => s.module))).join(" ")
252
- }));
253
-
254
- function generateE2EDiagram(flow) {
255
- // Generate ASCII diagram from flow.steps[]
256
- // Example output:
257
- // "Customer ──[read]──→ Order ──[create]──→ Invoice ──[send]──→"
258
- // " (Orders) (Orders) (Invoices)"
259
- // " Contributor Manager System"
260
-
261
- const stepDiagrams = (flow.steps || []).map(s =>
262
- `${s.action}(${s.module})`
263
- ).join(" ──→ ");
264
-
265
- return stepDiagrams;
266
- }
267
- ```
268
-
269
- ### Dependency Graph Mapping
270
-
271
- From master dependencyGraph:
272
-
273
- ```javascript
274
- EMBEDDED_ARTIFACTS.dependencyGraph = {
275
- nodes: (master.modules || []).map(m => ({
276
- id: m.code,
277
- label: m.code,
278
- type: m.featureType || "data-centric"
279
- })),
280
- edges: (master.dependencyGraph?.edges || []).map(e => ({
281
- from: e.from,
282
- to: e.to,
283
- description: e.description || ""
284
- }))
285
- };
286
- ```
287
-
288
- ---
289
-
290
- ## Usage in step-05-deploy
291
-
292
- 1. Serialize the FEATURE_DATA object as JSON (with 2-space indentation for readability)
293
- 2. Serialize the EMBEDDED_ARTIFACTS object as JSON (with 2-space indentation)
294
- 3. Replace `{{FEATURE_DATA}}` with the serialized FEATURE_DATA JSON
295
- 4. Replace `{{EMBEDDED_ARTIFACTS}}` with the serialized EMBEDDED_ARTIFACTS JSON
296
- 5. Replace `{{APPLICATION_NAME}}` → `{application_name}` (still used in `<title>` and header)
297
- 6. Replace `{{APPLICATION_ID}}` → `{feature_id}` (still used in `APP_KEY`)
298
- 7. Replace `{{VERSION}}` → `{version}`
299
- 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 (involvementaccess)
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}`