@atlashub/smartstack-cli 4.74.0 → 4.75.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 (93) hide show
  1. package/dist/index.js +111 -36
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +14 -3
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/templates/agents/ba-reader.md +17 -15
  7. package/templates/agents/ba-writer.md +49 -51
  8. package/templates/skills/apex/_shared.md +1 -1
  9. package/templates/skills/apex/references/checks/backend-checks.sh +21 -7
  10. package/templates/skills/apex/references/checks/infrastructure-checks.sh +47 -10
  11. package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +3 -0
  12. package/templates/skills/apex/references/post-checks.md +5 -2
  13. package/templates/skills/apex/references/smartstack-frontend.md +53 -7
  14. package/templates/skills/apex/steps/step-00-init.md +74 -0
  15. package/templates/skills/apex/steps/step-03-execute.md +16 -4
  16. package/templates/skills/apex/steps/step-03b-layer1-seed.md +39 -6
  17. package/templates/skills/apex/steps/step-03c-layer2-backend.md +50 -5
  18. package/templates/skills/apex/steps/step-03d-layer3-frontend.md +102 -2
  19. package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +3 -0
  20. package/templates/skills/business-analyse/SKILL.md +14 -0
  21. package/templates/skills/business-analyse/_shared.md +27 -0
  22. package/templates/skills/business-analyse/patterns/suggestion-catalog.md +34 -26
  23. package/templates/skills/business-analyse/questionnaire/01-context.md +13 -9
  24. package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +20 -27
  25. package/templates/skills/business-analyse/questionnaire.md +86 -9
  26. package/templates/skills/business-analyse/references/03-json-schemas.md +213 -0
  27. package/templates/skills/business-analyse/references/03-post-check-validation.md +144 -0
  28. package/templates/skills/business-analyse/references/03-smartstack-entity-guards.md +32 -0
  29. package/templates/skills/business-analyse/references/04-cross-module-validation.md +95 -0
  30. package/templates/skills/business-analyse/references/04-file-allocation.md +162 -0
  31. package/templates/skills/business-analyse/references/04-naming-audit-checks.md +174 -0
  32. package/templates/skills/business-analyse/references/04-semantic-validation-matrix.md +118 -0
  33. package/templates/skills/business-analyse/references/domain-research-playbook.md +234 -0
  34. package/templates/skills/business-analyse/references/entity-sourcing-presentation.md +166 -0
  35. package/templates/skills/business-analyse/references/init-resume-logic.md +70 -0
  36. package/templates/skills/business-analyse/references/module-completeness-challenge.md +174 -0
  37. package/templates/skills/business-analyse/references/multi-app-detection.md +149 -0
  38. package/templates/skills/business-analyse/references/portal-classification.md +52 -0
  39. package/templates/skills/business-analyse/references/validation-checklist.md +30 -1
  40. package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +37 -4
  41. package/templates/skills/business-analyse/steps/step-00-init.md +22 -190
  42. package/templates/skills/business-analyse/steps/step-01-cadrage.md +365 -269
  43. package/templates/skills/business-analyse/steps/step-02-structure.md +98 -20
  44. package/templates/skills/business-analyse/steps/step-03-specify.md +652 -229
  45. package/templates/skills/business-analyse/steps/step-04-consolidate.md +308 -287
  46. package/templates/skills/business-analyse-design/SKILL.md +10 -0
  47. package/templates/skills/business-analyse-design/references/screens-post-check.md +221 -0
  48. package/templates/skills/business-analyse-design/references/screens-type-mapping.md +138 -0
  49. package/templates/skills/business-analyse-design/references/smartcomponents-templates.md +225 -0
  50. package/templates/skills/{business-analyse → business-analyse-design}/references/spec-auto-inference.md +117 -117
  51. package/templates/skills/business-analyse-design/steps/step-01-screens.md +36 -162
  52. package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +8 -7
  53. package/templates/skills/business-analyse-design/steps/step-03-navigation.md +89 -42
  54. package/templates/skills/business-analyse-develop/references/compact-loop.md +9 -0
  55. package/templates/skills/business-analyse-develop/references/handoff-quality-gate.md +132 -0
  56. package/templates/skills/business-analyse-develop/references/prd-v3-transformation.md +326 -0
  57. package/templates/skills/business-analyse-develop/references/report-reconciliation.md +140 -0
  58. package/templates/skills/business-analyse-develop/references/report-template.md +142 -0
  59. package/templates/skills/business-analyse-develop/steps/step-01-task.md +5 -177
  60. package/templates/skills/business-analyse-develop/steps/step-02-execute.md +17 -4
  61. package/templates/skills/business-analyse-develop/steps/step-03-commit.md +6 -2
  62. package/templates/skills/business-analyse-develop/steps/step-04-check.md +6 -0
  63. package/templates/skills/business-analyse-develop/steps/step-05-report.md +3 -269
  64. package/templates/skills/business-analyse-handoff/SKILL.md +10 -0
  65. package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +208 -0
  66. package/templates/skills/business-analyse-handoff/references/context-isolation-pattern.md +47 -0
  67. package/templates/skills/business-analyse-handoff/references/handoff-file-inventory.md +49 -0
  68. package/templates/skills/business-analyse-handoff/references/handoff-global-validation.md +142 -0
  69. package/templates/skills/business-analyse-handoff/references/prd-validation-checks.md +125 -0
  70. package/templates/skills/business-analyse-handoff/references/project-index-update.md +98 -0
  71. package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +9 -160
  72. package/templates/skills/business-analyse-handoff/steps/step-02-export.md +10 -99
  73. package/templates/skills/business-analyse-html/SKILL.md +10 -0
  74. package/templates/skills/business-analyse-html/html/ba-interactive.html +306 -81
  75. package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +15 -2
  76. package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +6 -46
  77. package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +88 -33
  78. package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +116 -0
  79. package/templates/skills/business-analyse-html/html/src/styles/10-diagrams.css +73 -0
  80. package/templates/skills/business-analyse-html/html/src/template.html +2 -0
  81. package/templates/skills/business-analyse-html/references/02-embedded-artifacts-building.md +144 -0
  82. package/templates/skills/business-analyse-html/references/02-feature-data-building.md +141 -0
  83. package/templates/skills/business-analyse-html/references/02-mapping-tables.md +442 -0
  84. package/templates/skills/business-analyse-html/references/02-normalization-helpers.md +139 -0
  85. package/templates/skills/business-analyse-html/references/02-screen-format-detection.md +283 -0
  86. package/templates/skills/business-analyse-html/references/02-self-check-validation.md +199 -0
  87. package/templates/skills/business-analyse-html/references/data-build.md +22 -1
  88. package/templates/skills/business-analyse-html/references/data-mapping.md +40 -5
  89. package/templates/skills/business-analyse-html/steps/step-02-build-data.md +12 -555
  90. package/templates/skills/business-analyse-review/SKILL.md +10 -0
  91. package/templates/skills/business-analyse-status/SKILL.md +8 -0
  92. package/templates/skills/dev-start/SKILL.md +143 -307
  93. package/templates/skills/efcore/SKILL.md +13 -0
@@ -194,31 +194,36 @@ function renderSmartFormMockup(res) {
194
194
  html += '<div class="mock-form-tab-content' + (ti === 0 || isOnly ? ' active' : '') + '"';
195
195
  html += ' data-mockup="' + mockupId + '" data-tab="' + ti + '">';
196
196
 
197
- var fields = tab.fields || [];
198
- var rows = [];
199
- for (var i = 0; i < fields.length; i += 2) {
200
- rows.push(fields.slice(i, i + 2));
201
- }
197
+ // Tab-level subtable: the entire tab is a subtable (type: "subtable", entity, columns)
198
+ if (tab.type === 'subtable') {
199
+ html += renderSubtableMockup(tab);
200
+ } else {
201
+ var fields = tab.fields || [];
202
+ var rows = [];
203
+ for (var i = 0; i < fields.length; i += 2) {
204
+ rows.push(fields.slice(i, i + 2));
205
+ }
202
206
 
203
- rows.forEach(function(row) {
204
- if (row.length === 1 && row[0].type === 'subtable') {
205
- html += renderSubtableMockup(row[0]);
206
- } else {
207
- html += '<div class="mock-form-row">';
208
- row.forEach(function(field) {
209
- html += '<div class="mock-form-group">';
210
- html += '<label class="mock-label">' + escapeHtml(field.label || field.field);
211
- if (field.required) html += ' <span style="color:var(--error);">*</span>';
212
- html += '</label>';
213
- html += renderFormFieldMockup(field);
207
+ rows.forEach(function(row) {
208
+ if (row.length === 1 && row[0].type === 'subtable') {
209
+ html += renderSubtableMockup(row[0]);
210
+ } else {
211
+ html += '<div class="mock-form-row">';
212
+ row.forEach(function(field) {
213
+ html += '<div class="mock-form-group">';
214
+ html += '<label class="mock-label">' + escapeHtml(field.label || field.field);
215
+ if (field.required) html += ' <span style="color:var(--error);">*</span>';
216
+ html += '</label>';
217
+ html += renderFormFieldMockup(field);
218
+ html += '</div>';
219
+ });
214
220
  html += '</div>';
215
- });
216
- html += '</div>';
217
- }
218
- });
221
+ }
222
+ });
219
223
 
220
- if (fields.length === 0) {
221
- html += '<div style="padding:2rem;text-align:center;color:var(--text-muted);font-style:italic;">Contenu de l\'onglet &laquo; ' + escapeHtml(tab.label) + ' &raquo;</div>';
224
+ if (fields.length === 0) {
225
+ html += '<div style="padding:2rem;text-align:center;color:var(--text-muted);font-style:italic;">Contenu de l\'onglet &laquo; ' + escapeHtml(tab.label) + ' &raquo;</div>';
226
+ }
222
227
  }
223
228
 
224
229
  html += '</div>';
@@ -263,20 +268,39 @@ function renderSubtableMockup(field) {
263
268
 
264
269
  /* ---------- SmartCard ---------- */
265
270
  function renderSmartCardMockup(res) {
266
- var columns = res.columns || res.fields || [];
271
+ var fields = res.fields || res.columns || [];
267
272
  var html = '<div class="mock-header"><span class="mock-title">' + escapeHtml(res.label || 'Cartes') + '</span></div>';
268
273
  html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:1rem;">';
269
274
 
270
275
  for (var i = 0; i < 4; i++) {
271
276
  html += '<div style="background:var(--bg-hover);border:1px solid var(--border);border-radius:8px;padding:1rem;">';
272
- columns.forEach(function(col, ci) {
273
- var label = col.label || col.field || col;
274
- if (ci === 0) {
277
+ // Title/Subtitle pattern (SmartCard with title + subtitle + fields + actions)
278
+ if (res.title) {
279
+ html += '<div style="font-weight:600;color:var(--text-bright);margin-bottom:0.25rem;">' + escapeHtml(res.title) + ' #' + (i + 1) + '</div>';
280
+ }
281
+ if (res.subtitle) {
282
+ html += '<div style="font-size:0.8rem;color:var(--accent);margin-bottom:0.5rem;">' + escapeHtml(res.subtitle) + '</div>';
283
+ }
284
+ // Fields
285
+ fields.forEach(function(col, ci) {
286
+ var label = col.label || col.field || (typeof col === 'string' ? col : '');
287
+ var iconMap = { calendar: '&#128197; ', 'dollar-sign': '&#128176; ', 'alert-circle': '&#9888; ', mail: '&#9993; ', building: '&#127970; ', user: '&#128100; ' };
288
+ var icon = col.icon ? (iconMap[col.icon] || '&#9679; ') : '';
289
+ if (!res.title && ci === 0) {
275
290
  html += '<div style="font-weight:600;color:var(--text-bright);margin-bottom:0.5rem;">' + escapeHtml(label) + ' #' + (i + 1) + '</div>';
276
291
  } else {
277
- html += '<div style="font-size:0.8rem;color:var(--text-muted);margin-bottom:0.25rem;">' + escapeHtml(label) + ': <span style="color:var(--text);">valeur</span></div>';
292
+ html += '<div style="font-size:0.8rem;color:var(--text-muted);margin-bottom:0.25rem;">' + icon + escapeHtml(label) + ': <span style="color:var(--text);">valeur</span></div>';
278
293
  }
279
294
  });
295
+ // Actions
296
+ if (res.actions && res.actions.length > 0) {
297
+ html += '<div style="margin-top:0.75rem;display:flex;gap:0.4rem;">';
298
+ res.actions.forEach(function(a) {
299
+ var actionLabel = typeof a === 'string' ? a.replace(/-/g, ' ') : (a.label || a.action || '');
300
+ html += '<span class="mock-btn" style="font-size:0.75rem;">' + escapeHtml(actionLabel) + '</span>';
301
+ });
302
+ html += '</div>';
303
+ }
280
304
  html += '</div>';
281
305
  }
282
306
  html += '</div>';
@@ -285,7 +309,7 @@ function renderSmartCardMockup(res) {
285
309
 
286
310
  /* ---------- SmartKanban ---------- */
287
311
  function renderSmartKanbanMockup(res) {
288
- var options = res.options || res.columns || ['À faire', 'En cours', 'Terminé'];
312
+ var options = (res.options && res.options.length > 0) ? res.options : (res.columns && res.columns.length > 0) ? res.columns : ['À faire', 'En cours', 'Terminé'];
289
313
  var html = '<div class="mock-header"><span class="mock-title">' + escapeHtml(res.label || 'Kanban') + '</span></div>';
290
314
  html += '<div style="display:flex;gap:1rem;overflow-x:auto;padding-bottom:0.5rem;">';
291
315
 
@@ -359,11 +383,42 @@ function kpiDisplayValue(kpi) {
359
383
 
360
384
  /* ---------- SmartFilter ---------- */
361
385
  function renderSmartFilterMockup(res) {
362
- var options = res.options || [];
363
- var html = '<div style="display:flex;gap:0.4rem;flex-wrap:wrap;padding:0.5rem 0;">';
364
- html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--primary);color:#fff;cursor:pointer;">Tous</span>';
365
- options.forEach(function(opt) {
366
- html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--bg-hover);color:var(--text);border:1px solid var(--border);cursor:pointer;">' + escapeHtml(opt) + '</span>';
386
+ var filters = res.filters || [];
387
+ if (filters.length === 0) {
388
+ // Fallback: legacy options[] format (tag pills)
389
+ var options = res.options || [];
390
+ if (options.length === 0) return '<div style="padding:1rem;text-align:center;color:var(--text-muted);">Aucun filtre défini</div>';
391
+ var html = '<div style="display:flex;gap:0.4rem;flex-wrap:wrap;padding:0.5rem 0;">';
392
+ html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--primary);color:#fff;cursor:pointer;">Tous</span>';
393
+ options.forEach(function(opt) {
394
+ html += '<span style="padding:0.3rem 0.7rem;border-radius:16px;font-size:0.8rem;background:var(--bg-hover);color:var(--text);border:1px solid var(--border);cursor:pointer;">' + escapeHtml(typeof opt === 'string' ? opt : opt.label || '') + '</span>';
395
+ });
396
+ html += '</div>';
397
+ return html;
398
+ }
399
+
400
+ // Rich filter bar: render each filter based on its type
401
+ var html = '<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:flex-end;padding:0.5rem 0;">';
402
+ filters.forEach(function(f) {
403
+ var label = typeof f === 'string' ? f : (f.label || f.field || '');
404
+ var type = typeof f === 'string' ? 'text' : (f.type || 'text');
405
+ html += '<div style="display:flex;flex-direction:column;gap:0.2rem;">';
406
+ html += '<span style="font-size:0.7rem;color:var(--text-muted);">' + escapeHtml(label) + '</span>';
407
+ switch (type) {
408
+ case 'select':
409
+ var opts = f.options || ['Option 1', 'Option 2'];
410
+ html += '<span class="mock-input" style="width:auto;min-width:130px;font-size:0.8rem;color:var(--text-muted);">' + escapeHtml(opts[0]) + ' &#9662;</span>';
411
+ break;
412
+ case 'lookup':
413
+ html += '<span class="mock-input" style="width:auto;min-width:130px;font-size:0.8rem;color:var(--accent);">' + escapeHtml(f.entity || label) + ' &#128269;</span>';
414
+ break;
415
+ case 'daterange':
416
+ html += '<span class="mock-input" style="width:auto;min-width:180px;font-size:0.8rem;color:var(--text-muted);">01/01/2025 — 31/12/2025 &#128197;</span>';
417
+ break;
418
+ default:
419
+ html += '<span class="mock-input" style="width:auto;min-width:160px;font-size:0.8rem;color:var(--text-muted);">Rechercher... &#128269;</span>';
420
+ }
421
+ html += '</div>';
367
422
  });
368
423
  html += '</div>';
369
424
  return html;
@@ -0,0 +1,116 @@
1
+ /* ==========================================
2
+ MERMAID DIAGRAM RENDERING
3
+ Renders ERD, state machines, and sequence diagrams
4
+ from consolidation.mermaidDiagrams data.
5
+ ========================================== */
6
+
7
+ function renderMermaidDiagrams() {
8
+ const data = window.FEATURE_DATA;
9
+ if (!data) return;
10
+
11
+ const diagrams = data.consolidation?.mermaidDiagrams;
12
+ if (!diagrams) return;
13
+
14
+ // 1. ERD in consol-datamodel (prepend before entity cards)
15
+ if (diagrams.erd) {
16
+ const erdContainer = document.getElementById('dataModelContainer');
17
+ if (erdContainer) {
18
+ const erdDiv = document.createElement('div');
19
+ erdDiv.className = 'diagram-container diagram-erd';
20
+ erdDiv.innerHTML =
21
+ '<div class="diagram-section-header">Diagramme Entit\u00e9-Relation (ERD)</div>' +
22
+ '<div class="mermaid">' + escapeHtml(diagrams.erd) + '</div>';
23
+ erdContainer.insertBefore(erdDiv, erdContainer.firstChild);
24
+ }
25
+ }
26
+
27
+ // 2. State machine diagrams — inject in module spec sections or consol-datamodel
28
+ if (diagrams.stateMachines && Object.keys(diagrams.stateMachines).length > 0) {
29
+ const smContainer = document.getElementById('dataModelContainer');
30
+ if (smContainer) {
31
+ const smSection = document.createElement('div');
32
+ smSection.innerHTML = '<div class="diagram-section-header">Cycles de vie (State Machines)</div>';
33
+
34
+ Object.entries(diagrams.stateMachines).forEach(function(entry) {
35
+ var entity = entry[0];
36
+ var def = entry[1];
37
+ var smDiv = document.createElement('div');
38
+ smDiv.className = 'diagram-container diagram-state-machine';
39
+ smDiv.innerHTML =
40
+ '<h4>' + escapeHtml(entity) + '</h4>' +
41
+ '<div class="mermaid">' + escapeHtml(def) + '</div>';
42
+ smSection.appendChild(smDiv);
43
+ });
44
+
45
+ smContainer.appendChild(smSection);
46
+ }
47
+ }
48
+
49
+ // 3. Sequence diagrams in consol-flows
50
+ if (diagrams.sequences && Object.keys(diagrams.sequences).length > 0) {
51
+ var flowsContainer = document.getElementById('consolFlowsContainer');
52
+ // Fallback: try the consol-flows section
53
+ if (!flowsContainer) {
54
+ var consolFlows = document.getElementById('consol-flows');
55
+ if (consolFlows) {
56
+ flowsContainer = consolFlows.querySelector('.section-body') || consolFlows;
57
+ }
58
+ }
59
+
60
+ if (flowsContainer) {
61
+ var seqSection = document.createElement('div');
62
+ seqSection.innerHTML = '<div class="diagram-section-header">Diagrammes de s\u00e9quence</div>';
63
+
64
+ Object.entries(diagrams.sequences).forEach(function(entry) {
65
+ var flowName = entry[0];
66
+ var def = entry[1];
67
+ var seqDiv = document.createElement('div');
68
+ seqDiv.className = 'diagram-container diagram-sequence';
69
+ seqDiv.innerHTML =
70
+ '<h4>' + escapeHtml(flowName) + '</h4>' +
71
+ '<div class="mermaid">' + escapeHtml(def) + '</div>';
72
+ seqSection.appendChild(seqDiv);
73
+ });
74
+
75
+ flowsContainer.appendChild(seqSection);
76
+ }
77
+ }
78
+
79
+ // 4. Render all mermaid elements
80
+ try {
81
+ if (typeof mermaid !== 'undefined' && mermaid.run) {
82
+ mermaid.run({ querySelector: '.mermaid' });
83
+ }
84
+ } catch (e) {
85
+ console.warn('Mermaid rendering failed:', e);
86
+ // Fallback: show raw text
87
+ document.querySelectorAll('.mermaid').forEach(function(el) {
88
+ if (!el.querySelector('svg')) {
89
+ el.style.whiteSpace = 'pre-wrap';
90
+ el.style.fontFamily = 'monospace';
91
+ el.style.fontSize = '0.85rem';
92
+ el.style.color = 'var(--text-muted)';
93
+ }
94
+ });
95
+ }
96
+ }
97
+
98
+ // Escape HTML for safe injection
99
+ function escapeHtml(text) {
100
+ if (!text) return '';
101
+ // For mermaid content, we need to preserve the syntax
102
+ // Only escape actual HTML tags, not mermaid arrows
103
+ return text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
104
+ }
105
+
106
+ // Auto-run after consolidation rendering
107
+ (function() {
108
+ // Wait for DOM and other render functions to complete
109
+ if (document.readyState === 'loading') {
110
+ document.addEventListener('DOMContentLoaded', function() {
111
+ setTimeout(renderMermaidDiagrams, 500);
112
+ });
113
+ } else {
114
+ setTimeout(renderMermaidDiagrams, 500);
115
+ }
116
+ })();
@@ -0,0 +1,73 @@
1
+ /* ==========================================
2
+ MERMAID DIAGRAMS
3
+ ========================================== */
4
+
5
+ .diagram-container {
6
+ margin: 1.5rem 0;
7
+ padding: 1rem;
8
+ background: var(--bg-card);
9
+ border-radius: 8px;
10
+ border: 1px solid var(--border);
11
+ overflow-x: auto;
12
+ }
13
+
14
+ .diagram-container h3,
15
+ .diagram-container h4 {
16
+ color: var(--text-bright);
17
+ margin-bottom: 1rem;
18
+ font-size: 1.1rem;
19
+ }
20
+
21
+ .diagram-container .mermaid {
22
+ display: flex;
23
+ justify-content: center;
24
+ min-height: 200px;
25
+ }
26
+
27
+ .diagram-container .mermaid svg {
28
+ max-width: 100%;
29
+ height: auto;
30
+ }
31
+
32
+ /* ERD specific */
33
+ .diagram-erd {
34
+ margin-bottom: 2rem;
35
+ border-left: 3px solid var(--primary);
36
+ }
37
+
38
+ /* State machine specific */
39
+ .diagram-state-machine {
40
+ border-left: 3px solid var(--accent);
41
+ }
42
+
43
+ /* Sequence diagram specific */
44
+ .diagram-sequence {
45
+ border-left: 3px solid var(--success);
46
+ }
47
+
48
+ /* Diagram section header */
49
+ .diagram-section-header {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 0.5rem;
53
+ margin-bottom: 1rem;
54
+ color: var(--text-bright);
55
+ font-size: 1.2rem;
56
+ font-weight: 600;
57
+ }
58
+
59
+ .diagram-section-header::before {
60
+ content: '';
61
+ width: 4px;
62
+ height: 1.2em;
63
+ background: var(--primary);
64
+ border-radius: 2px;
65
+ }
66
+
67
+ /* No diagrams fallback */
68
+ .diagram-empty {
69
+ color: var(--text-muted);
70
+ font-style: italic;
71
+ padding: 1rem;
72
+ text-align: center;
73
+ }
@@ -4,6 +4,8 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>{{APPLICATION_NAME}} - Analyse métier</title>
7
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
8
+ <script>mermaid.initialize({ startOnLoad: false, theme: 'dark', securityLevel: 'loose' });</script>
7
9
  <style>
8
10
  <!-- CSS_PLACEHOLDER -->
9
11
  </style>
@@ -0,0 +1,144 @@
1
+ # Reference: EMBEDDED_ARTIFACTS Building Details
2
+
3
+ ## wireframes{} — per moduleCode
4
+
5
+ ### Architecture: Flat File + Nested Structures
6
+
7
+ **FLAT-FILE:** Wireframes come from `screens.json` in each module directory (collected in step-01),
8
+ NOT from `moduleFeature.specification.uiWireframes`.
9
+
10
+ ### STEP 1: Collect wireframe sources from BOTH flat and nested structures
11
+
12
+ ```javascript
13
+ const mod = collected_data.modules[moduleCode];
14
+
15
+ // Flat: mod.screens.screens[] with mockupFormat/mockup at top level
16
+ // Nested: mod.screens.sections[].resources[].wireframe (design step output)
17
+ let rawWireframes = [];
18
+
19
+ // Source A: flat screens[] array (original BA output or manually enriched)
20
+ const flatScreens = mod.screens?.screens || [];
21
+ rawWireframes.push(...flatScreens.filter(s => s.mockup || s.mockupFormat));
22
+
23
+ // Source B: nested sections[].resources[].wireframe (design step output)
24
+ const sections = mod.screens?.sections || [];
25
+ for (const section of sections) {
26
+ // B1: wireframe directly on section (ba-004 style: sections[].wireframe)
27
+ if (section.wireframe) {
28
+ rawWireframes.push({
29
+ ...section.wireframe,
30
+ section: section.wireframe.section || section.id || section.code || section.sectionCode || "",
31
+ screen: section.wireframe.screen || section.id || section.code || section.sectionCode || ""
32
+ });
33
+ }
34
+ // B2: wireframe on resources (nested: sections[].resources[].wireframe)
35
+ for (const resource of (section.resources || [])) {
36
+ if (resource.wireframe) {
37
+ rawWireframes.push({
38
+ ...resource.wireframe,
39
+ section: resource.wireframe.section || section.sectionCode || section.id || "",
40
+ screen: resource.wireframe.screen || `${section.sectionCode || section.id}-${resource.code}` || ""
41
+ });
42
+ }
43
+ }
44
+ }
45
+
46
+ // Source C: screens/sections without mockup → auto-generate text description as wireframe fallback
47
+ // C1: from flat screens[]
48
+ const screensWithoutMockup = flatScreens.filter(s => !s.mockup && !s.mockupFormat);
49
+ // C2: from sections[] (ba-004 style) — sections without wireframe property
50
+ const sectionsWithoutWireframe = sections.filter(s => !s.wireframe);
51
+ const allNoMockup = [
52
+ ...screensWithoutMockup.map(s => ({
53
+ type: s.componentType || "", columns: s.columns || [], tabs: s.tabs || [],
54
+ kpis: s.kpis || [], screen: s.screen || "", section: s.section || "",
55
+ description: s.sectionDescription || ""
56
+ })),
57
+ ...sectionsWithoutWireframe.map(s => ({
58
+ type: s.layout || s.componentType || "", columns: s.columns || [], tabs: s.tabs || [],
59
+ kpis: s.kpis || [], screen: s.id || s.code || "", section: s.id || s.code || "",
60
+ description: s.description || ""
61
+ }))
62
+ ];
63
+ for (const screen of allNoMockup) {
64
+ const type = screen.type;
65
+ let desc = "";
66
+ if (type.includes("Table") || type.includes("Grid")) {
67
+ const cols = screen.columns;
68
+ desc = "Tableau avec " + cols.length + " colonnes : " + cols.map(c => c.label || c.displayName || c.code || c.name).join(", ");
69
+ } else if (type.includes("Form")) {
70
+ const tabs = screen.tabs;
71
+ desc = "Formulaire " + (tabs.length > 0 ? "avec " + tabs.length + " onglet(s)" : "");
72
+ } else if (type.includes("Dashboard")) {
73
+ desc = "Tableau de bord avec " + (screen.kpis.length || "") + " KPIs";
74
+ } else if (type.includes("Kanban")) {
75
+ desc = "Vue Kanban";
76
+ }
77
+ if (desc) {
78
+ rawWireframes.push({
79
+ screen: screen.screen, section: screen.section,
80
+ mockupFormat: "text", mockup: desc,
81
+ description: screen.description, elements: [], componentMapping: []
82
+ });
83
+ }
84
+ }
85
+ ```
86
+
87
+ ### STEP 2: Map to HTML format (RENAME: mockupFormat → format, mockup → content)
88
+
89
+ **FIELD RENAME WARNING:** Module JSON uses `mockupFormat`/`mockup`. HTML reads `format`/`content`. You MUST rename.
90
+
91
+ ```javascript
92
+ wireframes: {
93
+ [moduleCode]: rawWireframes.map(wf => ({
94
+ screen: wf.screen || wf.name || wf.title || wf.id || "",
95
+ section: wf.section || "",
96
+ format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
97
+ content: wf.mockup || wf.ascii || wf.content || "", // RENAME: mockup → content
98
+ svgContent: null,
99
+ description: wf.description || "",
100
+ elements: wf.elements || [],
101
+ actions: wf.actions || [],
102
+ componentMapping: Array.isArray(wf.componentMapping)
103
+ ? wf.componentMapping.map(function(entry) {
104
+ if (entry.wireframeElement && entry.reactComponent) return entry; // canonical
105
+ // Shorthand: [{key: value}] → {wireframeElement, reactComponent}
106
+ var keys = Object.keys(entry);
107
+ if (keys.length === 1 && !entry.wireframeElement) {
108
+ return { wireframeElement: keys[0], reactComponent: entry[keys[0]] };
109
+ }
110
+ return entry;
111
+ })
112
+ : typeof wf.componentMapping === 'object' && wf.componentMapping !== null
113
+ ? Object.entries(wf.componentMapping).map(([k, v]) => ({ wireframeElement: k, reactComponent: v }))
114
+ : [],
115
+ layout: typeof wf.layout === 'object' ? wf.layout : null,
116
+ permissionsRequired: wf.permissionsRequired || []
117
+ }))
118
+ }
119
+ ```
120
+
121
+ ## e2eFlows[]
122
+
123
+ ```javascript
124
+ e2eFlows: (master.consolidation?.e2eFlows || []).map(flow => ({
125
+ name: flow.name,
126
+ diagram: flow.steps.map(s => s.action + "(" + s.module + ")").join(" ──→ "),
127
+ steps: flow.steps || [],
128
+ actors: [...new Set(flow.steps.map(s => s.permission?.split(".")[0]).filter(Boolean))].join(", "),
129
+ modules: [...new Set(flow.steps.map(s => s.module))].join(" → ")
130
+ }))
131
+ ```
132
+
133
+ ## dependencyGraph
134
+
135
+ ```javascript
136
+ dependencyGraph: {
137
+ nodes: (master.modules || []).map(m => ({
138
+ id: m.code, label: m.code, type: m.featureType || "data-centric"
139
+ })),
140
+ edges: (master.dependencyGraph?.edges || []).map(e => ({
141
+ from: e.from, to: e.to, description: e.description || ""
142
+ }))
143
+ }
144
+ ```
@@ -0,0 +1,141 @@
1
+ # Reference: FEATURE_DATA Building Details
2
+
3
+ ## moduleSpecs{} — ONE entry per module (CRITICAL)
4
+
5
+ ### Architecture: Flat File Data Collection
6
+
7
+ **FLAT-FILE ARCHITECTURE:** Module data comes from separate JSON files collected in step-01,
8
+ NOT from index.json fields. Use `collected_data.modules[moduleCode].entities`, `.usecases`, etc.
9
+
10
+ For EACH module, use the flat file data from `collected_data.modules[moduleCode]`:
11
+
12
+ ```javascript
13
+ const mod = collected_data.modules[moduleCode];
14
+
15
+ // NORMALIZE: usecases.json may use "useCases" (camelCase) or "usecases" (lowercase)
16
+ const rawUCs = mod.usecases?.useCases || mod.usecases?.usecases || [];
17
+ // NORMALIZE: rules.json may use "rules" or "businessRules"
18
+ const rawBRs = mod.rules?.rules || mod.rules?.businessRules || [];
19
+
20
+ moduleSpecs[moduleCode] = {
21
+ useCases: rawUCs.map(uc => ({
22
+ name: uc.name || uc.title || uc.id || "",
23
+ sectionCode: uc.sectionCode || "",
24
+ actor: uc.primaryActor || uc.actor || "",
25
+ // SAFETY NET: steps may be strings[] (mainScenario) or objects[] ({step, action})
26
+ steps: (uc.mainScenario || uc.steps || []).map(s =>
27
+ typeof s === 'string' ? s : (s.action || s.description || "")
28
+ ).join("\n"),
29
+ alternative: (uc.alternativeScenarios || uc.alternativeFlows || []).map(a =>
30
+ (a.name || a.trigger || "") + ": " + (a.steps || a.actions || []).map(s =>
31
+ typeof s === 'string' ? s : (s.action || s.description || "")
32
+ ).join(", ")
33
+ ).join("\n")
34
+ })),
35
+ businessRules: rawBRs.map(br => ({
36
+ name: br.name || br.id || "",
37
+ sectionCode: br.sectionCode || "",
38
+ category: br.category || "",
39
+ statement: br.statement || br.description || "",
40
+ example: (br.examples || []).map(e =>
41
+ typeof e === 'string' ? e : ((e.input || "") + " → " + (e.expected || ""))
42
+ ).join("; ")
43
+ })),
44
+ // ENTITY SAFETY NET: map fields[] → attributes[] if agent deviated
45
+ entities: (mod.entities?.entities || []).map(ent => ({
46
+ name: ent.name,
47
+ description: ent.description || "",
48
+ attributes: (ent.attributes || []).length > 0
49
+ ? ent.attributes.map(a => ({ name: a.name, type: a.type || "string", required: a.required || false, description: a.description || "" }))
50
+ : (ent.fields || []).map(f => ({ name: f.name, type: f.type || "string", required: f.required || false, description: f.description || "" })),
51
+ relationships: (ent.relationships || []).map(r =>
52
+ typeof r === 'string' ? r : r.target + " (" + r.type + ") - " + (r.description || ""))
53
+ })),
54
+ permissions: buildPermissionKeys(mod.permissions),
55
+ apiEndpoints: mod.usecases?.apiEndpoints || []
56
+ }
57
+ ```
58
+
59
+ ### Building screens[] for HTML Interactive Mockups
60
+
61
+ ```javascript
62
+ // BUILD screens[] for HTML interactive mockups — use helpers and format detection from references
63
+ const flatScr = mod.screens?.screens || [];
64
+ const sectionScr = mod.screens?.sections || [];
65
+ let screens = [];
66
+
67
+ // Apply normalization helpers from references/02-normalization-helpers.md
68
+ // Apply format detection from references/02-screen-format-detection.md
69
+
70
+ moduleSpecs[moduleCode].screens = screens;
71
+ ```
72
+
73
+ ### Enrich anticipatedSections with section-level UC/BR
74
+
75
+ **CRITICAL for HTML viewer to display UC/BR grouped by section.**
76
+
77
+ Execute AFTER moduleSpecs is built:
78
+
79
+ ```javascript
80
+ // Post-processing: populate each section's useCases[] and businessRules[]
81
+ // using the sectionCode field from moduleSpecs
82
+ FEATURE_DATA.modules.forEach(m => {
83
+ const spec = FEATURE_DATA.moduleSpecs[m.code];
84
+ if (!spec) return;
85
+ (m.anticipatedSections || []).forEach(section => {
86
+ section.useCases = (spec.useCases || []).filter(uc => uc.sectionCode === section.code);
87
+ section.businessRules = (spec.businessRules || []).filter(br => br.sectionCode === section.code);
88
+ });
89
+ });
90
+ ```
91
+
92
+ ## Top-Level Fields: dependencies, consolidation, handoff
93
+
94
+ ### dependencies[] (TOP-LEVEL — CRITICAL for HTML navigation)
95
+
96
+ ```javascript
97
+ dependencies: (master.consolidation?.crossModuleInteractions || master.dependencyGraph?.edges || []).map(i => ({
98
+ from: i.fromModule || i.from || "",
99
+ to: i.toModule || i.to || "",
100
+ description: i.description || ""
101
+ }))
102
+ ```
103
+
104
+ **WARNING:** `data.dependencies` is used by the sidebar (navigation), module rendering, consolidation views,
105
+ handoff summary, and export. If this array is missing, the entire HTML page crashes with a TypeError.
106
+ ALWAYS include it, even if empty (`dependencies: []`).
107
+
108
+ ### consolidation
109
+
110
+ ```javascript
111
+ consolidation: {
112
+ interactions: (master.consolidation?.crossModuleInteractions || []).map(i => ({
113
+ from: i.fromModule,
114
+ to: i.toModule,
115
+ description: i.description || ""
116
+ })),
117
+ sharedEntities: master.consolidation?.sharedEntities || [],
118
+ e2eFlows: (master.consolidation?.e2eFlows || []).map(f => ({
119
+ name: f.name,
120
+ steps: (f.steps || []).map(s => ({ module: s.module, action: s.action })),
121
+ actors: (f.steps || []).map(s => s.permission).join(", ")
122
+ }))
123
+ }
124
+ ```
125
+
126
+ ### handoff
127
+
128
+ ```javascript
129
+ handoff: {
130
+ complexity: master.handoff?.complexity,
131
+ implementationStrategy: master.handoff?.implementationStrategy,
132
+ moduleOrder: master.handoff?.moduleOrder,
133
+ filesToCreate: master.handoff?.filesToCreate,
134
+ brToCodeMapping: master.handoff?.brToCodeMapping,
135
+ apiEndpointSummary: master.handoff?.apiEndpointSummary
136
+ }
137
+ ```
138
+
139
+ ## Helper Function: buildPermissionKeys()
140
+
141
+ See `references/data-mapping.md` for `buildPermissionKeys()` implementation.