@atlashub/smartstack-cli 4.41.0 → 4.42.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 (142) hide show
  1. package/.documentation/apex.html +2 -2
  2. package/.documentation/business-analyse.html +26 -27
  3. package/.documentation/commands.html +6 -6
  4. package/dist/index.js +24 -13
  5. package/dist/index.js.map +1 -1
  6. package/package.json +2 -2
  7. package/templates/agents/ba-reader.md +2 -2
  8. package/templates/agents/ba-writer.md +44 -9
  9. package/templates/hooks/stop-hook.sh +6 -6
  10. package/templates/ralph/README.md +1 -1
  11. package/templates/scripts/setup-ralph-loop.sh +2 -2
  12. package/templates/skills/_resources/context-digest-template.md +1 -1
  13. package/templates/skills/_shared.md +13 -13
  14. package/templates/skills/apex/SKILL.md +14 -7
  15. package/templates/skills/apex/_shared.md +1 -1
  16. package/templates/skills/apex/references/challenge-questions.md +46 -13
  17. package/templates/skills/apex/references/core-seed-data.md +4 -4
  18. package/templates/skills/apex/references/error-classification.md +3 -3
  19. package/templates/skills/apex/references/smartstack-api.md +1 -1
  20. package/templates/skills/apex/references/smartstack-layers.md +1 -1
  21. package/templates/skills/apex/steps/step-00-init.md +46 -8
  22. package/templates/skills/apex/steps/step-01-analyze.md +1 -1
  23. package/templates/skills/apex/steps/step-02-plan.md +1 -1
  24. package/templates/skills/apex/steps/step-03-execute.md +1 -1
  25. package/templates/skills/business-analyse/SKILL.md +83 -22
  26. package/templates/skills/business-analyse/_shared.md +12 -9
  27. package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +13 -0
  28. package/templates/skills/business-analyse/questionnaire/03-data-ui.md +33 -0
  29. package/templates/skills/business-analyse/questionnaire/04-risks-metrics.md +1 -1
  30. package/templates/skills/business-analyse/react/components.md +1 -1
  31. package/templates/skills/business-analyse/react/schema.md +1 -1
  32. package/templates/skills/business-analyse/references/acceptance-criteria.md +3 -3
  33. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +1 -1
  34. package/templates/skills/business-analyse/references/detection-strategies.md +2 -2
  35. package/templates/skills/business-analyse/references/entity-architecture-decision.md +1 -1
  36. package/templates/skills/business-analyse/references/naming-conventions.md +6 -6
  37. package/templates/skills/business-analyse/references/robustness-checks.md +4 -4
  38. package/templates/skills/business-analyse/references/spec-auto-inference.md +2 -2
  39. package/templates/skills/business-analyse/references/validation-checklist.md +3 -3
  40. package/templates/skills/business-analyse/schemas/feature-schema.json +1 -1
  41. package/templates/skills/business-analyse/schemas/sections/handoff-schema.json +2 -2
  42. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +3 -2
  43. package/templates/skills/business-analyse/steps/step-00-init.md +15 -5
  44. package/templates/skills/business-analyse/steps/step-01-cadrage.md +14 -5
  45. package/templates/skills/business-analyse/steps/step-02-structure.md +17 -1
  46. package/templates/skills/business-analyse/steps/step-03-specify.md +136 -26
  47. package/templates/skills/business-analyse/steps/step-04-consolidate.md +44 -8
  48. package/templates/skills/business-analyse/templates/tpl-handoff.md +5 -5
  49. package/templates/skills/business-analyse/templates/tpl-launch-displays.md +4 -4
  50. package/templates/skills/business-analyse/templates-frd.md +4 -4
  51. package/templates/skills/{ba-design-ui → business-analyse-design}/SKILL.md +9 -9
  52. package/templates/skills/{ba-design-ui → business-analyse-design}/steps/step-01-screens.md +9 -0
  53. package/templates/skills/{ba-design-ui → business-analyse-design}/steps/step-03-navigation.md +9 -2
  54. package/templates/skills/business-analyse-develop/SKILL.md +248 -0
  55. package/templates/skills/{ralph-loop → business-analyse-develop}/references/category-completeness.md +1 -1
  56. package/templates/skills/{ralph-loop → business-analyse-develop}/references/init-resume-recovery.md +8 -8
  57. package/templates/skills/{ralph-loop → business-analyse-develop}/references/multi-module-queue.md +1 -1
  58. package/templates/skills/business-analyse-develop/references/quality-gates.md +70 -0
  59. package/templates/skills/{ralph-loop → business-analyse-develop}/references/task-transform-legacy.md +1 -1
  60. package/templates/skills/{ralph-loop → business-analyse-develop}/steps/step-00-init.md +20 -4
  61. package/templates/skills/{ralph-loop → business-analyse-develop}/steps/step-01-task.md +3 -2
  62. package/templates/skills/business-analyse-develop/steps/step-01-v4-execute.md +131 -0
  63. package/templates/skills/business-analyse-develop/steps/step-02-v4-verify.md +156 -0
  64. package/templates/skills/{ralph-loop → business-analyse-develop}/steps/step-04-check.md +1 -1
  65. package/templates/skills/{ralph-loop → business-analyse-develop}/steps/step-05-report.md +1 -1
  66. package/templates/skills/{derive-prd → business-analyse-handoff}/SKILL.md +7 -7
  67. package/templates/skills/{derive-prd → business-analyse-handoff}/references/acceptance-criteria.md +5 -5
  68. package/templates/skills/{derive-prd → business-analyse-handoff}/references/handoff-file-templates.md +1 -1
  69. package/templates/skills/{derive-prd → business-analyse-handoff}/references/handoff-mappings.md +1 -1
  70. package/templates/skills/{derive-prd → business-analyse-handoff}/references/handoff-seeddata-generation.md +2 -2
  71. package/templates/skills/{derive-prd → business-analyse-handoff}/references/prd-generation.md +14 -14
  72. package/templates/skills/{derive-prd → business-analyse-handoff}/schemas/handoff-schema.json +2 -2
  73. package/templates/skills/{derive-prd → business-analyse-handoff}/steps/step-00-validate.md +6 -6
  74. package/templates/skills/{derive-prd → business-analyse-handoff}/steps/step-01-transform.md +46 -7
  75. package/templates/skills/{derive-prd → business-analyse-handoff}/steps/step-02-export.md +34 -14
  76. package/templates/skills/{ba-generate-html → business-analyse-html}/SKILL.md +4 -4
  77. package/templates/skills/{ba-generate-html → business-analyse-html}/html/ba-interactive.html +709 -277
  78. package/templates/skills/{ba-generate-html → business-analyse-html}/html/build-html.js +25 -3
  79. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/01-data-init.js +54 -0
  80. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/02-navigation.js +97 -3
  81. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/03-render-cadrage.js +8 -7
  82. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/04-render-modules.js +7 -7
  83. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/05-render-specs.js +188 -85
  84. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/06-render-consolidation.js +15 -14
  85. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/06-render-mockups.js +19 -19
  86. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/07-render-handoff.js +24 -4
  87. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/08-editing.js +6 -2
  88. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/09-export.js +27 -57
  89. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/10-comments.js +67 -45
  90. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/scripts/11-review-panel.js +15 -13
  91. package/templates/skills/business-analyse-html/html/src/styles/02-layout.css +216 -0
  92. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/05-modules.css +36 -0
  93. package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/template.html +22 -12
  94. package/templates/skills/{ba-generate-html → business-analyse-html}/references/data-build.md +1 -1
  95. package/templates/skills/{ba-generate-html → business-analyse-html}/references/data-mapping.md +5 -1
  96. package/templates/skills/{ba-generate-html → business-analyse-html}/references/output-modes.md +7 -7
  97. package/templates/skills/{ba-generate-html → business-analyse-html}/steps/step-01-collect.md +25 -1
  98. package/templates/skills/{ba-generate-html → business-analyse-html}/steps/step-02-build-data.md +33 -5
  99. package/templates/skills/{ba-generate-html → business-analyse-html}/steps/step-03-render.md +2 -2
  100. package/templates/skills/{ba-generate-html → business-analyse-html}/steps/step-04-verify.md +2 -2
  101. package/templates/skills/{ba-review → business-analyse-review}/SKILL.md +11 -10
  102. package/templates/skills/{ba-review → business-analyse-review}/references/review-data-mapping.md +2 -2
  103. package/templates/skills/business-analyse-review/steps/step-00-init.md +107 -0
  104. package/templates/skills/{ba-review → business-analyse-review}/steps/step-01-apply.md +19 -11
  105. package/templates/skills/business-analyse-status/SKILL.md +118 -0
  106. package/templates/skills/documentation/SKILL.md +2 -2
  107. package/templates/skills/sketch/SKILL.md +172 -0
  108. package/templates/skills/sketch/references/domain-heuristics.md +116 -0
  109. package/templates/skills/ba-generate-html/html/src/styles/02-layout.css +0 -101
  110. package/templates/skills/ralph-loop/SKILL.md +0 -240
  111. /package/templates/skills/{ba-design-ui → business-analyse-design}/steps/step-02-wireframes.md +0 -0
  112. /package/templates/skills/{ralph-loop → business-analyse-develop}/references/category-rules.md +0 -0
  113. /package/templates/skills/{ralph-loop → business-analyse-develop}/references/compact-loop.md +0 -0
  114. /package/templates/skills/{ralph-loop → business-analyse-develop}/references/module-transition.md +0 -0
  115. /package/templates/skills/{ralph-loop → business-analyse-develop}/references/parallel-execution.md +0 -0
  116. /package/templates/skills/{ralph-loop → business-analyse-develop}/references/section-splitting.md +0 -0
  117. /package/templates/skills/{ralph-loop → business-analyse-develop}/references/team-orchestration.md +0 -0
  118. /package/templates/skills/{ralph-loop → business-analyse-develop}/steps/step-02-execute.md +0 -0
  119. /package/templates/skills/{ralph-loop → business-analyse-develop}/steps/step-03-commit.md +0 -0
  120. /package/templates/skills/{derive-prd → business-analyse-handoff}/references/entity-domain-mapping.md +0 -0
  121. /package/templates/skills/{derive-prd → business-analyse-handoff}/references/readiness-scoring.md +0 -0
  122. /package/templates/skills/{derive-prd → business-analyse-handoff}/templates/tpl-progress.md +0 -0
  123. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/cadrage-context.html +0 -0
  124. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/cadrage-scope.html +0 -0
  125. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/cadrage-stakeholders.html +0 -0
  126. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/cadrage-success.html +0 -0
  127. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/consol-datamodel.html +0 -0
  128. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/consol-flows.html +0 -0
  129. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/consol-interactions.html +0 -0
  130. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/consol-permissions.html +0 -0
  131. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/decomp-dependencies.html +0 -0
  132. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/decomp-modules.html +0 -0
  133. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/handoff-summary.html +0 -0
  134. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/partials/module-spec-container.html +0 -0
  135. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/01-variables.css +0 -0
  136. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/03-navigation.css +0 -0
  137. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/04-cards.css +0 -0
  138. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/06-wireframes.css +0 -0
  139. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/07-comments.css +0 -0
  140. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/08-review-panel.css +0 -0
  141. /package/templates/skills/{ba-generate-html → business-analyse-html}/html/src/styles/09-mockups-html.css +0 -0
  142. /package/templates/skills/{ba-generate-html → business-analyse-html}/references/wireframe-svg-style-guide.md +0 -0
@@ -60,8 +60,28 @@ function resolvePartials(template) {
60
60
  return resolved;
61
61
  }
62
62
 
63
+ function minifyCss(css) {
64
+ return css
65
+ .replace(/\/\*[\s\S]*?\*\//g, '') // remove comments
66
+ .replace(/\s*([{}:;,>~+])\s*/g, '$1') // remove whitespace around symbols
67
+ .replace(/\s+/g, ' ') // collapse whitespace
68
+ .replace(/;\s*}/g, '}') // remove trailing semicolons
69
+ .trim();
70
+ }
71
+
72
+ function minifyJs(js) {
73
+ // Light minification — remove comments and collapse whitespace (no AST transform)
74
+ return js
75
+ .replace(/\/\*[\s\S]*?\*\//g, '') // remove block comments
76
+ .replace(/\/\/.*$/gm, '') // remove line comments
77
+ .replace(/^\s*\n/gm, '') // remove empty lines
78
+ .replace(/\n\s+/g, '\n') // reduce leading whitespace
79
+ .trim();
80
+ }
81
+
63
82
  function build() {
64
- console.log('[build-html] Starting build...');
83
+ const doMinify = process.argv.includes('--minify');
84
+ console.log('[build-html] Starting build...' + (doMinify ? ' (minified)' : ''));
65
85
 
66
86
  // Read template
67
87
  if (!fs.existsSync(TEMPLATE_FILE)) {
@@ -80,12 +100,14 @@ function build() {
80
100
  // Read and concatenate CSS files
81
101
  const cssFiles = readSortedFiles(STYLES_DIR, '.css');
82
102
  console.log(`[build-html] CSS files: ${cssFiles.map(f => f.name).join(', ')}`);
83
- const css = cssFiles.map(f => `/* --- ${f.name} --- */\n${f.content}`).join('\n\n');
103
+ let css = cssFiles.map(f => `/* --- ${f.name} --- */\n${f.content}`).join('\n\n');
104
+ if (doMinify) css = minifyCss(css);
84
105
 
85
106
  // Read and concatenate JS files
86
107
  const jsFiles = readSortedFiles(SCRIPTS_DIR, '.js');
87
108
  console.log(`[build-html] JS files: ${jsFiles.map(f => f.name).join(', ')}`);
88
- const js = jsFiles.map(f => `/* --- ${f.name} --- */\n${f.content}`).join('\n\n');
109
+ let js = jsFiles.map(f => `/* --- ${f.name} --- */\n${f.content}`).join('\n\n');
110
+ if (doMinify) js = minifyJs(js);
89
111
 
90
112
  // Inject into template
91
113
  template = template.replace('<!-- CSS_PLACEHOLDER -->', css);
@@ -73,8 +73,23 @@ data.moduleSpecs = data.moduleSpecs || {};
73
73
  if (!data.moduleSpecs[m.code].screens) {
74
74
  data.moduleSpecs[m.code].screens = [];
75
75
  }
76
+ // Ensure sections have initialized arrays for hierarchical data
77
+ m.anticipatedSections.forEach(function(section) {
78
+ section.useCases = section.useCases || [];
79
+ section.businessRules = section.businessRules || [];
80
+ section.resources = section.resources || [];
81
+ section.permission = section.permission || '';
82
+ section.route = section.route || '';
83
+ });
76
84
  });
77
85
 
86
+ // Detect if modules use section-level specs (hierarchical mode)
87
+ function hasHierarchicalSpecs(mod) {
88
+ return (mod.anticipatedSections || []).some(function(s) {
89
+ return (s.useCases && s.useCases.length > 0) || (s.businessRules && s.businessRules.length > 0);
90
+ });
91
+ }
92
+
78
93
  // Defensive: normalize stakeholder tasks (string → array)
79
94
  (data.cadrage.stakeholders || []).forEach(function(s) {
80
95
  if (typeof s.tasks === 'string') {
@@ -146,6 +161,45 @@ function formatModuleType(t) {
146
161
  return { 'data-centric': 'Données', 'workflow': 'Processus', 'reporting': 'Rapports', 'integration': 'Intégration', 'full-module': 'Complet' }[t] || t;
147
162
  }
148
163
 
164
+ function escapeHtml(s) {
165
+ if (s == null) return '';
166
+ var d = document.createElement('div');
167
+ d.textContent = String(s);
168
+ return d.innerHTML;
169
+ }
170
+
171
+ function computeProgress() {
172
+ var totalModules = data.modules.length;
173
+ var modulesWithUC = 0, modulesWithBR = 0, modulesWithEntities = 0, modulesWithWireframes = 0;
174
+ var totalUCs = 0, totalBRs = 0, totalEntities = 0;
175
+
176
+ data.modules.forEach(function(m) {
177
+ var spec = data.moduleSpecs[m.code] || {};
178
+ var ucs = (spec.useCases || []).length;
179
+ var brs = (spec.businessRules || []).length;
180
+ var ents = (spec.entities || []).length;
181
+ var wfs = (EMBEDDED_ARTIFACTS?.wireframes?.[m.code] || []).length + (spec.screens || []).length;
182
+ totalUCs += ucs; totalBRs += brs; totalEntities += ents;
183
+ if (ucs > 0) modulesWithUC++;
184
+ if (brs > 0) modulesWithBR++;
185
+ if (ents > 0) modulesWithEntities++;
186
+ if (wfs > 0) modulesWithWireframes++;
187
+ });
188
+
189
+ var checks = [];
190
+ if (totalModules > 0) checks.push({ done: true, label: 'Modules définis (' + totalModules + ')' });
191
+ checks.push({ done: modulesWithUC === totalModules && totalModules > 0, label: 'Cas d\'utilisation (' + modulesWithUC + '/' + totalModules + ' modules)' });
192
+ checks.push({ done: modulesWithBR === totalModules && totalModules > 0, label: 'Règles métier (' + modulesWithBR + '/' + totalModules + ' modules)' });
193
+ checks.push({ done: modulesWithEntities === totalModules && totalModules > 0, label: 'Données (' + modulesWithEntities + '/' + totalModules + ' modules)' });
194
+ checks.push({ done: modulesWithWireframes === totalModules && totalModules > 0, label: 'Maquettes (' + modulesWithWireframes + '/' + totalModules + ' modules)' });
195
+ checks.push({ done: data.cadrage.stakeholders.length > 0, label: 'Parties prenantes (' + data.cadrage.stakeholders.length + ')' });
196
+ checks.push({ done: (data.cadrage.scope.inscope || []).length > 0, label: 'Périmètre défini' });
197
+
198
+ var doneCount = checks.filter(function(c) { return c.done; }).length;
199
+ var pct = checks.length > 0 ? Math.round(doneCount / checks.length * 100) : 0;
200
+ return { checks: checks, doneCount: doneCount, total: checks.length, pct: pct, totalUCs: totalUCs, totalBRs: totalBRs, totalEntities: totalEntities };
201
+ }
202
+
149
203
  /* ============================================
150
204
  INITIALIZATION
151
205
  ============================================ */
@@ -174,17 +174,20 @@ function renderModuleNavItem(mod) {
174
174
  if (sections.length > 0) {
175
175
  sections.forEach(function(section) {
176
176
  var resources = section.resources || [];
177
+ var sectionUCs = (section.useCases || []).length;
178
+ var sectionBRs = (section.businessRules || []).length;
179
+ var contentCount = sectionUCs + sectionBRs + resources.length;
177
180
  html += '<div class="nav-section-item">';
178
181
  html += '<a class="nav-item nav-section-link" onclick="showSection(\'module-spec-' + code + '\');switchTab(\'' + code + '\',\'struct\')" data-section="module-struct-' + code + '-' + section.code + '">';
179
- html += '<span class="nav-icon nav-icon-section">&#9655;</span> ' + section.code;
180
- if (resources.length > 0) html += ' <span class="nav-badge">' + resources.length + '</span>';
182
+ html += '<span class="nav-icon nav-icon-section">&#9655;</span> ' + escapeHtml(section.code || section.name || '');
183
+ if (contentCount > 0) html += ' <span class="nav-badge">' + contentCount + '</span>';
181
184
  html += '</a>';
182
185
  if (resources.length > 0) {
183
186
  html += '<div class="nav-children nav-resources">';
184
187
  resources.forEach(function(res) {
185
188
  var resName = typeof res === 'string' ? res : (res.code || res.name || '');
186
189
  html += '<a class="nav-item nav-resource-link">';
187
- html += '<span class="nav-icon nav-icon-resource">&#8226;</span> ' + resName;
190
+ html += '<span class="nav-icon nav-icon-resource">&#8226;</span> ' + escapeHtml(resName);
188
191
  html += '</a>';
189
192
  });
190
193
  html += '</div>';
@@ -250,3 +253,94 @@ function highlightActiveNavItem() {
250
253
  var navItem = document.querySelector('#sidebarNav [data-section="' + currentSectionId + '"]');
251
254
  if (navItem) navItem.classList.add('active');
252
255
  }
256
+
257
+ /* ---------- Mobile Sidebar ---------- */
258
+
259
+ function toggleMobileSidebar() {
260
+ var sidebar = document.getElementById('sidebarAside');
261
+ var overlay = document.getElementById('sidebarOverlay');
262
+ if (!sidebar) return;
263
+ var isOpen = sidebar.classList.contains('mobile-open');
264
+ sidebar.classList.toggle('mobile-open', !isOpen);
265
+ if (overlay) overlay.classList.toggle('visible', !isOpen);
266
+ }
267
+
268
+ /* ---------- Search / Filter ---------- */
269
+
270
+ var _searchTimer;
271
+ function filterNavItems(query) {
272
+ clearTimeout(_searchTimer);
273
+ _searchTimer = setTimeout(function() { doFilterNavItems(query); }, 200);
274
+ }
275
+
276
+ function doFilterNavItems(query) {
277
+ var q = (query || '').toLowerCase().trim();
278
+ var nav = document.getElementById('sidebarNav');
279
+ if (!nav) return;
280
+
281
+ // Clear previous highlights
282
+ nav.querySelectorAll('.search-highlight').forEach(function(el) {
283
+ el.outerHTML = el.textContent;
284
+ });
285
+
286
+ if (!q) {
287
+ // Show all items
288
+ nav.querySelectorAll('.nav-item, .nav-group, .nav-module, .nav-section-item').forEach(function(el) {
289
+ el.classList.remove('search-hidden');
290
+ });
291
+ return;
292
+ }
293
+
294
+ // Filter nav items
295
+ var allItems = nav.querySelectorAll('.nav-item');
296
+ var visibleSections = new Set();
297
+
298
+ allItems.forEach(function(item) {
299
+ var text = item.textContent.toLowerCase();
300
+ if (text.includes(q)) {
301
+ item.classList.remove('search-hidden');
302
+ // Show parent groups
303
+ var parent = item.parentElement;
304
+ while (parent && parent.id !== 'sidebarNav') {
305
+ parent.classList.remove('search-hidden');
306
+ if (parent.querySelector(':scope > .nav-children')) {
307
+ var children = parent.querySelector(':scope > .nav-children');
308
+ if (children) children.style.display = '';
309
+ }
310
+ parent = parent.parentElement;
311
+ }
312
+ // Track section for content search
313
+ var sectionId = item.dataset.section;
314
+ if (sectionId) visibleSections.add(sectionId);
315
+ } else {
316
+ item.classList.add('search-hidden');
317
+ }
318
+ });
319
+
320
+ // Hide groups that have no visible children
321
+ nav.querySelectorAll('.nav-group, .nav-module').forEach(function(group) {
322
+ var visibleChildren = group.querySelectorAll('.nav-item:not(.search-hidden)');
323
+ if (visibleChildren.length === 0) {
324
+ group.classList.add('search-hidden');
325
+ } else {
326
+ group.classList.remove('search-hidden');
327
+ }
328
+ });
329
+
330
+ // Also search in section content and show matching sections
331
+ document.querySelectorAll('.section').forEach(function(section) {
332
+ var text = section.textContent.toLowerCase();
333
+ if (text.includes(q) && !visibleSections.has(section.id)) {
334
+ // Unhide corresponding nav item
335
+ var navItem = nav.querySelector('[data-section="' + section.id + '"]');
336
+ if (navItem) {
337
+ navItem.classList.remove('search-hidden');
338
+ var parent = navItem.parentElement;
339
+ while (parent && parent.id !== 'sidebarNav') {
340
+ parent.classList.remove('search-hidden');
341
+ parent = parent.parentElement;
342
+ }
343
+ }
344
+ }
345
+ });
346
+ }
@@ -42,23 +42,24 @@ function renderStakeholders() {
42
42
  grid.innerHTML = data.cadrage.stakeholders.map((s, i) => `
43
43
  <div class="stakeholder-card">
44
44
  <div style="display:flex;justify-content:space-between;align-items:start;">
45
- <div class="stakeholder-role">${s.role}</div>
45
+ <div class="stakeholder-role">${escapeHtml(s.role)}</div>
46
46
  <button class="btn btn-sm" onclick="removeStakeholder(${i})" style="opacity:0.5;font-size:0.7rem;">Supprimer</button>
47
47
  </div>
48
- <div class="stakeholder-function">${s.function || ''}</div>
48
+ <div class="stakeholder-function">${escapeHtml(s.function || '')}</div>
49
49
  <ul class="stakeholder-tasks">
50
- ${(Array.isArray(s.tasks) ? s.tasks : typeof s.tasks === 'string' ? s.tasks.split(',').map(t => t.trim()).filter(Boolean) : []).map(t => '<li>' + t + '</li>').join('')}
50
+ ${(Array.isArray(s.tasks) ? s.tasks : typeof s.tasks === 'string' ? s.tasks.split(',').map(t => t.trim()).filter(Boolean) : []).map(t => '<li>' + escapeHtml(t) + '</li>').join('')}
51
51
  </ul>
52
52
  <div class="stakeholder-meta">
53
53
  <span>${formatFrequency(s.frequency)}</span>
54
54
  <span>${formatAccess(s.access)}</span>
55
55
  </div>
56
- ${s.frustrations ? '<div style="font-size:0.8rem;color:var(--warning);margin-top:0.5rem;font-style:italic;">' + s.frustrations + '</div>' : ''}
56
+ ${s.frustrations ? '<div style="font-size:0.8rem;color:var(--warning);margin-top:0.5rem;font-style:italic;">' + escapeHtml(s.frustrations) + '</div>' : ''}
57
57
  </div>
58
58
  `).join('');
59
59
  }
60
60
 
61
61
  function removeStakeholder(index) {
62
+ if (!confirm('Supprimer ce profil utilisateur ?')) return;
62
63
  data.cadrage.stakeholders.splice(index, 1);
63
64
  renderStakeholders();
64
65
  updateCounts();
@@ -89,12 +90,12 @@ function renderScope() {
89
90
  <div class="uc-item">
90
91
  <div class="uc-header">
91
92
  <span class="priority priority-${p}">${formatPriority(p)}</span>
92
- <span class="uc-title">${item.name}</span>
93
+ <span class="uc-title">${escapeHtml(item.name)}</span>
93
94
  <div class="uc-actions">
94
95
  <button class="btn btn-sm" onclick="removeScopeItem('${p}',${i})">Supprimer</button>
95
96
  </div>
96
97
  </div>
97
- ${item.description ? '<div class="uc-detail">' + item.description + '</div>' : ''}
98
+ ${item.description ? '<div class="uc-detail">' + escapeHtml(item.description) + '</div>' : ''}
98
99
  </div>
99
100
  `).join('');
100
101
  });
@@ -139,7 +140,7 @@ function renderCriteria() {
139
140
  container.innerHTML = criteria.map((c, i) => `
140
141
  <div class="uc-item" style="display:flex;align-items:center;gap:0.75rem;">
141
142
  <input type="checkbox" ${c.validated ? 'checked' : ''} onchange="toggleCriterion(${i})" style="cursor:pointer;width:18px;height:18px;flex-shrink:0;">
142
- <span style="flex:1;${c.validated ? 'text-decoration:line-through;color:var(--text-muted);' : ''}">${c.text}</span>
143
+ <span style="flex:1;${c.validated ? 'text-decoration:line-through;color:var(--text-muted);' : ''}">${escapeHtml(c.text)}</span>
143
144
  <button class="btn btn-sm" onclick="removeCriterion(${i})" style="opacity:0.5;flex-shrink:0;">&#10005;</button>
144
145
  </div>
145
146
  `).join('');
@@ -55,10 +55,10 @@ function renderModules() {
55
55
  <div class="module-card" onclick="showSection('module-spec-${m.code}')">
56
56
  <button class="module-card-remove" onclick="event.stopPropagation();removeModule(${i})">&#10005;</button>
57
57
  <div class="module-card-header">
58
- <span class="module-card-code">${m.name}</span>
58
+ <span class="module-card-code">${escapeHtml(m.name)}</span>
59
59
  <span class="module-card-type">${formatModuleType(m.featureType)}</span>
60
60
  </div>
61
- <div class="module-card-desc">${m.description || ''}</div>
61
+ <div class="module-card-desc">${escapeHtml(m.description || '')}</div>
62
62
  <div class="module-card-meta">
63
63
  <span>${(m.entities || []).length} données</span>
64
64
  <span>${(data.moduleSpecs[m.code]?.useCases || []).length} cas d'utilisation</span>
@@ -115,10 +115,10 @@ function renderDependencies() {
115
115
  const toName = data.modules.find(m => m.code === d.to)?.name || d.to;
116
116
  return `
117
117
  <div class="interaction-item">
118
- <span style="font-weight:600;color:var(--text-bright);">${fromName}</span>
118
+ <span style="font-weight:600;color:var(--text-bright);">${escapeHtml(fromName)}</span>
119
119
  <span class="interaction-arrow">&#8594;</span>
120
- <span style="font-weight:600;color:var(--text-bright);">${toName}</span>
121
- <span style="flex:1;font-size:0.8rem;color:var(--text-muted);">${d.description || ''}</span>
120
+ <span style="font-weight:600;color:var(--text-bright);">${escapeHtml(toName)}</span>
121
+ <span style="flex:1;font-size:0.8rem;color:var(--text-muted);">${escapeHtml(d.description || '')}</span>
122
122
  <button class="btn btn-sm" onclick="removeDependency(${i})" style="opacity:0.5;">Supprimer</button>
123
123
  </div>
124
124
  `;
@@ -147,7 +147,7 @@ function renderDepGraph() {
147
147
  <div class="dep-layer-modules">
148
148
  ${layer.map(code => {
149
149
  const m = data.modules.find(mod => mod.code === code);
150
- return `<div class="dep-module">${m ? (m.name || m.code) : code}</div>`;
150
+ return `<div class="dep-module">${escapeHtml(m ? (m.name || m.code) : code)}</div>`;
151
151
  }).join('')}
152
152
  </div>
153
153
  </div>
@@ -195,7 +195,7 @@ function renderProcessingOrder() {
195
195
  return `
196
196
  <div class="process-step">
197
197
  <div class="process-step-number">Étape ${i + 1}</div>
198
- <div class="process-step-label">${m ? (m.name || m.code) : code}</div>
198
+ <div class="process-step-label">${escapeHtml(m ? (m.name || m.code) : code)}</div>
199
199
  </div>
200
200
  ${i < order.length - 1 ? '<div class="process-arrow">&#8594;</div>' : ''}
201
201
  `;