@atlashub/smartstack-cli 4.23.0 → 4.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/skills/ba-generate-html/html/ba-interactive.html +950 -1055
- package/templates/skills/ba-generate-html/html/src/scripts/01-data-init.js +1 -2
- package/templates/skills/ba-generate-html/html/src/scripts/02-navigation.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/03-render-cadrage.js +0 -39
- package/templates/skills/ba-generate-html/html/src/scripts/05-render-specs.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/07-render-handoff.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/08-editing.js +133 -135
- package/templates/skills/ba-generate-html/html/src/scripts/10-comments.js +199 -199
- package/templates/skills/ba-generate-html/html/src/scripts/11-review-panel.js +165 -166
- package/templates/skills/ba-generate-html/html/src/styles/05-modules.css +444 -454
- package/templates/skills/ba-generate-html/html/src/template.html +0 -49
- package/templates/skills/ba-generate-html/references/data-build.md +176 -182
- package/templates/skills/ba-generate-html/references/data-mapping.md +295 -301
- package/templates/skills/ba-generate-html/steps/step-01-collect.md +1 -1
- package/templates/skills/ba-generate-html/steps/step-02-build-data.md +0 -9
- package/templates/skills/derive-prd/SKILL.md +9 -9
- package/templates/skills/derive-prd/references/acceptance-criteria.md +166 -116
- package/templates/skills/derive-prd/references/entity-domain-mapping.md +5 -5
- package/templates/skills/derive-prd/references/handoff-file-templates.md +12 -12
- package/templates/skills/derive-prd/references/handoff-mappings.md +13 -14
- package/templates/skills/derive-prd/references/handoff-seeddata-generation.md +1 -1
- package/templates/skills/derive-prd/references/readiness-scoring.md +41 -50
- package/templates/skills/derive-prd/schemas/handoff-schema.json +2 -2
- package/templates/skills/derive-prd/steps/step-00-validate.md +73 -52
- package/templates/skills/derive-prd/steps/step-01-transform.md +86 -43
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-risks.html +0 -48
|
@@ -192,55 +192,6 @@
|
|
|
192
192
|
</div>
|
|
193
193
|
</div>
|
|
194
194
|
|
|
195
|
-
<!-- SECTION: Risques et hypotheses -->
|
|
196
|
-
<div class="section" id="cadrage-risks" style="display:none;" data-vibe-hide>
|
|
197
|
-
<h2 class="section-title">Risques et hypotheses</h2>
|
|
198
|
-
<p class="section-subtitle">Ce qui pourrait mal tourner et les certitudes non verifiees.</p>
|
|
199
|
-
|
|
200
|
-
<h3 style="color: var(--text-bright); font-size: 1rem; margin-bottom: 0.75rem;">Risques identifies</h3>
|
|
201
|
-
<div id="risksList"></div>
|
|
202
|
-
<button class="add-btn" onclick="toggleForm('addRiskForm')">+ Ajouter un risque</button>
|
|
203
|
-
|
|
204
|
-
<div class="inline-form" id="addRiskForm">
|
|
205
|
-
<div class="inline-form-title">Nouveau risque</div>
|
|
206
|
-
<div class="form-group">
|
|
207
|
-
<label class="form-label">Description du risque</label>
|
|
208
|
-
<input type="text" class="form-input" id="risk-desc" placeholder="Qu'est-ce qui pourrait mal tourner ?">
|
|
209
|
-
</div>
|
|
210
|
-
<div class="form-row">
|
|
211
|
-
<div class="form-group">
|
|
212
|
-
<label class="form-label">Probabilite</label>
|
|
213
|
-
<select class="form-select" id="risk-probability">
|
|
214
|
-
<option value="high">Forte</option>
|
|
215
|
-
<option value="medium">Moyenne</option>
|
|
216
|
-
<option value="low">Faible</option>
|
|
217
|
-
</select>
|
|
218
|
-
</div>
|
|
219
|
-
<div class="form-group">
|
|
220
|
-
<label class="form-label">Impact</label>
|
|
221
|
-
<select class="form-select" id="risk-impact">
|
|
222
|
-
<option value="high">Grave</option>
|
|
223
|
-
<option value="medium">Moyen</option>
|
|
224
|
-
<option value="low">Faible</option>
|
|
225
|
-
</select>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
<div class="form-group">
|
|
229
|
-
<label class="form-label">Mesure de prevention ou de reduction</label>
|
|
230
|
-
<textarea class="form-textarea" id="risk-mitigation" placeholder="Comment prevenir ou reduire ce risque ?"></textarea>
|
|
231
|
-
</div>
|
|
232
|
-
<div class="form-actions">
|
|
233
|
-
<button class="btn" onclick="toggleForm('addRiskForm')">Annuler</button>
|
|
234
|
-
<button class="btn btn-primary" onclick="addRisk()">Ajouter ce risque</button>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
|
|
238
|
-
<h3 style="color: var(--text-bright); font-size: 1rem; margin: 2rem 0 0.75rem;">Hypotheses a verifier</h3>
|
|
239
|
-
<div class="card">
|
|
240
|
-
<div class="editable" contenteditable="true" data-field="risks.assumptions" data-placeholder="Quelles hypotheses faites-vous sur ce projet sans les avoir verifiees ? (une par ligne)"></div>
|
|
241
|
-
</div>
|
|
242
|
-
</div>
|
|
243
|
-
|
|
244
195
|
<!-- SECTION: Criteres de reussite -->
|
|
245
196
|
<div class="section" id="cadrage-success" style="display:none;">
|
|
246
197
|
<h2 class="section-title">Criteres de reussite</h2>
|
|
@@ -1,182 +1,176 @@
|
|
|
1
|
-
# FEATURE_DATA & EMBEDDED_ARTIFACTS Build Reference
|
|
2
|
-
|
|
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
|
-
|
|
6
|
-
## FEATURE_DATA Object
|
|
7
|
-
|
|
8
|
-
```javascript
|
|
9
|
-
const FEATURE_DATA = {
|
|
10
|
-
metadata: {
|
|
11
|
-
applicationName: master.application_name,
|
|
12
|
-
applicationId: master.feature_id,
|
|
13
|
-
version: master.version,
|
|
14
|
-
createdAt: ISO_TIMESTAMP,
|
|
15
|
-
analysisMode: master.metadata.analysisMode || "interactive" // always "interactive" — analysis is always interactive
|
|
16
|
-
},
|
|
17
|
-
cadrage: {
|
|
18
|
-
// CONTEXT SECTION — merged from problem/asIs/toBe (lean cadrage)
|
|
19
|
-
context: {
|
|
20
|
-
problem: master.cadrage.problem || "", // flat string from index.json
|
|
21
|
-
trigger: master.cadrage.trigger || "", // flat string from index.json
|
|
22
|
-
currentSituation: master.cadrage.asIs || "", // flat string from index.json
|
|
23
|
-
desiredSituation: master.cadrage.toBe || "", // flat string from index.json
|
|
24
|
-
painPoints: (master.cadrage.stakeholders || []).flatMap(s => s.painPoints || []),
|
|
25
|
-
acceptanceCriteria: (master.cadrage.acceptanceCriteria || []).map(c => c.criterion)
|
|
26
|
-
},
|
|
27
|
-
scope: {
|
|
28
|
-
// CONVERT index.json keys to HTML keys:
|
|
29
|
-
// mustHave → vital, shouldHave → important, couldHave → optional, outOfScope → excluded
|
|
30
|
-
// CRITICAL: Preserve per-item `module` assignment from coverageMatrix (NOT modules[0])
|
|
31
|
-
vital: (master.cadrage.globalScope?.mustHave || master.cadrage.coverageMatrix?.filter(i => i.category === "mustHave") || [])
|
|
32
|
-
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
33
|
-
important: (master.cadrage.globalScope?.shouldHave || master.cadrage.coverageMatrix?.filter(i => i.category === "shouldHave") || [])
|
|
34
|
-
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
35
|
-
optional: (master.cadrage.globalScope?.couldHave || master.cadrage.coverageMatrix?.filter(i => i.category === "couldHave") || [])
|
|
36
|
-
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
37
|
-
excluded: (master.cadrage.globalScope?.outOfScope || master.cadrage.coverageMatrix?.filter(i => i.category === "outOfScope") || [])
|
|
38
|
-
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null })
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
1. Serialize FEATURE_DATA as JSON (2-space indent)
|
|
178
|
-
2. Serialize EMBEDDED_ARTIFACTS as JSON (2-space indent)
|
|
179
|
-
3. Replace `{{FEATURE_DATA}}` with serialized FEATURE_DATA
|
|
180
|
-
4. Replace `{{EMBEDDED_ARTIFACTS}}` with serialized EMBEDDED_ARTIFACTS
|
|
181
|
-
5. Replace `{{APPLICATION_NAME}}`, `{{APPLICATION_ID}}`, `{{VERSION}}`, `{{CREATED_AT}}`
|
|
182
|
-
6. Verify: grep for `{{` to confirm all placeholders replaced
|
|
1
|
+
# FEATURE_DATA & EMBEDDED_ARTIFACTS Build Reference
|
|
2
|
+
|
|
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
|
+
|
|
6
|
+
## FEATURE_DATA Object
|
|
7
|
+
|
|
8
|
+
```javascript
|
|
9
|
+
const FEATURE_DATA = {
|
|
10
|
+
metadata: {
|
|
11
|
+
applicationName: master.application_name,
|
|
12
|
+
applicationId: master.feature_id,
|
|
13
|
+
version: master.version,
|
|
14
|
+
createdAt: ISO_TIMESTAMP,
|
|
15
|
+
analysisMode: master.metadata.analysisMode || "interactive" // always "interactive" — analysis is always interactive
|
|
16
|
+
},
|
|
17
|
+
cadrage: {
|
|
18
|
+
// CONTEXT SECTION — merged from problem/asIs/toBe (lean cadrage)
|
|
19
|
+
context: {
|
|
20
|
+
problem: master.cadrage.problem || "", // flat string from index.json
|
|
21
|
+
trigger: master.cadrage.trigger || "", // flat string from index.json
|
|
22
|
+
currentSituation: master.cadrage.asIs || "", // flat string from index.json
|
|
23
|
+
desiredSituation: master.cadrage.toBe || "", // flat string from index.json
|
|
24
|
+
painPoints: (master.cadrage.stakeholders || []).flatMap(s => s.painPoints || []),
|
|
25
|
+
acceptanceCriteria: (master.cadrage.acceptanceCriteria || []).map(c => c.criterion)
|
|
26
|
+
},
|
|
27
|
+
scope: {
|
|
28
|
+
// CONVERT index.json keys to HTML keys:
|
|
29
|
+
// mustHave → vital, shouldHave → important, couldHave → optional, outOfScope → excluded
|
|
30
|
+
// CRITICAL: Preserve per-item `module` assignment from coverageMatrix (NOT modules[0])
|
|
31
|
+
vital: (master.cadrage.globalScope?.mustHave || master.cadrage.coverageMatrix?.filter(i => i.category === "mustHave") || [])
|
|
32
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
33
|
+
important: (master.cadrage.globalScope?.shouldHave || master.cadrage.coverageMatrix?.filter(i => i.category === "shouldHave") || [])
|
|
34
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
35
|
+
optional: (master.cadrage.globalScope?.couldHave || master.cadrage.coverageMatrix?.filter(i => i.category === "couldHave") || [])
|
|
36
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null }),
|
|
37
|
+
excluded: (master.cadrage.globalScope?.outOfScope || master.cadrage.coverageMatrix?.filter(i => i.category === "outOfScope") || [])
|
|
38
|
+
.map(item => typeof item === 'string' ? { name: item, description: "", module: null } : { name: item.item || item, description: item.notes || "", module: item.module || null })
|
|
39
|
+
},
|
|
40
|
+
stakeholders: (master.cadrage.stakeholders || []).map(s => ({
|
|
41
|
+
role: s.role,
|
|
42
|
+
function: s.function,
|
|
43
|
+
tasks: s.tasks || [],
|
|
44
|
+
frequency: s.frequency || "",
|
|
45
|
+
access: s.involvement || "",
|
|
46
|
+
frustrations: (s.painPoints || []).join("\n")
|
|
47
|
+
}))
|
|
48
|
+
},
|
|
49
|
+
modules: [
|
|
50
|
+
// FOR EACH module in master.modules[]:
|
|
51
|
+
{
|
|
52
|
+
code: module.code, // PascalCase key (e.g., "GestionTemps")
|
|
53
|
+
name: module.name || module.code, // Display name (e.g., "Gestion du temps") — MANDATORY
|
|
54
|
+
description: module.description || "",
|
|
55
|
+
featureType: module.featureType || "data-centric",
|
|
56
|
+
priority: module.priority || "must",
|
|
57
|
+
estimatedComplexity: module.estimatedComplexity || "medium",
|
|
58
|
+
entities: module.entities || [],
|
|
59
|
+
anticipatedSections: module.anticipatedSections || [],
|
|
60
|
+
dependencies: module.dependencies || [],
|
|
61
|
+
dependents: module.dependents || []
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
moduleSpecs: {
|
|
65
|
+
// CRITICAL: Must have ONE entry per module with ALL module data
|
|
66
|
+
"{moduleCode}": {
|
|
67
|
+
useCases: module.specification.useCases || [],
|
|
68
|
+
businessRules: module.analysis.businessRules || [],
|
|
69
|
+
// ENTITY SAFETY NET: map fields[] → attributes[] if agent deviated from canonical format
|
|
70
|
+
entities: (module.analysis.entities || []).map(ent => ({
|
|
71
|
+
name: ent.name,
|
|
72
|
+
description: ent.description || "",
|
|
73
|
+
attributes: (ent.attributes || []).length > 0
|
|
74
|
+
? ent.attributes.map(a => ({ name: a.name, type: a.type || "string", required: a.required || false, description: a.description || "" }))
|
|
75
|
+
: (ent.fields || []).map(f => ({ name: f.name, type: f.type || "string", required: f.required || false, description: f.description || "" })),
|
|
76
|
+
relationships: (ent.relationships || []).length > 0
|
|
77
|
+
? ent.relationships.map(r =>
|
|
78
|
+
typeof r === 'string' ? r : `${r.target} (${r.type}) - ${r.description || ""}`)
|
|
79
|
+
: (ent.fields || []).filter(f => f.foreignKey)
|
|
80
|
+
.map(f => `${f.foreignKey.table} (N:1) - ${f.description || f.name}`)
|
|
81
|
+
})),
|
|
82
|
+
permissions: module.specification.permissionMatrix?.permissions || [],
|
|
83
|
+
apiEndpoints: module.specification.apiEndpoints || []
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
consolidation: {
|
|
87
|
+
integrations: master.consolidation.crossModuleInteractions || [],
|
|
88
|
+
sharedEntities: master.consolidation.sharedEntities || [],
|
|
89
|
+
sequenceDiagrams: master.consolidation.e2eFlows || []
|
|
90
|
+
},
|
|
91
|
+
handoff: {
|
|
92
|
+
complexity: master.handoff.complexity,
|
|
93
|
+
implementationStrategy: master.handoff.implementationStrategy,
|
|
94
|
+
moduleOrder: master.handoff.moduleOrder,
|
|
95
|
+
filesToCreate: master.handoff.filesToCreate,
|
|
96
|
+
brToCodeMapping: master.handoff.brToCodeMapping,
|
|
97
|
+
apiEndpointSummary: master.handoff.apiEndpointSummary
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Build Process
|
|
103
|
+
|
|
104
|
+
1. Extract metadata from master index.json
|
|
105
|
+
2. Extract cadrage from master index.json (CONVERT scope keys)
|
|
106
|
+
3. Extract stakeholders from master.stakeholders
|
|
107
|
+
4. Iterate ALL modules and populate moduleSpecs (THIS IS CRITICAL — empty moduleSpecs = BUG)
|
|
108
|
+
5. For EACH module, extract: useCases, businessRules, entities, permissions, apiEndpoints
|
|
109
|
+
6. Extract consolidation data (integrations, shared entities, E2E flows)
|
|
110
|
+
7. Extract handoff section (complexity, strategy, module order, file counts)
|
|
111
|
+
|
|
112
|
+
## EMBEDDED_ARTIFACTS Object
|
|
113
|
+
|
|
114
|
+
> **CRITICAL:** The wireframes object is keyed by moduleCode (NOT a flat array).
|
|
115
|
+
> Field names MUST be renamed from module JSON files: `mockupFormat` → `format`, `mockup` → `content`.
|
|
116
|
+
> The HTML renderer reads `wf.format` and `wf.content` — using module JSON file names will produce EMPTY mockups.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
const EMBEDDED_ARTIFACTS = {
|
|
120
|
+
wireframes: {
|
|
121
|
+
// PER-MODULE keyed object (NOT a flat array)
|
|
122
|
+
// FOR EACH module: extract from specification.uiWireframes[] OR specification.wireframes[] (SAFETY NET)
|
|
123
|
+
// IMPORTANT: The agent may write wireframes under either key name — always check BOTH
|
|
124
|
+
// Read from module JSON files
|
|
125
|
+
[moduleCode]: (moduleFeature.specification.uiWireframes || moduleFeature.specification.wireframes || []).map(wf => ({
|
|
126
|
+
screen: wf.screen || wf.name || wf.title || wf.id || "", // SAFETY NET: fallback name/title/id → screen
|
|
127
|
+
section: wf.section || "", // e.g. "list"
|
|
128
|
+
format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
|
|
129
|
+
content: wf.mockup || wf.ascii || wf.content || "", // SAFETY NET: mockup/ascii/content → content
|
|
130
|
+
svgContent: null, // Populated by SVG generation step (see wireframe-svg-style-guide.md)
|
|
131
|
+
description: wf.description || "",
|
|
132
|
+
elements: wf.elements || [], // [{ id, type, label }] or ["DataGrid", ...]
|
|
133
|
+
actions: wf.actions || [], // [{ trigger, action }] or ["filter", ...]
|
|
134
|
+
// SAFETY NET: convert object → array format if agent used { "Header": "PageHeader" } instead of [{ wireframeElement, reactComponent }]
|
|
135
|
+
componentMapping: Array.isArray(wf.componentMapping) ? wf.componentMapping
|
|
136
|
+
: typeof wf.componentMapping === 'object' && wf.componentMapping !== null
|
|
137
|
+
? Object.entries(wf.componentMapping).map(([k, v]) => ({ wireframeElement: k, reactComponent: v }))
|
|
138
|
+
: [],
|
|
139
|
+
layout: typeof wf.layout === 'object' ? wf.layout : null, // SAFETY NET: ignore string layout ("grid")
|
|
140
|
+
permissionsRequired: wf.permissionsRequired || []
|
|
141
|
+
}))
|
|
142
|
+
},
|
|
143
|
+
e2eFlows: (master.consolidation?.e2eFlows || []).map(flow => ({
|
|
144
|
+
name: flow.name,
|
|
145
|
+
diagram: flow.steps.map(s => `${s.action}(${s.module})`).join(" ──→ "),
|
|
146
|
+
steps: flow.steps || [],
|
|
147
|
+
actors: [...new Set(flow.steps.map(s => s.permission?.split(".")[0]).filter(Boolean))].join(", "),
|
|
148
|
+
modules: [...new Set(flow.steps.map(s => s.module))].join(" → ")
|
|
149
|
+
})),
|
|
150
|
+
dependencyGraph: {
|
|
151
|
+
nodes: (master.modules || []).map(m => ({
|
|
152
|
+
id: m.code, label: m.code, type: m.featureType || "data-centric"
|
|
153
|
+
})),
|
|
154
|
+
edges: (master.dependencyGraph?.edges || []).map(e => ({
|
|
155
|
+
from: e.from, to: e.to, description: e.description || ""
|
|
156
|
+
}))
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Artifact Gathering
|
|
162
|
+
|
|
163
|
+
1. For EACH module: read `specification.uiWireframes[]` OR `specification.wireframes[]` (check BOTH keys — agent may use either), **rename fields** (`mockupFormat`→`format`, `mockup`/`ascii`/`content`→`content`, `screen`/`name`/`title`→`screen`), store under `wireframes[moduleCode]`
|
|
164
|
+
2. Read master's `consolidation.e2eFlows[]` and build e2eFlows array with diagram generation
|
|
165
|
+
3. Read master's `dependencyGraph` and build nodes/edges
|
|
166
|
+
4. Serialize as JSON with 2-space indentation
|
|
167
|
+
5. **SVG Wireframe Enrichment** (after wireframe extraction): For EACH wireframe with `content` (ASCII) and `svgContent === null`, generate SVG using parallel Task(sonnet) agents. See [wireframe-svg-style-guide.md](wireframe-svg-style-guide.md) for the complete prompt template and orchestration process. If generation fails for any wireframe → leave `svgContent` as null (graceful fallback to ASCII).
|
|
168
|
+
|
|
169
|
+
## Placeholder Replacement
|
|
170
|
+
|
|
171
|
+
1. Serialize FEATURE_DATA as JSON (2-space indent)
|
|
172
|
+
2. Serialize EMBEDDED_ARTIFACTS as JSON (2-space indent)
|
|
173
|
+
3. Replace `{{FEATURE_DATA}}` with serialized FEATURE_DATA
|
|
174
|
+
4. Replace `{{EMBEDDED_ARTIFACTS}}` with serialized EMBEDDED_ARTIFACTS
|
|
175
|
+
5. Replace `{{APPLICATION_NAME}}`, `{{APPLICATION_ID}}`, `{{VERSION}}`, `{{CREATED_AT}}`
|
|
176
|
+
6. Verify: grep for `{{` to confirm all placeholders replaced
|