@atlashub/smartstack-cli 4.19.0 → 4.21.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 (73) hide show
  1. package/package.json +2 -2
  2. package/templates/skills/ba-generate-html/SKILL.md +60 -0
  3. package/templates/skills/{business-analyse → ba-generate-html}/html/ba-interactive.html +3 -3
  4. package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/cadrage-risks.html +1 -1
  5. package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/02-navigation.js +1 -1
  6. package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/07-render-handoff.js +1 -1
  7. package/templates/skills/{business-analyse → ba-generate-html}/html/src/template.html +1 -1
  8. package/templates/skills/{business-analyse/references/deploy-data-build.md → ba-generate-html/references/data-build.md} +2 -2
  9. package/templates/skills/{business-analyse/references/html-data-mapping.md → ba-generate-html/references/data-mapping.md} +2 -2
  10. package/templates/skills/{business-analyse/references/deploy-modes.md → ba-generate-html/references/output-modes.md} +1 -1
  11. package/templates/skills/ba-generate-html/steps/step-01-collect.md +113 -0
  12. package/templates/skills/ba-generate-html/steps/step-02-build-data.md +237 -0
  13. package/templates/skills/ba-generate-html/steps/step-03-render.md +75 -0
  14. package/templates/skills/ba-generate-html/steps/step-04-verify.md +83 -0
  15. package/templates/skills/ba-review/SKILL.md +45 -0
  16. package/templates/skills/{business-analyse → ba-review}/references/review-data-mapping.md +2 -2
  17. package/templates/skills/{business-analyse/steps/step-06-review.md → ba-review/steps/step-01-apply.md} +7 -18
  18. package/templates/skills/business-analyse/SKILL.md +24 -59
  19. package/templates/skills/business-analyse/_shared.md +9 -14
  20. package/templates/skills/business-analyse/questionnaire/01-context.md +11 -157
  21. package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +9 -50
  22. package/templates/skills/business-analyse/questionnaire/03-data-ui.md +1 -3
  23. package/templates/skills/business-analyse/questionnaire/04-risks-metrics.md +4 -148
  24. package/templates/skills/business-analyse/questionnaire/05-cross-module.md +5 -5
  25. package/templates/skills/business-analyse/questionnaire.md +7 -8
  26. package/templates/skills/business-analyse/react/components.md +1 -1
  27. package/templates/skills/business-analyse/react/schema.md +1 -1
  28. package/templates/skills/business-analyse/references/acceptance-criteria.md +2 -7
  29. package/templates/skills/business-analyse/references/detection-strategies.md +3 -3
  30. package/templates/skills/business-analyse/references/naming-conventions.md +2 -2
  31. package/templates/skills/business-analyse/references/robustness-checks.md +2 -121
  32. package/templates/skills/business-analyse/references/validation-checklist.md +3 -4
  33. package/templates/skills/business-analyse/schemas/feature-schema.json +1 -1
  34. package/templates/skills/business-analyse/steps/step-00-init.md +6 -9
  35. package/templates/skills/business-analyse/steps/step-01-cadrage.md +9 -49
  36. package/templates/skills/business-analyse/steps/step-04-consolidate.md +13 -6
  37. package/templates/skills/business-analyse/templates/tpl-handoff.md +1 -1
  38. package/templates/skills/business-analyse/templates/tpl-launch-displays.md +1 -1
  39. package/templates/skills/documentation/SKILL.md +7 -0
  40. package/templates/skills/business-analyse/steps/step-05-deploy.md +0 -220
  41. /package/templates/skills/{business-analyse → ba-generate-html}/html/build-html.js +0 -0
  42. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/cadrage-context.html +0 -0
  43. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/cadrage-scope.html +0 -0
  44. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/cadrage-stakeholders.html +0 -0
  45. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/cadrage-success.html +0 -0
  46. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/consol-datamodel.html +0 -0
  47. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/consol-flows.html +0 -0
  48. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/consol-interactions.html +0 -0
  49. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/consol-permissions.html +0 -0
  50. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/decomp-dependencies.html +0 -0
  51. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/decomp-modules.html +0 -0
  52. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/handoff-summary.html +0 -0
  53. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/partials/module-spec-container.html +0 -0
  54. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/01-data-init.js +0 -0
  55. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/03-render-cadrage.js +0 -0
  56. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/04-render-modules.js +0 -0
  57. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/05-render-specs.js +0 -0
  58. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/06-render-consolidation.js +0 -0
  59. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/06-render-mockups.js +0 -0
  60. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/08-editing.js +0 -0
  61. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/09-export.js +0 -0
  62. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/10-comments.js +0 -0
  63. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/scripts/11-review-panel.js +0 -0
  64. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/01-variables.css +0 -0
  65. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/02-layout.css +0 -0
  66. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/03-navigation.css +0 -0
  67. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/04-cards.css +0 -0
  68. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/05-modules.css +0 -0
  69. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/06-wireframes.css +0 -0
  70. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/07-comments.css +0 -0
  71. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/08-review-panel.css +0 -0
  72. /package/templates/skills/{business-analyse → ba-generate-html}/html/src/styles/09-mockups-html.css +0 -0
  73. /package/templates/skills/{business-analyse → ba-generate-html}/references/wireframe-svg-style-guide.md +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlashub/smartstack-cli",
3
- "version": "4.19.0",
3
+ "version": "4.21.0",
4
4
  "description": "SmartStack Claude Code automation toolkit - GitFlow, EF Core migrations, prompts and more",
5
5
  "author": {
6
6
  "name": "SmartStack",
@@ -54,7 +54,7 @@
54
54
  "scripts": {
55
55
  "postinstall": "node scripts/postinstall.js || exit 0",
56
56
  "dev": "tsup --watch",
57
- "build:html": "node templates/skills/business-analyse/html/build-html.js",
57
+ "build:html": "node templates/skills/ba-generate-html/html/build-html.js",
58
58
  "build": "npm run build:html && npx tsup",
59
59
  "lint": "eslint src --ext .ts",
60
60
  "format": "prettier --write \"src/**/*.ts\"",
@@ -0,0 +1,60 @@
1
+ ---
2
+ name: ba-generate-html
3
+ description: "Generate the interactive HTML document from business analysis JSON data"
4
+ model: opus
5
+ user_invocable: true
6
+ ---
7
+
8
+ # /ba-generate-html
9
+
10
+ Generate the interactive HTML document of the business analysis from the JSON analysis files.
11
+
12
+ ## Triggers
13
+
14
+ - Explicit invocation: `/ba-generate-html <feature-id>`
15
+ - After `/business-analyse` step-04 (consolidation complete)
16
+ - Delegation from `/ba-review` (after review corrections applied)
17
+
18
+ ## Parameters
19
+
20
+ | Parameter | Required | Description |
21
+ |-----------|----------|-------------|
22
+ | `<feature-id>` | Yes | Feature identifier (e.g., FEAT-001) |
23
+ | `--force` | No | Regenerate even if HTML already exists |
24
+
25
+ ## Prerequisites
26
+
27
+ - JSON analysis files must exist (at minimum `index.json` + `cadrage.json`)
28
+ - PRD files must exist (`.ralph/prd-{moduleCode}.json`) — run `/derive-prd` first
29
+ - Feature status must be `consolidated`
30
+
31
+ ## Workflow
32
+
33
+ 4 progressive steps:
34
+
35
+ | Step | File | Role |
36
+ |------|------|------|
37
+ | 01 | `steps/step-01-collect.md` | Read JSON sources (index, cadrage, modules, consolidation) |
38
+ | 02 | `steps/step-02-build-data.md` | Build FEATURE_DATA + EMBEDDED_ARTIFACTS objects |
39
+ | 03 | `steps/step-03-render.md` | Inject into ba-interactive.html template, write final file |
40
+ | 04 | `steps/step-04-verify.md` | POST-CHECK (size, sections, coherence) |
41
+
42
+ ## Absolute Rules
43
+
44
+ - **NEVER** deploy an empty template — FEATURE_DATA must be injected
45
+ - **moduleSpecs** MUST have ONE entry per module (empty = BROKEN)
46
+ - **Scope keys** MUST be converted: `mustHave` → `vital`, `shouldHave` → `important`, `couldHave` → `optional`, `outOfScope` → `excluded`
47
+ - **Wireframe fields** MUST be renamed: `mockupFormat` → `format`, `mockup` → `content`
48
+ - **Final file** MUST be > 100KB
49
+
50
+ ## References
51
+
52
+ | File | Content |
53
+ |------|---------|
54
+ | `references/data-mapping.md` | JSON → FEATURE_DATA field mapping |
55
+ | `references/data-build.md` | FEATURE_DATA & EMBEDDED_ARTIFACTS construction |
56
+ | `references/output-modes.md` | Standard, micro, delta, multi-app modes |
57
+
58
+ ## Entry Point
59
+
60
+ **FIRST ACTION:** Load `steps/step-01-collect.md`
@@ -1960,7 +1960,7 @@ body {
1960
1960
  </div>
1961
1961
 
1962
1962
  <!-- SECTION: Risques et hypotheses -->
1963
- <div class="section" id="cadrage-risks" style="display:none;">
1963
+ <div class="section" id="cadrage-risks" style="display:none;" data-vibe-hide>
1964
1964
  <h2 class="section-title">Risques et hypotheses</h2>
1965
1965
  <p class="section-subtitle">Ce qui pourrait mal tourner et les certitudes non verifiees.</p>
1966
1966
 
@@ -2562,7 +2562,7 @@ function buildCadrageItems() {
2562
2562
  return renderNavItem('cadrage-context', 'Contexte') +
2563
2563
  renderNavItem('cadrage-stakeholders', 'Parties prenantes', data.cadrage.stakeholders.length) +
2564
2564
  renderNavItem('cadrage-scope', 'Perimetre fonctionnel') +
2565
- renderNavItem('cadrage-risks', 'Risques et hypotheses', data.cadrage.risks.length) +
2565
+ (isVibeCoding ? '' : renderNavItem('cadrage-risks', 'Risques et hypotheses', data.cadrage.risks.length)) +
2566
2566
  renderNavItem('cadrage-success', 'Criteres de reussite');
2567
2567
  }
2568
2568
 
@@ -4399,7 +4399,7 @@ function renderHandoffStats() {
4399
4399
  <div class="stat-card"><div class="stat-value">${totalStakeholders}</div><div class="stat-label">Profils utilisateurs</div></div>
4400
4400
  <div class="stat-card"><div class="stat-value">${data.dependencies.length}</div><div class="stat-label">Dependances</div></div>
4401
4401
  <div class="stat-card"><div class="stat-value">${data.consolidation.e2eFlows.length}</div><div class="stat-label">Parcours bout en bout</div></div>
4402
- <div class="stat-card"><div class="stat-value">${data.cadrage.risks.length}</div><div class="stat-label">Risques identifies</div></div>
4402
+ ${isVibeCoding ? '' : `<div class="stat-card"><div class="stat-value">${data.cadrage.risks.length}</div><div class="stat-label">Risques identifies</div></div>`}
4403
4403
  `;
4404
4404
  }
4405
4405
 
@@ -1,5 +1,5 @@
1
1
  <!-- SECTION: Risques et hypotheses -->
2
- <div class="section" id="cadrage-risks" style="display:none;">
2
+ <div class="section" id="cadrage-risks" style="display:none;" data-vibe-hide>
3
3
  <h2 class="section-title">Risques et hypotheses</h2>
4
4
  <p class="section-subtitle">Ce qui pourrait mal tourner et les certitudes non verifiees.</p>
5
5
 
@@ -113,7 +113,7 @@ function buildCadrageItems() {
113
113
  return renderNavItem('cadrage-context', 'Contexte') +
114
114
  renderNavItem('cadrage-stakeholders', 'Parties prenantes', data.cadrage.stakeholders.length) +
115
115
  renderNavItem('cadrage-scope', 'Perimetre fonctionnel') +
116
- renderNavItem('cadrage-risks', 'Risques et hypotheses', data.cadrage.risks.length) +
116
+ (isVibeCoding ? '' : renderNavItem('cadrage-risks', 'Risques et hypotheses', data.cadrage.risks.length)) +
117
117
  renderNavItem('cadrage-success', 'Criteres de reussite');
118
118
  }
119
119
 
@@ -24,7 +24,7 @@ function renderHandoffStats() {
24
24
  <div class="stat-card"><div class="stat-value">${totalStakeholders}</div><div class="stat-label">Profils utilisateurs</div></div>
25
25
  <div class="stat-card"><div class="stat-value">${data.dependencies.length}</div><div class="stat-label">Dependances</div></div>
26
26
  <div class="stat-card"><div class="stat-value">${data.consolidation.e2eFlows.length}</div><div class="stat-label">Parcours bout en bout</div></div>
27
- <div class="stat-card"><div class="stat-value">${data.cadrage.risks.length}</div><div class="stat-label">Risques identifies</div></div>
27
+ ${isVibeCoding ? '' : `<div class="stat-card"><div class="stat-value">${data.cadrage.risks.length}</div><div class="stat-label">Risques identifies</div></div>`}
28
28
  `;
29
29
  }
30
30
 
@@ -193,7 +193,7 @@
193
193
  </div>
194
194
 
195
195
  <!-- SECTION: Risques et hypotheses -->
196
- <div class="section" id="cadrage-risks" style="display:none;">
196
+ <div class="section" id="cadrage-risks" style="display:none;" data-vibe-hide>
197
197
  <h2 class="section-title">Risques et hypotheses</h2>
198
198
  <p class="section-subtitle">Ce qui pourrait mal tourner et les certitudes non verifiees.</p>
199
199
 
@@ -1,7 +1,7 @@
1
1
  # FEATURE_DATA & EMBEDDED_ARTIFACTS Build Reference
2
2
 
3
- > Reference for step-05-deploy.md — complete mapping specification for the interactive HTML.
4
- > **Canonical field mapping reference:** See also `html-data-mapping.md` for the authoritative field name mapping between module JSON files and HTML data objects.
3
+ > Reference for `/ba-generate-html` skill (step-02-build-data) — complete mapping specification for the interactive HTML.
4
+ > **Canonical field mapping reference:** See also `data-mapping.md` for the authoritative field name mapping between module JSON files and HTML data objects.
5
5
 
6
6
  ## FEATURE_DATA Object
7
7
 
@@ -1,6 +1,6 @@
1
- # HTML Data Mapping Reference (references/html-data-mapping.md)
1
+ # HTML Data Mapping Reference
2
2
 
3
- > **Used by:** step-05-deploy (Deploy Interactive HTML)
3
+ > **Used by:** `/ba-generate-html` skill (step-02-build-data)
4
4
  > **Purpose:** Exact mapping from module JSON files to HTML FEATURE_DATA and EMBEDDED_ARTIFACTS objects
5
5
 
6
6
  ---
@@ -1,6 +1,6 @@
1
1
  # Deploy Mode Support & Troubleshooting
2
2
 
3
- > Reference for step-05-deploy.md (HTML deployment) and `/derive-prd` skill (handoff + PRD generation) — mode variations and common issues.
3
+ > Reference for `/ba-generate-html` skill (HTML deployment) and `/derive-prd` skill (handoff + PRD generation) — mode variations and common issues.
4
4
 
5
5
  ## Mode Support
6
6
 
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: step-01-collect
3
+ description: Collect all JSON source data for HTML generation
4
+ model: opus
5
+ next_step: steps/step-02-build-data.md
6
+ ---
7
+
8
+ # Step 1: Collect JSON Sources
9
+
10
+ ## YOUR TASK
11
+
12
+ Read all JSON analysis files for the feature and store them as `{collected_data}` for the next step.
13
+
14
+ ---
15
+
16
+ ## EXECUTION SEQUENCE
17
+
18
+ ### 1. Locate Feature
19
+
20
+ ```
21
+ 1. Read feature_id from parameters
22
+ 2. Locate master index.json:
23
+ - Multi-app (project): docs/business-analyse/v{version}/index.json
24
+ - Single-app: docs/{app}/business-analyse/v{version}/index.json
25
+ 3. IF index.json NOT found → BLOCKING ERROR: "index.json not found — run /business-analyse first"
26
+ ```
27
+
28
+ ### 2. Detect Mode
29
+
30
+ ```
31
+ IF index.json contains "applications[]" with multiple entries:
32
+ mode = "project" (multi-app)
33
+ ELSE:
34
+ mode = "single-app"
35
+
36
+ Store: workflow.mode
37
+ ```
38
+
39
+ ### 3. Verify PRD Exists
40
+
41
+ ```
42
+ FOR each module in modules:
43
+ prdPath = ".ralph/prd-{moduleCode}.json"
44
+ IF NOT exists(prdPath):
45
+ BLOCKING ERROR: "PRD not found: {prdPath} — Run /derive-prd first"
46
+ STOP
47
+ IF fileSize(prdPath) < 100:
48
+ BLOCKING ERROR: "PRD file too small: {prdPath} — Run /derive-prd to regenerate"
49
+ STOP
50
+ ```
51
+
52
+ ### 4. Verify Consolidation Status
53
+
54
+ ```
55
+ IF workflow.mode === "project":
56
+ projectFeature = ba-reader.findProjectFeature()
57
+ FOR each app in projectFeature.applications:
58
+ appFeature = ba-reader.findFeature(app.featureJsonPath)
59
+ IF appFeature.status !== "consolidated":
60
+ BLOCKING ERROR: "Application {app.code} not consolidated"
61
+ ELSE:
62
+ feature = ba-reader.findFeature({feature_id})
63
+ IF feature.status !== "consolidated":
64
+ BLOCKING ERROR: "Feature status: {feature.status}, expected consolidated"
65
+ ```
66
+
67
+ ### 5. Read All JSON Files
68
+
69
+ ```
70
+ collected_data = {
71
+ master: {
72
+ index: READ(index.json), // metadata, modules[], consolidation, handoff
73
+ cadrage: READ(cadrage.json) // context, stakeholders, scope, risks
74
+ },
75
+ modules: {}
76
+ }
77
+
78
+ FOR each module in master.index.modules[]:
79
+ moduleIndexPath = module.featureJsonPath || "{module.code}/business-analyse/v{version}/index.json"
80
+ moduleIndex = READ(moduleIndexPath)
81
+
82
+ collected_data.modules[module.code] = {
83
+ index: moduleIndex,
84
+ specification: moduleIndex.specification || {},
85
+ analysis: moduleIndex.analysis || {}
86
+ }
87
+ ```
88
+
89
+ ### 6. Display Collection Summary
90
+
91
+ ```
92
+ PRD verified: {module_count} modules
93
+ .ralph/prd-{module1}.json ({size} bytes)
94
+ .ralph/prd-{module2}.json ({size} bytes)
95
+
96
+ JSON collected:
97
+ Master: index.json + cadrage.json
98
+ Modules: {module_count} module index files
99
+ → Proceeding to data build...
100
+ ```
101
+
102
+ ---
103
+
104
+ ## VALIDATION
105
+
106
+ - BLOCK if index.json absent
107
+ - BLOCK if 0 modules found
108
+ - BLOCK if any PRD file missing
109
+ - BLOCK if feature not consolidated
110
+
111
+ ## NEXT STEP
112
+
113
+ Load: `steps/step-02-build-data.md`
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: step-02-build-data
3
+ description: Build FEATURE_DATA and EMBEDDED_ARTIFACTS objects from collected JSON data
4
+ model: opus
5
+ next_step: steps/step-03-render.md
6
+ ---
7
+
8
+ > **Reference files:** `references/data-mapping.md` | `references/data-build.md`
9
+
10
+ # Step 2: Build Data Objects
11
+
12
+ ## YOUR TASK
13
+
14
+ Build `FEATURE_DATA` and `EMBEDDED_ARTIFACTS` objects from `{collected_data}` collected in step-01.
15
+
16
+ ---
17
+
18
+ ## EXECUTION SEQUENCE
19
+
20
+ ### 1. Build FEATURE_DATA
21
+
22
+ Construct the complete FEATURE_DATA object following the exact mapping in `references/data-mapping.md`:
23
+
24
+ **metadata:**
25
+ ```javascript
26
+ metadata: {
27
+ applicationName: master.metadata.application,
28
+ applicationId: master.id,
29
+ version: master.version,
30
+ createdAt: master.metadata.createdAt,
31
+ lastModified: master.metadata.updatedAt,
32
+ analysisMode: master.metadata.analysisMode || "interactive"
33
+ }
34
+ ```
35
+
36
+ **cadrage.context** (lean format):
37
+ ```javascript
38
+ context: {
39
+ problem: master.cadrage.problem || "",
40
+ trigger: master.cadrage.trigger || "",
41
+ currentSituation: master.cadrage.asIs || "", // asIs → currentSituation
42
+ desiredSituation: master.cadrage.toBe || "", // toBe → desiredSituation
43
+ painPoints: (master.cadrage.stakeholders || []).flatMap(s => s.painPoints || []).join("\n"),
44
+ acceptanceCriteria: (master.cadrage.acceptanceCriteria || []).map(ac => ac.criterion).join("\n")
45
+ }
46
+ ```
47
+
48
+ **cadrage.stakeholders** (with frequency/access conversion):
49
+ ```javascript
50
+ stakeholders: master.cadrage.stakeholders.map(s => ({
51
+ role: s.role,
52
+ function: s.function || "",
53
+ tasks: s.tasks || [],
54
+ frequency: mapFrequency(s.frequency), // "Quotidien"→"daily", "Hebdomadaire"→"weekly", "Mensuel"→"monthly"
55
+ access: mapAccess(s.involvement), // "decision-maker"→"admin", "end-user"→"contributor", "observer"→"viewer"
56
+ frustrations: (s.painPoints || []).join("\n")
57
+ }))
58
+ ```
59
+
60
+ **cadrage.scope** (KEY CONVERSION — CRITICAL):
61
+ ```javascript
62
+ scope: {
63
+ vital: (master.cadrage.globalScope?.mustHave || []).map(item => ({ name: item, description: "" })),
64
+ important: (master.cadrage.globalScope?.shouldHave || []).map(item => ({ name: item, description: "" })),
65
+ optional: (master.cadrage.globalScope?.couldHave || []).map(item => ({ name: item, description: "" })),
66
+ excluded: (master.cadrage.globalScope?.outOfScope || []).map(item => ({ name: item, description: "" }))
67
+ }
68
+ ```
69
+
70
+ > Safety net: also check `master.cadrage.coverageMatrix` as alternative source for scope items.
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
+
82
+ **modules[]:**
83
+ ```javascript
84
+ modules: master.modules.map(m => ({
85
+ code: m.code,
86
+ name: m.name || m.code, // display name (MANDATORY)
87
+ description: m.description || "",
88
+ featureType: m.featureType || "data-centric",
89
+ priority: m.priority || "must",
90
+ entities: m.entities || [],
91
+ anticipatedSections: m.anticipatedSections || [],
92
+ dependencies: m.dependencies || [],
93
+ dependents: m.dependents || [],
94
+ estimatedComplexity: m.estimatedComplexity || "medium",
95
+ status: m.status || "handed-off"
96
+ }))
97
+ ```
98
+
99
+ **moduleSpecs{} — ONE entry per module (CRITICAL):**
100
+
101
+ For EACH module, read the module index.json and map:
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"),
109
+ alternative: (uc.alternativeScenarios || []).map(a => a.name + ": " + (a.steps || []).join(", ")).join("\n")
110
+ })),
111
+ businessRules: (moduleFeature.analysis?.businessRules || []).map(br => ({
112
+ name: br.name,
113
+ category: br.category,
114
+ statement: br.statement,
115
+ example: (br.examples || []).map(e => e.input + " → " + e.expected).join("; ")
116
+ })),
117
+ // ENTITY SAFETY NET: map fields[] → attributes[] if agent deviated
118
+ entities: (moduleFeature.analysis?.entities || []).map(ent => ({
119
+ name: ent.name,
120
+ description: ent.description || "",
121
+ attributes: (ent.attributes || []).length > 0
122
+ ? ent.attributes.map(a => ({ name: a.name, description: a.description || "" }))
123
+ : (ent.fields || []).map(f => ({ name: f.name, description: f.description || f.type || "" })),
124
+ relationships: (ent.relationships || []).map(r =>
125
+ typeof r === 'string' ? r : r.target + " (" + r.type + ") - " + (r.description || ""))
126
+ })),
127
+ permissions: buildPermissionKeys(moduleFeature),
128
+ apiEndpoints: moduleFeature.specification?.apiEndpoints || []
129
+ }
130
+ ```
131
+
132
+ > See `references/data-mapping.md` for `buildPermissionKeys()` implementation.
133
+
134
+ **consolidation:**
135
+ ```javascript
136
+ consolidation: {
137
+ interactions: (master.consolidation?.crossModuleInteractions || []).map(i => ({
138
+ from: i.fromModule,
139
+ to: i.toModule,
140
+ description: i.description || ""
141
+ })),
142
+ sharedEntities: master.consolidation?.sharedEntities || [],
143
+ e2eFlows: (master.consolidation?.e2eFlows || []).map(f => ({
144
+ name: f.name,
145
+ steps: (f.steps || []).map(s => ({ module: s.module, action: s.action })),
146
+ actors: (f.steps || []).map(s => s.permission).join(", ")
147
+ }))
148
+ }
149
+ ```
150
+
151
+ **handoff:**
152
+ ```javascript
153
+ handoff: {
154
+ complexity: master.handoff?.complexity,
155
+ implementationStrategy: master.handoff?.implementationStrategy,
156
+ moduleOrder: master.handoff?.moduleOrder,
157
+ filesToCreate: master.handoff?.filesToCreate,
158
+ brToCodeMapping: master.handoff?.brToCodeMapping,
159
+ apiEndpointSummary: master.handoff?.apiEndpointSummary
160
+ }
161
+ ```
162
+
163
+ ---
164
+
165
+ ### 2. Build EMBEDDED_ARTIFACTS
166
+
167
+ > **FIELD RENAME WARNING:** Module JSON uses `mockupFormat`/`mockup`. HTML reads `format`/`content`. You MUST rename.
168
+
169
+ **wireframes{} — per moduleCode:**
170
+ ```javascript
171
+ wireframes: {
172
+ [moduleCode]: (moduleFeature.specification.uiWireframes || moduleFeature.specification.wireframes || []).map(wf => ({
173
+ screen: wf.screen || wf.name || wf.title || wf.id || "",
174
+ section: wf.section || "",
175
+ format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
176
+ content: wf.mockup || wf.ascii || wf.content || "", // RENAME: mockup → content
177
+ svgContent: null,
178
+ description: wf.description || "",
179
+ elements: wf.elements || [],
180
+ actions: wf.actions || [],
181
+ componentMapping: Array.isArray(wf.componentMapping) ? wf.componentMapping
182
+ : typeof wf.componentMapping === 'object' && wf.componentMapping !== null
183
+ ? Object.entries(wf.componentMapping).map(([k, v]) => ({ wireframeElement: k, reactComponent: v }))
184
+ : [],
185
+ layout: typeof wf.layout === 'object' ? wf.layout : null,
186
+ permissionsRequired: wf.permissionsRequired || []
187
+ }))
188
+ }
189
+ ```
190
+
191
+ **e2eFlows[]:**
192
+ ```javascript
193
+ e2eFlows: (master.consolidation?.e2eFlows || []).map(flow => ({
194
+ name: flow.name,
195
+ diagram: flow.steps.map(s => s.action + "(" + s.module + ")").join(" ──→ "),
196
+ steps: flow.steps || [],
197
+ actors: [...new Set(flow.steps.map(s => s.permission?.split(".")[0]).filter(Boolean))].join(", "),
198
+ modules: [...new Set(flow.steps.map(s => s.module))].join(" → ")
199
+ }))
200
+ ```
201
+
202
+ **dependencyGraph:**
203
+ ```javascript
204
+ dependencyGraph: {
205
+ nodes: (master.modules || []).map(m => ({
206
+ id: m.code, label: m.code, type: m.featureType || "data-centric"
207
+ })),
208
+ edges: (master.dependencyGraph?.edges || []).map(e => ({
209
+ from: e.from, to: e.to, description: e.description || ""
210
+ }))
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ### 3. Generate SVG Wireframes (Parallel, Optional)
217
+
218
+ > This step is NEVER blocking — ASCII-only wireframes are acceptable.
219
+ > **Reference:** `business-analyse/references/wireframe-svg-style-guide.md` for full agent prompt template
220
+
221
+ 1. Collect all wireframes where `content` exists and `svgContent` is null
222
+ 2. Spawn parallel Task(sonnet) agents — ONE per wireframe
223
+ 3. Validate results: strip markdown fences, verify SVG syntax
224
+ 4. Inject valid SVGs into `EMBEDDED_ARTIFACTS.wireframes[moduleCode][index].svgContent`
225
+ 5. Display: `"SVG wireframe generation: {successCount}/{total} generated, {failCount} fallback (ASCII)"`
226
+
227
+ ---
228
+
229
+ ## VALIDATION
230
+
231
+ - FEATURE_DATA.moduleSpecs must have ONE entry per module
232
+ - cadrage.scope uses HTML keys (vital/important/optional/excluded)
233
+ - Wireframe fields use format/content (NOT mockupFormat/mockup)
234
+
235
+ ## NEXT STEP
236
+
237
+ Load: `steps/step-03-render.md`
@@ -0,0 +1,75 @@
1
+ ---
2
+ name: step-03-render
3
+ description: Inject data into HTML template and write final file
4
+ model: opus
5
+ next_step: steps/step-04-verify.md
6
+ ---
7
+
8
+ # Step 3: Render HTML
9
+
10
+ ## YOUR TASK
11
+
12
+ Inject FEATURE_DATA and EMBEDDED_ARTIFACTS into the HTML template and write the final file.
13
+
14
+ ---
15
+
16
+ ## EXECUTION SEQUENCE
17
+
18
+ ### 1. Locate Template
19
+
20
+ ```
21
+ 1. Primary: ~/.claude/skills/ba-generate-html/html/ba-interactive.html
22
+ 2. Fallback: templates/skills/ba-generate-html/html/ba-interactive.html (project CLI path)
23
+ 3. IF neither found → BLOCKING ERROR: "HTML template not found"
24
+ ```
25
+
26
+ ### 2. Read Template
27
+
28
+ ```
29
+ Read the full HTML template file.
30
+ Verify it contains placeholders: {{FEATURE_DATA}}, {{EMBEDDED_ARTIFACTS}}
31
+ ```
32
+
33
+ ### 3. Replace Placeholders
34
+
35
+ Serialize and inject:
36
+
37
+ ```
38
+ 1. {{FEATURE_DATA}} → JSON.stringify(FEATURE_DATA, null, 2)
39
+ 2. {{EMBEDDED_ARTIFACTS}} → JSON.stringify(EMBEDDED_ARTIFACTS, null, 2)
40
+ 3. {{APPLICATION_NAME}} → metadata.applicationName
41
+ 4. {{APPLICATION_ID}} → metadata.applicationId
42
+ 5. {{VERSION}} → metadata.version
43
+ 6. {{CREATED_AT}} → ISO timestamp (now)
44
+ ```
45
+
46
+ > Verify: grep for remaining `{{` to confirm ALL placeholders are replaced.
47
+
48
+ ### 4. Determine Output Path
49
+
50
+ ```
51
+ IF workflow.mode === "project" (multi-app):
52
+ outputPath = "docs/business-analyse/v{version}/ba-interactive.html"
53
+ ELSE (single-app):
54
+ outputPath = "docs/{app}/business-analyse/v{version}/ba-interactive.html"
55
+ ```
56
+
57
+ ### 5. Write File
58
+
59
+ ```
60
+ 1. Create parent directories if needed
61
+ 2. Write the final HTML file to outputPath
62
+ 3. Display: "HTML written: {outputPath} ({fileSize} bytes)"
63
+ ```
64
+
65
+ ---
66
+
67
+ ## VALIDATION
68
+
69
+ - Template was found and read
70
+ - All placeholders replaced (no remaining `{{`)
71
+ - File written successfully
72
+
73
+ ## NEXT STEP
74
+
75
+ Load: `steps/step-04-verify.md`