@atlashub/smartstack-cli 4.74.0 → 4.76.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/dist/index.js +152 -31
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +14 -3
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-reader.md +17 -15
- package/templates/agents/ba-writer.md +49 -51
- package/templates/skills/apex/SKILL.md +2 -2
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/backend-checks.sh +21 -7
- package/templates/skills/apex/references/checks/frontend-checks.sh +26 -0
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +47 -10
- package/templates/skills/apex/references/checks/seed-checks.sh +47 -7
- package/templates/skills/apex/references/core-seed-data.md +20 -18
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/apex/references/post-checks.md +23 -3
- package/templates/skills/apex/references/smartstack-api.md +4 -4
- package/templates/skills/apex/references/smartstack-frontend.md +54 -8
- package/templates/skills/apex/references/smartstack-layers.md +6 -6
- package/templates/skills/apex/steps/step-00-init.md +75 -1
- package/templates/skills/apex/steps/step-03-execute.md +16 -4
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +65 -6
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +50 -5
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +226 -4
- package/templates/skills/apex/steps/step-04-examine.md +163 -0
- package/templates/skills/apex-verify/SKILL.md +110 -0
- package/templates/skills/apex-verify/references/audit-rules.md +50 -0
- package/templates/skills/apex-verify/steps/step-00-init.md +119 -0
- package/templates/skills/apex-verify/steps/step-01-nav-audit.md +92 -0
- package/templates/skills/apex-verify/steps/step-02-crud-audit.md +127 -0
- package/templates/skills/apex-verify/steps/step-03-perm-audit.md +119 -0
- package/templates/skills/apex-verify/steps/step-04-route-audit.md +98 -0
- package/templates/skills/apex-verify/steps/step-05-report.md +110 -0
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/application/templates-frontend.md +2 -2
- package/templates/skills/business-analyse/SKILL.md +17 -3
- package/templates/skills/business-analyse/_shared.md +64 -0
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +34 -26
- package/templates/skills/business-analyse/questionnaire/01-context.md +13 -9
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +20 -27
- package/templates/skills/business-analyse/questionnaire.md +86 -9
- package/templates/skills/business-analyse/references/03-json-schemas.md +221 -0
- package/templates/skills/business-analyse/references/03-post-check-validation.md +208 -0
- package/templates/skills/business-analyse/references/03-smartstack-entity-guards.md +32 -0
- package/templates/skills/business-analyse/references/04-cross-module-validation.md +95 -0
- package/templates/skills/business-analyse/references/04-file-allocation.md +162 -0
- package/templates/skills/business-analyse/references/04-naming-audit-checks.md +174 -0
- package/templates/skills/business-analyse/references/04-semantic-validation-matrix.md +118 -0
- package/templates/skills/business-analyse/references/canonical-json-formats.md +7 -3
- package/templates/skills/business-analyse/references/domain-research-playbook.md +234 -0
- package/templates/skills/business-analyse/references/entity-sourcing-presentation.md +166 -0
- package/templates/skills/business-analyse/references/init-resume-logic.md +70 -0
- package/templates/skills/business-analyse/references/module-completeness-challenge.md +174 -0
- package/templates/skills/business-analyse/references/multi-app-detection.md +149 -0
- package/templates/skills/business-analyse/references/portal-classification.md +52 -0
- package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
- package/templates/skills/business-analyse/references/validation-checklist.md +35 -6
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +50 -6
- package/templates/skills/business-analyse/steps/step-00-init.md +22 -190
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +365 -269
- package/templates/skills/business-analyse/steps/step-02-structure.md +98 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +810 -229
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +509 -278
- package/templates/skills/business-analyse-design/SKILL.md +10 -0
- package/templates/skills/business-analyse-design/references/screens-post-check.md +221 -0
- package/templates/skills/business-analyse-design/references/screens-type-mapping.md +138 -0
- package/templates/skills/business-analyse-design/references/smartcomponents-templates.md +225 -0
- package/templates/skills/{business-analyse → business-analyse-design}/references/spec-auto-inference.md +117 -117
- package/templates/skills/business-analyse-design/steps/step-01-screens.md +36 -162
- package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +8 -7
- package/templates/skills/business-analyse-design/steps/step-03-navigation.md +89 -42
- package/templates/skills/business-analyse-develop/references/compact-loop.md +9 -0
- package/templates/skills/business-analyse-develop/references/handoff-quality-gate.md +132 -0
- package/templates/skills/business-analyse-develop/references/prd-v3-transformation.md +326 -0
- package/templates/skills/business-analyse-develop/references/report-reconciliation.md +140 -0
- package/templates/skills/business-analyse-develop/references/report-template.md +142 -0
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +5 -177
- package/templates/skills/business-analyse-develop/steps/step-02-execute.md +17 -4
- package/templates/skills/business-analyse-develop/steps/step-03-commit.md +6 -2
- package/templates/skills/business-analyse-develop/steps/step-04-check.md +6 -0
- package/templates/skills/business-analyse-develop/steps/step-05-report.md +3 -269
- package/templates/skills/business-analyse-handoff/SKILL.md +10 -0
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +211 -0
- package/templates/skills/business-analyse-handoff/references/context-isolation-pattern.md +47 -0
- package/templates/skills/business-analyse-handoff/references/handoff-file-inventory.md +49 -0
- package/templates/skills/business-analyse-handoff/references/handoff-global-validation.md +142 -0
- package/templates/skills/business-analyse-handoff/references/prd-validation-checks.md +125 -0
- package/templates/skills/business-analyse-handoff/references/project-index-update.md +98 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +9 -160
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +10 -99
- package/templates/skills/business-analyse-html/SKILL.md +10 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +504 -97
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +79 -2
- package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +6 -46
- package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +80 -11
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-consolidation.js +2 -2
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +94 -36
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +162 -0
- package/templates/skills/business-analyse-html/html/src/styles/10-diagrams.css +73 -0
- package/templates/skills/business-analyse-html/html/src/template.html +2 -0
- package/templates/skills/business-analyse-html/references/02-embedded-artifacts-building.md +144 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +143 -0
- package/templates/skills/business-analyse-html/references/02-mapping-tables.md +442 -0
- package/templates/skills/business-analyse-html/references/02-normalization-helpers.md +139 -0
- package/templates/skills/business-analyse-html/references/02-screen-format-detection.md +283 -0
- package/templates/skills/business-analyse-html/references/02-self-check-validation.md +199 -0
- package/templates/skills/business-analyse-html/references/data-build.md +24 -1
- package/templates/skills/business-analyse-html/references/data-mapping.md +119 -17
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +18 -555
- package/templates/skills/business-analyse-html/steps/step-04-verify.md +92 -3
- package/templates/skills/business-analyse-quick/SKILL.md +807 -0
- package/templates/skills/{sketch → business-analyse-quick}/references/domain-heuristics.md +59 -3
- package/templates/skills/business-analyse-quick/references/prd-schema.md +268 -0
- package/templates/skills/business-analyse-review/SKILL.md +10 -0
- package/templates/skills/business-analyse-review/references/review-data-mapping.md +6 -0
- package/templates/skills/business-analyse-status/SKILL.md +8 -0
- package/templates/skills/dev-start/SKILL.md +143 -307
- package/templates/skills/efcore/SKILL.md +13 -0
- package/templates/skills/sketch/SKILL.md +15 -153
- package/templates/skills/ui-components/SKILL.md +1 -1
- package/templates/skills/ui-components/patterns/data-table.md +1 -1
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 02-mapping-tables
|
|
3
|
+
description: Complete mapping tables for FEATURE_DATA object fields from master and collected_data sources
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Mapping Tables
|
|
7
|
+
|
|
8
|
+
This reference documents all field mappings used when constructing the FEATURE_DATA object from collected BA data sources.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Metadata Mapping
|
|
13
|
+
|
|
14
|
+
**Source:** `master.metadata` and root `master` fields
|
|
15
|
+
|
|
16
|
+
**Mapping:**
|
|
17
|
+
```javascript
|
|
18
|
+
metadata: {
|
|
19
|
+
applicationName: master.metadata.application, // application name
|
|
20
|
+
applicationId: master.id, // application unique ID
|
|
21
|
+
version: master.version, // version string
|
|
22
|
+
createdAt: master.metadata.createdAt, // ISO timestamp
|
|
23
|
+
lastModified: master.metadata.updatedAt, // ISO timestamp
|
|
24
|
+
analysisMode: master.metadata.analysisMode || "interactive" // default: interactive
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Cadrage Context Mapping
|
|
31
|
+
|
|
32
|
+
**Source:** `master.cadrage` object
|
|
33
|
+
|
|
34
|
+
**Mapping:**
|
|
35
|
+
```javascript
|
|
36
|
+
cadrage.context: {
|
|
37
|
+
problem: master.cadrage.problem || "", // problem statement
|
|
38
|
+
trigger: master.cadrage.trigger || "", // what triggered the project
|
|
39
|
+
currentSituation: master.cadrage.asIs || "", // current state (AS-IS)
|
|
40
|
+
desiredSituation: master.cadrage.toBe || "", // desired state (TO-BE)
|
|
41
|
+
painPoints: (master.cadrage.stakeholders || []) // extracted from stakeholders
|
|
42
|
+
.flatMap(s => s.painPoints || [])
|
|
43
|
+
.join("\n"),
|
|
44
|
+
acceptanceCriteria: (master.cadrage.acceptanceCriteria || []) // AC list
|
|
45
|
+
.map(ac => ac.criterion)
|
|
46
|
+
.join("\n")
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Validation:** Warn if `problem` or `currentSituation/desiredSituation` are empty — these are MANDATORY for the HTML viewer.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Cadrage Stakeholders Mapping
|
|
55
|
+
|
|
56
|
+
**Source:** `master.cadrage.stakeholders[]`
|
|
57
|
+
|
|
58
|
+
**Mapping:**
|
|
59
|
+
```javascript
|
|
60
|
+
cadrage.stakeholders: master.cadrage.stakeholders.map(s => ({
|
|
61
|
+
role: s.role, // role name
|
|
62
|
+
function: s.function || "", // job function
|
|
63
|
+
tasks: Array.isArray(s.tasks)
|
|
64
|
+
? s.tasks // already an array
|
|
65
|
+
: typeof s.tasks === 'string'
|
|
66
|
+
? s.tasks.split(',').map(t => t.trim()).filter(Boolean) // parse CSV string
|
|
67
|
+
: [],
|
|
68
|
+
frequency: mapFrequency(s.frequency), // frequency conversion
|
|
69
|
+
access: mapAccess(s.involvement), // involvement → access level conversion
|
|
70
|
+
frustrations: (s.painPoints || []).join("\n") // stakeholder pain points
|
|
71
|
+
}))
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Helper: `mapFrequency(freq)`**
|
|
75
|
+
|
|
76
|
+
Maps user frequency to standardized values:
|
|
77
|
+
```
|
|
78
|
+
"Quotidien" | "Journalière" | "daily" → "daily"
|
|
79
|
+
"Hebdomadaire" | "weekly" → "weekly"
|
|
80
|
+
"Mensuel" | "monthly" → "monthly"
|
|
81
|
+
"Trimestriel" | "quarterly" → "quarterly"
|
|
82
|
+
"Annuel" | "yearly" → "yearly"
|
|
83
|
+
default → freq (as-is)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Helper: `mapAccess(involvement)`**
|
|
87
|
+
|
|
88
|
+
Maps user involvement/role to access level:
|
|
89
|
+
```
|
|
90
|
+
"decision-maker" | "approver" | "responsable" → "admin"
|
|
91
|
+
"end-user" | "user" | "utilisateur" → "contributor"
|
|
92
|
+
"observer" | "lecteur" | "stakeholder" → "viewer"
|
|
93
|
+
default → "viewer"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Cadrage Scope Mapping
|
|
99
|
+
|
|
100
|
+
**Source:** `master.cadrage.globalScope` and fallback `master.cadrage.coverageMatrix`
|
|
101
|
+
|
|
102
|
+
**Key Challenge:** Scope items can be strings, simple objects `{name, description}`, or complex objects `{feature, priority, module, app}`.
|
|
103
|
+
|
|
104
|
+
**Normalization Helper:**
|
|
105
|
+
```javascript
|
|
106
|
+
function normalizeScopeItem(item) {
|
|
107
|
+
// Case 1: string value
|
|
108
|
+
if (typeof item === 'string') return { name: item, description: "" };
|
|
109
|
+
|
|
110
|
+
// Case 2: already in {name, description} format
|
|
111
|
+
if (item.name) return { name: item.name, description: item.description || "" };
|
|
112
|
+
|
|
113
|
+
// Case 3: {feature, priority, module, app} format (from globalScope)
|
|
114
|
+
var name = item.feature || item.label || item.title || JSON.stringify(item);
|
|
115
|
+
var parts = [];
|
|
116
|
+
if (item.priority) parts.push(item.priority.toUpperCase()); // priority → upper
|
|
117
|
+
if (item.module) parts.push("Module: " + item.module); // module reference
|
|
118
|
+
if (item.app) parts.push("App: " + item.app); // app reference
|
|
119
|
+
return { name: name, description: parts.join(" — ") }; // parts → description
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Mapping:**
|
|
124
|
+
```javascript
|
|
125
|
+
cadrage.scope: {
|
|
126
|
+
inscope: (master.cadrage.globalScope?.inScope || [])
|
|
127
|
+
.map(normalizeScopeItem),
|
|
128
|
+
outofscope: (master.cadrage.globalScope?.outOfScope || [])
|
|
129
|
+
.map(normalizeScopeItem)
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Fallback:** If `globalScope` is missing/empty but `coverageMatrix` exists, build `inscope` from coverageMatrix entries.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Cadrage Criteria Mapping
|
|
138
|
+
|
|
139
|
+
**Source:** `master.cadrage.acceptanceCriteria[]` with fallback to `collected_data.master.validation.acceptanceCriteria[]`
|
|
140
|
+
|
|
141
|
+
**Primary Mapping:**
|
|
142
|
+
```javascript
|
|
143
|
+
let criteria = (master.cadrage.acceptanceCriteria || []).map(ac => ({
|
|
144
|
+
text: ac.criterion || ac.text || "",
|
|
145
|
+
validated: false
|
|
146
|
+
}));
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Fallback (if criteria is empty):**
|
|
150
|
+
```javascript
|
|
151
|
+
if (criteria.length === 0 && collected_data.master.validation) {
|
|
152
|
+
const valAC = collected_data.master.validation.acceptanceCriteria || [];
|
|
153
|
+
criteria = valAC.map(ac => ({
|
|
154
|
+
text: (ac.module ? '[' + ac.module + '] ' : '') + (ac.criteria || ac.criterion || ac.text || ""),
|
|
155
|
+
validated: false,
|
|
156
|
+
module: ac.module || null,
|
|
157
|
+
type: ac.type || null
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Modules and Applications Mapping
|
|
165
|
+
|
|
166
|
+
**Source:** `master.modules[]` and `master.applications[]` (with fallback to `collected_data.navigation?.applications`)
|
|
167
|
+
|
|
168
|
+
**Applications Mapping:**
|
|
169
|
+
```javascript
|
|
170
|
+
applications: (collected_data.navigation?.applications || master.applications || []).map(app => ({
|
|
171
|
+
code: app.code, // unique application code
|
|
172
|
+
name: app.name || app.code, // display name (fallback to code)
|
|
173
|
+
icon: app.icon || "" // icon reference
|
|
174
|
+
}))
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Modules Mapping:**
|
|
178
|
+
```javascript
|
|
179
|
+
modules: master.modules.map(m => ({
|
|
180
|
+
code: m.code, // unique module code
|
|
181
|
+
name: m.name || m.code, // display name (MANDATORY)
|
|
182
|
+
applicationCode: m.applicationCode || "", // multi-app grouping
|
|
183
|
+
description: m.description || "",
|
|
184
|
+
featureType: m.featureType || "data-centric", // component type
|
|
185
|
+
entities: m.entities || [], // entity references
|
|
186
|
+
anticipatedSections: (m.anticipatedSections || []).map(s =>
|
|
187
|
+
typeof s === 'string'
|
|
188
|
+
? { code: s, name: s, description: "", resources: [] }
|
|
189
|
+
: {
|
|
190
|
+
code: s.code || s.name || "",
|
|
191
|
+
name: s.label || s.name || s.code || "",
|
|
192
|
+
description: s.description || "",
|
|
193
|
+
resources: s.resources || [],
|
|
194
|
+
route: s.route || "",
|
|
195
|
+
permission: s.permission || ""
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
dependencies: m.dependencies || [], // module dependencies
|
|
199
|
+
dependents: m.dependents || [], // dependent modules
|
|
200
|
+
estimatedComplexity: m.estimatedComplexity || "medium",
|
|
201
|
+
status: m.status || "handed-off" // handoff status
|
|
202
|
+
}))
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Dependencies Mapping (Top-Level)
|
|
208
|
+
|
|
209
|
+
**Source:** `master.consolidation?.crossModuleInteractions` or `master.dependencyGraph?.edges`
|
|
210
|
+
|
|
211
|
+
**CRITICAL:** This array is used by HTML sidebar navigation, module rendering, consolidation views, handoff summary, and export. If missing, the HTML page crashes with a TypeError.
|
|
212
|
+
|
|
213
|
+
**Mapping:**
|
|
214
|
+
```javascript
|
|
215
|
+
dependencies: (master.consolidation?.crossModuleInteractions || master.dependencyGraph?.edges || []).map(i => ({
|
|
216
|
+
from: i.fromModule || i.from || "",
|
|
217
|
+
to: i.toModule || i.to || "",
|
|
218
|
+
description: i.description || ""
|
|
219
|
+
}))
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Always include**, even if empty: `dependencies: []`
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Consolidation Mapping
|
|
227
|
+
|
|
228
|
+
**Source:** `master.consolidation` object
|
|
229
|
+
|
|
230
|
+
**Mapping:**
|
|
231
|
+
```javascript
|
|
232
|
+
consolidation: {
|
|
233
|
+
interactions: (master.consolidation?.crossModuleInteractions || []).map(i => ({
|
|
234
|
+
from: i.fromModule,
|
|
235
|
+
to: i.toModule,
|
|
236
|
+
description: i.description || ""
|
|
237
|
+
})),
|
|
238
|
+
sharedEntities: master.consolidation?.sharedEntities || [],
|
|
239
|
+
e2eFlows: (master.consolidation?.e2eFlows || []).map(f => ({
|
|
240
|
+
name: f.name,
|
|
241
|
+
steps: (f.steps || []).map(s => ({ module: s.module, action: s.action })),
|
|
242
|
+
actors: (f.steps || []).map(s => s.permission).join(", ")
|
|
243
|
+
}))
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Handoff Mapping
|
|
250
|
+
|
|
251
|
+
**Source:** `master.handoff` object
|
|
252
|
+
|
|
253
|
+
**Mapping:**
|
|
254
|
+
```javascript
|
|
255
|
+
handoff: {
|
|
256
|
+
complexity: master.handoff?.complexity,
|
|
257
|
+
implementationStrategy: master.handoff?.implementationStrategy,
|
|
258
|
+
moduleOrder: master.handoff?.moduleOrder,
|
|
259
|
+
filesToCreate: master.handoff?.filesToCreate,
|
|
260
|
+
brToCodeMapping: master.handoff?.brToCodeMapping,
|
|
261
|
+
apiEndpointSummary: master.handoff?.apiEndpointSummary
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Module Specifications: useCases Mapping
|
|
268
|
+
|
|
269
|
+
**Source:** `collected_data.modules[moduleCode].usecases`
|
|
270
|
+
|
|
271
|
+
**Normalization Notes:**
|
|
272
|
+
- Field may be `useCases` (camelCase) or `usecases` (lowercase)
|
|
273
|
+
- Steps may be strings[] or objects[] with `{step, action}` structure
|
|
274
|
+
- Alternative flows may be `alternativeScenarios` or `alternativeFlows`
|
|
275
|
+
|
|
276
|
+
**Mapping:**
|
|
277
|
+
```javascript
|
|
278
|
+
const rawUCs = mod.usecases?.useCases || mod.usecases?.usecases || [];
|
|
279
|
+
|
|
280
|
+
useCases: rawUCs.map(uc => ({
|
|
281
|
+
name: uc.name || uc.title || uc.id || "",
|
|
282
|
+
sectionCode: uc.sectionCode || "",
|
|
283
|
+
actor: uc.primaryActor || uc.actor || "",
|
|
284
|
+
steps: (uc.mainScenario || uc.steps || []).map(s =>
|
|
285
|
+
typeof s === 'string' ? s : (s.action || s.description || "")
|
|
286
|
+
).join("\n"),
|
|
287
|
+
alternative: (uc.alternativeScenarios || uc.alternativeFlows || []).map(a =>
|
|
288
|
+
(a.name || a.trigger || "") + ": " + (a.steps || a.actions || []).map(s =>
|
|
289
|
+
typeof s === 'string' ? s : (s.action || s.description || "")
|
|
290
|
+
).join(", ")
|
|
291
|
+
).join("\n")
|
|
292
|
+
}))
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Module Specifications: businessRules Mapping
|
|
298
|
+
|
|
299
|
+
**Source:** `collected_data.modules[moduleCode].rules`
|
|
300
|
+
|
|
301
|
+
**Normalization Notes:**
|
|
302
|
+
- Field may be `rules` or `businessRules`
|
|
303
|
+
|
|
304
|
+
**Mapping:**
|
|
305
|
+
```javascript
|
|
306
|
+
const rawBRs = mod.rules?.rules || mod.rules?.businessRules || [];
|
|
307
|
+
|
|
308
|
+
businessRules: rawBRs.map(br => ({
|
|
309
|
+
name: br.name || br.id || "",
|
|
310
|
+
sectionCode: br.sectionCode || "",
|
|
311
|
+
category: br.category || "",
|
|
312
|
+
statement: br.statement || br.description || "",
|
|
313
|
+
example: (br.examples || []).map(e =>
|
|
314
|
+
typeof e === 'string' ? e : ((e.input || "") + " → " + (e.expected || ""))
|
|
315
|
+
).join("; ")
|
|
316
|
+
}))
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Module Specifications: Entities Mapping
|
|
322
|
+
|
|
323
|
+
**Source:** `collected_data.modules[moduleCode].entities`
|
|
324
|
+
|
|
325
|
+
**Normalization Notes:**
|
|
326
|
+
- Attributes may be `attributes[]` or `fields[]` (fallback if attributes missing)
|
|
327
|
+
|
|
328
|
+
**Mapping:**
|
|
329
|
+
```javascript
|
|
330
|
+
entities: (mod.entities?.entities || []).map(ent => ({
|
|
331
|
+
name: ent.name,
|
|
332
|
+
description: ent.description || "",
|
|
333
|
+
attributes: (ent.attributes || []).length > 0
|
|
334
|
+
? ent.attributes.map(a => ({
|
|
335
|
+
name: a.name,
|
|
336
|
+
type: a.type || "string",
|
|
337
|
+
required: a.required || false,
|
|
338
|
+
description: a.description || ""
|
|
339
|
+
}))
|
|
340
|
+
: (ent.fields || []).map(f => ({ // fallback to fields[]
|
|
341
|
+
name: f.name,
|
|
342
|
+
type: f.type || "string",
|
|
343
|
+
required: f.required || false,
|
|
344
|
+
description: f.description || ""
|
|
345
|
+
})),
|
|
346
|
+
relationships: (ent.relationships || []).map(r =>
|
|
347
|
+
typeof r === 'string' ? r : r.target + " (" + r.type + ") - " + (r.description || "")
|
|
348
|
+
)
|
|
349
|
+
}))
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Wireframes Mapping
|
|
355
|
+
|
|
356
|
+
**Source:** `collected_data.modules[moduleCode].screens` with wireframe data
|
|
357
|
+
|
|
358
|
+
**Field Rename CRITICAL:** Module JSON uses `mockupFormat`/`mockup`. HTML reads `format`/`content`.
|
|
359
|
+
|
|
360
|
+
**Mapping:**
|
|
361
|
+
```javascript
|
|
362
|
+
wireframes: {
|
|
363
|
+
[moduleCode]: rawWireframes.map(wf => ({
|
|
364
|
+
screen: wf.screen || wf.name || wf.title || wf.id || "",
|
|
365
|
+
section: wf.section || "",
|
|
366
|
+
format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
|
|
367
|
+
content: wf.mockup || wf.ascii || wf.content || "", // RENAME: mockup → content
|
|
368
|
+
svgContent: null, // populated later if SVG generated
|
|
369
|
+
description: wf.description || "",
|
|
370
|
+
elements: wf.elements || [],
|
|
371
|
+
actions: wf.actions || [],
|
|
372
|
+
componentMapping: Array.isArray(wf.componentMapping)
|
|
373
|
+
? wf.componentMapping.map(entry => ...) // see below
|
|
374
|
+
: typeof wf.componentMapping === 'object' && wf.componentMapping !== null
|
|
375
|
+
? Object.entries(wf.componentMapping).map(([k, v]) => ({ wireframeElement: k, reactComponent: v }))
|
|
376
|
+
: [],
|
|
377
|
+
layout: typeof wf.layout === 'object' ? wf.layout : null,
|
|
378
|
+
permissionsRequired: wf.permissionsRequired || []
|
|
379
|
+
}))
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**componentMapping Normalization:**
|
|
384
|
+
|
|
385
|
+
Handles three formats:
|
|
386
|
+
```javascript
|
|
387
|
+
// Format 1: Array of canonical entries {wireframeElement, reactComponent}
|
|
388
|
+
[{wireframeElement: "Button1", reactComponent: "Button"}]
|
|
389
|
+
|
|
390
|
+
// Format 2: Shorthand [{key: value}]
|
|
391
|
+
[{"Button1": "Button"}] → {wireframeElement: "Button1", reactComponent: "Button"}
|
|
392
|
+
|
|
393
|
+
// Format 3: Object {key: value}
|
|
394
|
+
{"Button1": "Button"} → [{wireframeElement: "Button1", reactComponent: "Button"}]
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## E2E Flows Mapping
|
|
400
|
+
|
|
401
|
+
**Source:** `master.consolidation?.e2eFlows`
|
|
402
|
+
|
|
403
|
+
**Mapping:**
|
|
404
|
+
```javascript
|
|
405
|
+
e2eFlows: (master.consolidation?.e2eFlows || []).map(flow => ({
|
|
406
|
+
name: flow.name,
|
|
407
|
+
diagram: flow.steps.map(s => s.action + "(" + s.module + ")").join(" ──→ "),
|
|
408
|
+
steps: flow.steps || [],
|
|
409
|
+
actors: [...new Set(flow.steps.map(s => s.permission?.split(".")[0]).filter(Boolean))].join(", "),
|
|
410
|
+
modules: [...new Set(flow.steps.map(s => s.module))].join(" → ")
|
|
411
|
+
}))
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## Dependency Graph Mapping
|
|
417
|
+
|
|
418
|
+
**Source:** `master.modules[]` and `master.dependencyGraph?.edges`
|
|
419
|
+
|
|
420
|
+
**Mapping:**
|
|
421
|
+
```javascript
|
|
422
|
+
dependencyGraph: {
|
|
423
|
+
nodes: (master.modules || []).map(m => ({
|
|
424
|
+
id: m.code,
|
|
425
|
+
label: m.code,
|
|
426
|
+
type: m.featureType || "data-centric"
|
|
427
|
+
})),
|
|
428
|
+
edges: (master.dependencyGraph?.edges || []).map(e => ({
|
|
429
|
+
from: e.from,
|
|
430
|
+
to: e.to,
|
|
431
|
+
description: e.description || ""
|
|
432
|
+
}))
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Permission Keys Helper
|
|
439
|
+
|
|
440
|
+
**Source:** `collected_data.modules[moduleCode].permissions`
|
|
441
|
+
|
|
442
|
+
**Implementation:** See `references/data-mapping.md` for `buildPermissionKeys()` function implementation.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 02-normalization-helpers
|
|
3
|
+
description: Helper functions for normalizing field definitions, columns, filters, actions, charts, and KPIs across various JSON schema formats
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Normalization Helpers
|
|
7
|
+
|
|
8
|
+
These helper functions normalize field definitions, columns, filters, actions, charts, and KPIs from various JSON schema conventions into a standard format used by the HTML renderer.
|
|
9
|
+
|
|
10
|
+
## Column Normalization
|
|
11
|
+
|
|
12
|
+
```javascript
|
|
13
|
+
// Helper: normalize a column definition regardless of field naming convention
|
|
14
|
+
function normalizeColumn(c) {
|
|
15
|
+
return {
|
|
16
|
+
field: c.code || c.name || c.id || c.field || c.fieldCode || "",
|
|
17
|
+
label: c.label || c.displayName || c.code || c.name || "",
|
|
18
|
+
type: c.renderAs === "badge" ? "badge" : (c.type || c.dataType || "text"),
|
|
19
|
+
sortable: !!c.sortable
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Handles:** `code`, `name`, `id`, `field`, `fieldCode` for field reference; `label`, `displayName` for display; `renderAs`, `type`, `dataType` for type detection; `sortable` flag.
|
|
25
|
+
|
|
26
|
+
## Form Field Normalization
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
// Helper: normalize a form field
|
|
30
|
+
function normalizeField(f) {
|
|
31
|
+
return {
|
|
32
|
+
field: f.code || f.name || f.id || f.fieldCode || f.field || "",
|
|
33
|
+
label: f.label || f.displayName || f.code || f.name || "",
|
|
34
|
+
type: f.type || f.fieldType || f.dataType || "text",
|
|
35
|
+
required: !!f.required
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Handles:** Field reference via `code`, `name`, `id`, `fieldCode`, `field`; display via `label`, `displayName`; type via `type`, `fieldType`, `dataType`; required flag.
|
|
41
|
+
|
|
42
|
+
## Filter Normalization (Simple)
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
// Helper: normalize a filter (for SmartTable inline filters — label only)
|
|
46
|
+
function normalizeFilter(f) {
|
|
47
|
+
if (typeof f === 'string') return f;
|
|
48
|
+
return f.label || f.displayName || f.filterLabel || f.name || f.code || f.filterCode || "";
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Handles:** String filters (direct label) or objects with `label`, `displayName`, `filterLabel`, `name`, `code`, or `filterCode`.
|
|
53
|
+
|
|
54
|
+
## SmartFilter Field Normalization
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
// Helper: normalize a SmartFilter field (preserves type/options/entity for rich rendering)
|
|
58
|
+
function normalizeSmartFilterField(f) {
|
|
59
|
+
if (typeof f === 'string') return { label: f, type: 'text', field: '' };
|
|
60
|
+
return {
|
|
61
|
+
field: f.field || f.code || f.name || "",
|
|
62
|
+
label: f.label || f.displayName || f.field || "",
|
|
63
|
+
type: f.type || "text",
|
|
64
|
+
options: f.options || [],
|
|
65
|
+
entity: f.entity || ""
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Handles:** String filters or rich objects with field reference, label, type, options array, and entity linkage for dropdown/select filters.
|
|
71
|
+
|
|
72
|
+
## Action Normalization
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// Helper: normalize an action
|
|
76
|
+
function normalizeAction(a) {
|
|
77
|
+
if (typeof a === 'string') return a;
|
|
78
|
+
return a.code || a.id || a.label || a.actionCode || "";
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Handles:** String actions (direct code/label) or objects with `code`, `id`, `label`, or `actionCode`.
|
|
83
|
+
|
|
84
|
+
## Chart Normalization
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
// Helper: normalize a chart definition
|
|
88
|
+
function normalizeChart(c) {
|
|
89
|
+
if (typeof c === 'string') return { type: 'bar', label: c };
|
|
90
|
+
return {
|
|
91
|
+
type: c.type || c.chartType || 'bar',
|
|
92
|
+
label: c.label || c.displayName || c.title || 'Graphique'
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Handles:** String charts (default to bar type with label) or objects with `type`/`chartType` and `label`/`displayName`/`title`.
|
|
98
|
+
|
|
99
|
+
## KPI Normalization
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
// Helper: normalize a KPI — replace formula values with sample display values
|
|
103
|
+
function normalizeKpi(k) {
|
|
104
|
+
if (typeof k !== 'object') return { label: String(k), value: "0" };
|
|
105
|
+
const label = k.label || k.displayName || "";
|
|
106
|
+
const rawValue = k.value || k.metric || "0";
|
|
107
|
+
let displayValue = rawValue;
|
|
108
|
+
// Detect formula patterns (e.g., count(...), sum(...), ratio(...), avg(...))
|
|
109
|
+
if (typeof rawValue === 'string' && rawValue.includes('(')) {
|
|
110
|
+
const lbl = label.toLowerCase();
|
|
111
|
+
if (rawValue.includes('ratio') || rawValue.includes('%') || lbl.includes('taux') || lbl.includes('rate'))
|
|
112
|
+
displayValue = "87.5%";
|
|
113
|
+
else if (rawValue.includes('avg') || lbl.includes('moyen') || lbl.includes('average'))
|
|
114
|
+
displayValue = "12.4";
|
|
115
|
+
else if (rawValue.includes('sum'))
|
|
116
|
+
displayValue = (lbl.includes('jour') || lbl.includes('day') || lbl.includes('heure') || lbl.includes('hour')) ? "156" : "45,678";
|
|
117
|
+
else
|
|
118
|
+
displayValue = "1,234";
|
|
119
|
+
}
|
|
120
|
+
// Also handle format hint from the KPI definition
|
|
121
|
+
if (k.format === 'percentage' && displayValue === rawValue) displayValue = "80%";
|
|
122
|
+
return { label: label, value: displayValue };
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Handles:** Non-object KPIs (converted to `{label, value}`); label via `label` or `displayName`; value via `value` or `metric`; formula pattern detection (ratio/avg/sum) to generate representative display values; percentage format hints.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Usage Pattern
|
|
131
|
+
|
|
132
|
+
All helpers follow this pattern:
|
|
133
|
+
|
|
134
|
+
1. **Handle multiple naming conventions** for the same field (e.g., `code`, `name`, `id`)
|
|
135
|
+
2. **Preserve data** when already in canonical form
|
|
136
|
+
3. **Generate reasonable defaults** for optional fields
|
|
137
|
+
4. **Convert internal formats** to HTML-renderable values (e.g., formula → sample number)
|
|
138
|
+
|
|
139
|
+
Use these helpers when building `moduleSpecs[moduleCode].screens` arrays to normalize columns, fields, filters, actions, charts, and KPIs from heterogeneous BA JSON outputs.
|