@atlashub/smartstack-cli 3.8.0 → 3.9.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 (120) hide show
  1. package/dist/index.js +365 -2
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -1
  4. package/templates/agents/action.md +1 -0
  5. package/templates/agents/ba-writer.md +33 -0
  6. package/templates/agents/explore-codebase.md +1 -0
  7. package/templates/agents/explore-docs.md +1 -0
  8. package/templates/agents/fix-grammar.md +1 -0
  9. package/templates/agents/snipper.md +1 -0
  10. package/templates/skills/admin/SKILL.md +6 -0
  11. package/templates/skills/ai-prompt/SKILL.md +32 -136
  12. package/templates/skills/ai-prompt/steps/step-01-implementation.md +122 -0
  13. package/templates/skills/apex/SKILL.md +120 -0
  14. package/templates/skills/apex/_shared.md +86 -0
  15. package/templates/skills/apex/references/agent-teams-protocol.md +164 -0
  16. package/templates/skills/apex/references/smartstack-layers.md +173 -0
  17. package/templates/skills/apex/steps/step-00-init.md +156 -0
  18. package/templates/skills/apex/steps/step-01-analyze.md +169 -0
  19. package/templates/skills/apex/steps/step-02-plan.md +160 -0
  20. package/templates/skills/apex/steps/step-03-execute.md +166 -0
  21. package/templates/skills/apex/steps/step-04-validate.md +138 -0
  22. package/templates/skills/apex/steps/step-05-examine.md +124 -0
  23. package/templates/skills/apex/steps/step-06-resolve.md +105 -0
  24. package/templates/skills/apex/steps/step-07-tests.md +130 -0
  25. package/templates/skills/apex/steps/step-08-run-tests.md +115 -0
  26. package/templates/skills/application/SKILL.md +10 -0
  27. package/templates/skills/application/references/backend-controller-hierarchy.md +58 -0
  28. package/templates/skills/application/references/backend-entity-seeding.md +72 -0
  29. package/templates/skills/application/references/backend-verification.md +88 -0
  30. package/templates/skills/application/references/frontend-verification.md +111 -0
  31. package/templates/skills/application/references/nav-fallback-procedure.md +200 -0
  32. package/templates/skills/application/references/provider-template.md +134 -0
  33. package/templates/skills/application/references/test-frontend.md +73 -0
  34. package/templates/skills/application/references/test-prerequisites.md +72 -0
  35. package/templates/skills/application/steps/step-01-navigation.md +7 -198
  36. package/templates/skills/application/steps/step-03b-provider.md +4 -128
  37. package/templates/skills/application/steps/step-04-backend.md +20 -350
  38. package/templates/skills/application/steps/step-05-frontend.md +12 -101
  39. package/templates/skills/application/steps/step-07-tests.md +12 -132
  40. package/templates/skills/business-analyse/SKILL.md +11 -2
  41. package/templates/skills/business-analyse/html/ba-interactive.html +176 -14
  42. package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +1 -0
  43. package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +16 -4
  44. package/templates/skills/business-analyse/html/src/scripts/06-render-consolidation.js +7 -2
  45. package/templates/skills/business-analyse/html/src/scripts/09-export.js +103 -0
  46. package/templates/skills/business-analyse/html/src/scripts/10-comments.js +12 -6
  47. package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +24 -2
  48. package/templates/skills/business-analyse/html/src/styles/08-review-panel.css +12 -0
  49. package/templates/skills/business-analyse/html/src/template.html +1 -0
  50. package/templates/skills/business-analyse/references/cadrage-structure-cards.md +78 -0
  51. package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +97 -0
  52. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +92 -0
  53. package/templates/skills/business-analyse/references/deploy-data-build.md +121 -0
  54. package/templates/skills/business-analyse/references/deploy-modes.md +49 -0
  55. package/templates/skills/business-analyse/references/handoff-file-templates.md +119 -0
  56. package/templates/skills/business-analyse/references/handoff-mappings.md +81 -0
  57. package/templates/skills/business-analyse/references/html-data-mapping.md +10 -2
  58. package/templates/skills/business-analyse/references/init-schema-deployment.md +65 -0
  59. package/templates/skills/business-analyse/references/review-data-mapping.md +363 -0
  60. package/templates/skills/business-analyse/references/spec-auto-inference.md +57 -0
  61. package/templates/skills/business-analyse/references/ui-dashboard-spec.md +85 -0
  62. package/templates/skills/business-analyse/references/ui-resource-cards.md +110 -0
  63. package/templates/skills/business-analyse/references/validate-incremental-html.md +55 -0
  64. package/templates/skills/business-analyse/steps/step-00-init.md +35 -68
  65. package/templates/skills/business-analyse/steps/step-01-cadrage.md +5 -194
  66. package/templates/skills/business-analyse/steps/step-03a-data.md +6 -49
  67. package/templates/skills/business-analyse/steps/step-03b-ui.md +12 -178
  68. package/templates/skills/business-analyse/steps/step-03d-validate.md +3 -48
  69. package/templates/skills/business-analyse/steps/step-04-consolidation.md +9 -104
  70. package/templates/skills/business-analyse/steps/step-05a-handoff.md +25 -441
  71. package/templates/skills/business-analyse/steps/step-05b-deploy.md +19 -187
  72. package/templates/skills/business-analyse/steps/step-06-review.md +277 -0
  73. package/templates/skills/cc-agent/references/agent-behavior-patterns.md +95 -0
  74. package/templates/skills/cc-agent/steps/step-02-generate.md +5 -78
  75. package/templates/skills/check-version/SKILL.md +7 -0
  76. package/templates/skills/controller/references/controller-code-templates.md +159 -0
  77. package/templates/skills/controller/references/permission-sync-templates.md +152 -0
  78. package/templates/skills/controller/steps/step-03-generate.md +6 -158
  79. package/templates/skills/controller/steps/step-04-perms.md +5 -144
  80. package/templates/skills/debug/SKILL.md +7 -0
  81. package/templates/skills/explore/SKILL.md +6 -0
  82. package/templates/skills/feature-full/SKILL.md +39 -142
  83. package/templates/skills/feature-full/steps/step-01-implementation.md +120 -0
  84. package/templates/skills/gitflow/references/init-config-template.md +135 -0
  85. package/templates/skills/gitflow/references/init-name-normalization.md +103 -0
  86. package/templates/skills/gitflow/references/plan-template.md +69 -0
  87. package/templates/skills/gitflow/references/start-efcore-preflight.md +70 -0
  88. package/templates/skills/gitflow/references/start-local-config.md +110 -0
  89. package/templates/skills/gitflow/steps/step-init.md +18 -289
  90. package/templates/skills/gitflow/steps/step-plan.md +6 -63
  91. package/templates/skills/gitflow/steps/step-start.md +16 -126
  92. package/templates/skills/mcp/SKILL.md +9 -213
  93. package/templates/skills/mcp/steps/step-01-healthcheck.md +108 -0
  94. package/templates/skills/mcp/steps/step-02-tools.md +73 -0
  95. package/templates/skills/notification/SKILL.md +7 -0
  96. package/templates/skills/quick-search/SKILL.md +5 -0
  97. package/templates/skills/ralph-loop/SKILL.md +99 -381
  98. package/templates/skills/ralph-loop/references/category-rules.md +259 -0
  99. package/templates/skills/ralph-loop/references/compact-loop.md +182 -0
  100. package/templates/skills/ralph-loop/references/task-transform-legacy.md +259 -0
  101. package/templates/skills/ralph-loop/references/team-orchestration.md +189 -0
  102. package/templates/skills/ralph-loop/steps/step-00-init.md +111 -383
  103. package/templates/skills/ralph-loop/steps/step-01-task.md +79 -896
  104. package/templates/skills/ralph-loop/steps/step-02-execute.md +68 -680
  105. package/templates/skills/ralph-loop/steps/step-03-commit.md +47 -277
  106. package/templates/skills/ralph-loop/steps/step-04-check.md +124 -607
  107. package/templates/skills/ralph-loop/steps/step-05-report.md +68 -367
  108. package/templates/skills/refactor/SKILL.md +12 -176
  109. package/templates/skills/refactor/steps/step-01-discover.md +60 -0
  110. package/templates/skills/refactor/steps/step-02-execute.md +67 -0
  111. package/templates/skills/review-code/SKILL.md +19 -257
  112. package/templates/skills/review-code/steps/step-01-smartstack.md +96 -0
  113. package/templates/skills/review-code/steps/step-02-detailed-review.md +80 -0
  114. package/templates/skills/review-code/steps/step-03-react.md +44 -0
  115. package/templates/skills/ui-components/SKILL.md +7 -0
  116. package/templates/skills/utils/SKILL.md +6 -0
  117. package/templates/skills/validate/SKILL.md +6 -0
  118. package/templates/skills/validate-feature/SKILL.md +8 -0
  119. package/templates/skills/workflow/SKILL.md +40 -118
  120. package/templates/skills/workflow/steps/step-01-implementation.md +84 -0
@@ -0,0 +1,81 @@
1
+ # Handoff Mappings: BR-to-Code & API Summary
2
+
3
+ ## Business Rules to Code Mapping
4
+
5
+ Derive from `analysis.businessRules[]` of **EACH module**.
6
+
7
+ Generate complete mapping for each BR:
8
+
9
+ ```json
10
+ {
11
+ "brToCodeMapping": [
12
+ {
13
+ "ruleId": "BR-VAL-001",
14
+ "title": "Order total must equal sum of item prices",
15
+ "module": "{moduleCode}",
16
+ "severity": "critical",
17
+ "implementationPoints": [
18
+ { "layer": "Domain", "component": "Order.cs", "method": "CalculateTotal()", "implementation": "Validate sum equals sum of OrderItems.Price" },
19
+ { "layer": "Application", "component": "CreateOrderService.cs", "method": "Handle()", "implementation": "Calculate total before persisting" },
20
+ { "layer": "API", "component": "OrdersController.cs", "method": "CreateOrder()", "implementation": "Return validation error if total mismatch" },
21
+ { "layer": "Frontend", "component": "OrderForm.tsx", "method": "calculateTotal()", "implementation": "Real-time calculation on item change" }
22
+ ]
23
+ }
24
+ ]
25
+ }
26
+ ```
27
+
28
+ For each BR include:
29
+ - **ruleId**: Reference to analysis.businessRules[].id
30
+ - **title**: The rule statement
31
+ - **module**: Which module it belongs to
32
+ - **severity**: "critical", "high", "medium", "low"
33
+ - **implementationPoints**: Array of {layer, component, method, implementation}
34
+
35
+ Layers: Domain, Application, Infrastructure, API, Frontend
36
+
37
+ ## API Endpoint Summary
38
+
39
+ > **ABSOLUTE RULE:** Copy **EXACTLY** from `specification.apiEndpoints[]`. **NEVER** reinvent routes.
40
+
41
+ ```json
42
+ {
43
+ "apiEndpointSummary": [
44
+ {
45
+ "operation": "ListOrders",
46
+ "method": "GET",
47
+ "route": "/api/business/orders",
48
+ "linkedUC": "UC-001",
49
+ "linkedFR": "FR-001",
50
+ "permissions": ["business.orders.read"],
51
+ "requestSchema": { "type": "query", "params": ["pageNumber", "pageSize", "status"] },
52
+ "responseSchema": { "type": "PaginatedOrderDto[]" },
53
+ "errorCodes": [401, 403, 400, 500],
54
+ "module": "{moduleCode}"
55
+ },
56
+ {
57
+ "operation": "CreateOrder",
58
+ "method": "POST",
59
+ "route": "/api/business/orders",
60
+ "linkedUC": "UC-002",
61
+ "linkedFR": "FR-002",
62
+ "permissions": ["business.orders.create"],
63
+ "requestSchema": { "type": "body", "schema": "CreateOrderDto" },
64
+ "responseSchema": { "type": "OrderDto" },
65
+ "errorCodes": [400, 401, 403, 422, 500],
66
+ "module": "{moduleCode}"
67
+ }
68
+ ]
69
+ }
70
+ ```
71
+
72
+ For each endpoint:
73
+ - **operation**: Use case name
74
+ - **method**: HTTP method (GET, POST, PUT, DELETE, PATCH)
75
+ - **route**: Full API path from specification
76
+ - **linkedUC/linkedFR**: Use case and feature requirement IDs
77
+ - **permissions**: Array of exact permission paths
78
+ - **requestSchema**: Input contract (query params or body)
79
+ - **responseSchema**: Output contract
80
+ - **errorCodes**: Expected HTTP error codes
81
+ - **module**: Which module
@@ -161,8 +161,16 @@ function buildPermissionKeys(moduleFeature) {
161
161
  (matrix.roleAssignments || []).forEach(ra => {
162
162
  (ra.permissions || []).forEach(permPath => {
163
163
  const action = permPath.split(".").pop(); // last segment = action
164
- const uiAction = actionMap[action] || action;
165
- keys.push(ra.role + "|" + uiAction);
164
+ if (action === "*") {
165
+ // Wildcard: expand to all standard actions
166
+ Object.values(actionMap).forEach(uiAction => {
167
+ const key = ra.role + "|" + uiAction;
168
+ if (!keys.includes(key)) keys.push(key);
169
+ });
170
+ } else {
171
+ const uiAction = actionMap[action] || action;
172
+ keys.push(ra.role + "|" + uiAction);
173
+ }
166
174
  });
167
175
  });
168
176
  return keys;
@@ -0,0 +1,65 @@
1
+ # Init: JSON Schema Deployment
2
+
3
+ > Reference for step-00-init.md — cache-based schema deployment.
4
+
5
+ ## Cache-Based Deployment Logic
6
+
7
+ ### Step 1: Check Deployment Cache
8
+
9
+ Cache file location: `docs/business/{app}/business-analyse/.schema-cache.json`
10
+
11
+ ```
12
+ IF EXISTS .schema-cache.json:
13
+ Read cache file
14
+ IF cache.version == "{CLI_VERSION}" (from package.json):
15
+ Display: "Schemas already deployed ({CLI_VERSION}) - skipping"
16
+ SKIP deployment → Go to Step 9
17
+ ELSE:
18
+ Display: "Schema version mismatch (cache: {cache.version}, current: {CLI_VERSION})"
19
+ Proceed to deployment
20
+ ELSE:
21
+ Display: "Deploying schemas (first time)..."
22
+ Proceed to deployment
23
+ ```
24
+
25
+ ### Step 2: Deploy Schemas (if needed)
26
+
27
+ Source: `schemas/` (relative to skill root = `~/.claude/skills/business-analyse/schemas/`)
28
+ Destination: `docs/business/{app}/business-analyse/schemas/`
29
+
30
+ ```
31
+ docs/business/{app}/business-analyse/schemas/
32
+ ├── feature-schema.json
33
+ ├── application-schema.json
34
+ ├── sections/
35
+ │ ├── metadata-schema.json
36
+ │ ├── discovery-schema.json
37
+ │ ├── analysis-schema.json
38
+ │ ├── specification-schema.json
39
+ │ ├── validation-schema.json
40
+ │ └── handoff-schema.json
41
+ └── shared/
42
+ └── common-defs.json
43
+ ```
44
+
45
+ **Total: 9 files to deploy.**
46
+
47
+ ### Step 3: Write Cache File
48
+
49
+ ```json
50
+ {
51
+ "version": "{CLI_VERSION}",
52
+ "deployedAt": "{ISO timestamp}",
53
+ "schemas": [
54
+ "feature-schema.json",
55
+ "application-schema.json",
56
+ "sections/metadata-schema.json",
57
+ "sections/discovery-schema.json",
58
+ "sections/analysis-schema.json",
59
+ "sections/specification-schema.json",
60
+ "sections/validation-schema.json",
61
+ "sections/handoff-schema.json",
62
+ "shared/common-defs.json"
63
+ ]
64
+ }
65
+ ```
@@ -0,0 +1,363 @@
1
+ # Review Data Mapping Reference (references/review-data-mapping.md)
2
+
3
+ > **Used by:** step-06-review (Apply Review Corrections)
4
+ > **Purpose:** Reverse mapping from ba-review.json (HTML export) back to feature.json format
5
+ > **Complement of:** `references/html-data-mapping.md` (forward mapping)
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ The ba-review.json is exported from the interactive HTML with the same structure as the HTML data model. This document defines the **reverse transformation** to apply corrections back into feature.json format.
12
+
13
+ ---
14
+
15
+ ## Cadrage Reverse Mapping
16
+
17
+ ### Scope (HTML → feature.json)
18
+
19
+ ```javascript
20
+ // HTML format: { vital: [{name, description}], important: [...], optional: [...], excluded: [...] }
21
+ // feature.json format: { mustHave: [string], shouldHave: [string], couldHave: [string], outOfScope: [string] }
22
+
23
+ reverseScope(reviewCadrage) {
24
+ return {
25
+ mustHave: (reviewCadrage.scope?.vital || []).map(s => s.name),
26
+ shouldHave: (reviewCadrage.scope?.important || []).map(s => s.name),
27
+ couldHave: (reviewCadrage.scope?.optional || []).map(s => s.name),
28
+ outOfScope: (reviewCadrage.scope?.excluded || []).map(s => s.name)
29
+ };
30
+ }
31
+ ```
32
+
33
+ ### Stakeholders (HTML → feature.json)
34
+
35
+ ```javascript
36
+ // HTML format: { role, function, tasks[], frequency, access, frustrations }
37
+ // feature.json format: { role, function, involvement, tasks[], frequency, painPoints[] }
38
+
39
+ const accessToInvolvement = {
40
+ admin: "decision-maker",
41
+ manager: "consulted",
42
+ contributor: "end-user",
43
+ viewer: "informed"
44
+ };
45
+
46
+ const frequencyReverse = {
47
+ daily: "Quotidien",
48
+ weekly: "Hebdomadaire",
49
+ monthly: "Mensuel",
50
+ occasional: "Occasionnel"
51
+ };
52
+
53
+ reverseStakeholder(htmlStakeholder) {
54
+ return {
55
+ role: htmlStakeholder.role,
56
+ function: htmlStakeholder.function || "",
57
+ involvement: accessToInvolvement[htmlStakeholder.access] || "end-user",
58
+ tasks: htmlStakeholder.tasks || [],
59
+ frequency: frequencyReverse[htmlStakeholder.frequency] || htmlStakeholder.frequency,
60
+ painPoints: (htmlStakeholder.frustrations || "").split("\n").filter(Boolean)
61
+ };
62
+ }
63
+ ```
64
+
65
+ ### Problem / Vision / Current (HTML → feature.json)
66
+
67
+ ```javascript
68
+ // HTML has detailed sub-fields; feature.json has flat strings
69
+ reverseProblemVision(reviewCadrage) {
70
+ return {
71
+ problem: reviewCadrage.problem?.description || "",
72
+ trigger: reviewCadrage.problem?.trigger || "",
73
+ asIs: reviewCadrage.current?.tools || "",
74
+ toBe: reviewCadrage.vision?.changes || ""
75
+ };
76
+ }
77
+ ```
78
+
79
+ ### Risks (HTML → feature.json)
80
+
81
+ ```javascript
82
+ // HTML format: { description, probability, impact, mitigation }
83
+ // feature.json format: { id, type, description, probability, impact, mitigation }
84
+
85
+ reverseRisks(reviewRisks, existingRisks) {
86
+ return (reviewRisks || []).map((r, i) => {
87
+ // Try to match with existing risk by description
88
+ const existing = (existingRisks || []).find(er => er.description === r.description);
89
+ return {
90
+ id: existing?.id || "RISK-" + String(i + 1).padStart(3, "0"),
91
+ type: existing?.type || "business",
92
+ description: r.description,
93
+ probability: r.probability,
94
+ impact: r.impact,
95
+ mitigation: r.mitigation || ""
96
+ };
97
+ });
98
+ }
99
+ ```
100
+
101
+ ### Acceptance Criteria (HTML → feature.json)
102
+
103
+ ```javascript
104
+ // HTML format: success.definition (string, one criterion per line)
105
+ // feature.json format: acceptanceCriteria[]: { id, criterion, validated }
106
+
107
+ reverseAcceptanceCriteria(reviewSuccess, existingCriteria) {
108
+ const lines = (reviewSuccess?.definition || "").split("\n").filter(Boolean);
109
+ return lines.map((line, i) => {
110
+ const existing = (existingCriteria || []).find(ac => ac.criterion === line);
111
+ return {
112
+ id: existing?.id || "AC-" + String(i + 1).padStart(3, "0"),
113
+ criterion: line.trim(),
114
+ validated: existing?.validated || false
115
+ };
116
+ });
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Module Specifications Reverse Mapping
123
+
124
+ ### Use Cases (HTML → feature.json)
125
+
126
+ ```javascript
127
+ // HTML format: { id, name, actor, steps (newline-separated string), alternative (string) }
128
+ // feature.json format: { id, name, primaryActor, permission, preconditions[], postconditions[], mainScenario[], alternativeScenarios[], linkedRules[] }
129
+
130
+ reverseUseCase(htmlUC, existingUC) {
131
+ return {
132
+ id: htmlUC.id || existingUC?.id,
133
+ name: htmlUC.name,
134
+ primaryActor: htmlUC.actor,
135
+ permission: existingUC?.permission || "",
136
+ preconditions: existingUC?.preconditions || [],
137
+ postconditions: existingUC?.postconditions || [],
138
+ mainScenario: (htmlUC.steps || "").split("\n").filter(Boolean),
139
+ alternativeScenarios: existingUC?.alternativeScenarios || [],
140
+ errorScenarios: existingUC?.errorScenarios || [],
141
+ linkedRules: existingUC?.linkedRules || []
142
+ };
143
+ }
144
+ ```
145
+
146
+ ### Business Rules (HTML → feature.json)
147
+
148
+ ```javascript
149
+ // HTML format: { id, name, category, statement, example (string) }
150
+ // feature.json format: { id, name, category, statement, priority, conditions[], examples[], testability }
151
+
152
+ reverseBusinessRule(htmlBR, existingBR) {
153
+ return {
154
+ id: htmlBR.id || existingBR?.id,
155
+ name: htmlBR.name,
156
+ category: htmlBR.category,
157
+ statement: htmlBR.statement,
158
+ priority: existingBR?.priority || "must",
159
+ conditions: existingBR?.conditions || [],
160
+ examples: htmlBR.example
161
+ ? [{ input: htmlBR.example, expected: "" }]
162
+ : (existingBR?.examples || []),
163
+ testability: existingBR?.testability || ""
164
+ };
165
+ }
166
+ ```
167
+
168
+ ### Entities (HTML → feature.json)
169
+
170
+ ```javascript
171
+ // HTML format: { name, description, attributes: [{name, description}], relationships: [string] }
172
+ // feature.json format: { name, description, attributes: [{name, description, required}], relationships: [{target, type, description}] }
173
+
174
+ reverseEntity(htmlEntity, existingEntity) {
175
+ return {
176
+ name: htmlEntity.name,
177
+ description: htmlEntity.description || "",
178
+ attributes: (htmlEntity.attributes || []).map(a => {
179
+ const existing = (existingEntity?.attributes || []).find(ea => ea.name === a.name);
180
+ return {
181
+ name: a.name,
182
+ description: a.description || "",
183
+ required: existing?.required ?? true
184
+ };
185
+ }),
186
+ relationships: (htmlEntity.relationships || []).map(relStr => {
187
+ // Parse "Target (type) - description" format back to structured
188
+ const match = relStr.match(/^(.+?)\s*\((.+?)\)\s*-\s*(.*)$/);
189
+ if (match) {
190
+ return { target: match[1].trim(), type: match[2].trim(), description: match[3].trim() };
191
+ }
192
+ return { target: relStr, type: "reference", description: "" };
193
+ })
194
+ };
195
+ }
196
+ ```
197
+
198
+ ### Permissions (HTML → feature.json)
199
+
200
+ ```javascript
201
+ // HTML format: permissions[] = ["Role|Action", "Role|Action", "Role|*"]
202
+ // feature.json format: permissionMatrix = { permissions: [{path, action, description}], roleAssignments: [{role, permissions[]}] }
203
+
204
+ const actionToPermission = {
205
+ Consulter: "read",
206
+ Creer: "create",
207
+ Modifier: "update",
208
+ Supprimer: "delete",
209
+ Valider: "validate",
210
+ Exporter: "export"
211
+ };
212
+
213
+ reversePermissions(htmlPermissions, moduleCode, appName) {
214
+ const rolePerms = {};
215
+
216
+ // Group permissions by role
217
+ (htmlPermissions || []).forEach(p => {
218
+ const [role, action] = p.split("|");
219
+ if (!rolePerms[role]) rolePerms[role] = [];
220
+ if (action === "*") {
221
+ // Wildcard: add all standard permission paths
222
+ Object.values(actionToPermission).forEach(permAction => {
223
+ const path = `business.${appName}.${moduleCode}.*.${permAction}`;
224
+ if (!rolePerms[role].includes(path)) rolePerms[role].push(path);
225
+ });
226
+ } else {
227
+ const permAction = actionToPermission[action] || action.toLowerCase();
228
+ const path = `business.${appName}.${moduleCode}.*.${permAction}`;
229
+ if (!rolePerms[role].includes(path)) rolePerms[role].push(path);
230
+ }
231
+ });
232
+
233
+ // Build unique permission paths
234
+ const allPaths = new Set();
235
+ Object.values(rolePerms).forEach(perms => perms.forEach(p => allPaths.add(p)));
236
+
237
+ return {
238
+ permissions: Array.from(allPaths).map(path => ({
239
+ path,
240
+ action: path.split(".").pop(),
241
+ description: ""
242
+ })),
243
+ roleAssignments: Object.entries(rolePerms).map(([role, perms]) => ({
244
+ role,
245
+ permissions: perms
246
+ }))
247
+ };
248
+ }
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Modules Reverse Mapping
254
+
255
+ ### Module List (HTML → feature.json)
256
+
257
+ ```javascript
258
+ // HTML format: modules[] = [{ code, name, description, featureType, priority, entities[], status }]
259
+ // feature.json format: modules[] = [{ code, description, featureType, dependencies[], dependents[], status, priority, sortOrder, entities[], estimatedComplexity }]
260
+
261
+ reverseModule(htmlModule, existingModule) {
262
+ return {
263
+ code: htmlModule.code,
264
+ description: htmlModule.description || "",
265
+ featureType: htmlModule.featureType || "data-centric",
266
+ dependencies: existingModule?.dependencies || [],
267
+ dependents: existingModule?.dependents || [],
268
+ status: existingModule?.status || "pending",
269
+ priority: htmlModule.priority || "must",
270
+ sortOrder: existingModule?.sortOrder || 0,
271
+ entities: htmlModule.entities || [],
272
+ estimatedComplexity: existingModule?.estimatedComplexity || "medium",
273
+ featureJsonPath: existingModule?.featureJsonPath
274
+ };
275
+ }
276
+ ```
277
+
278
+ ---
279
+
280
+ ## Consolidation Reverse Mapping
281
+
282
+ ### Cross-Module Interactions (HTML → feature.json)
283
+
284
+ ```javascript
285
+ // HTML format: consolidation.interactions[] = [{ from, to, description }]
286
+ // feature.json format: consolidation.crossModuleInteractions[] = [{ fromModule, toModule, interactionType, description, entities[] }]
287
+
288
+ reverseInteraction(htmlInteraction, existingInteraction) {
289
+ return {
290
+ fromModule: htmlInteraction.from,
291
+ toModule: htmlInteraction.to,
292
+ interactionType: existingInteraction?.interactionType || "data-reference",
293
+ description: htmlInteraction.description || "",
294
+ entities: existingInteraction?.entities || []
295
+ };
296
+ }
297
+ ```
298
+
299
+ ### E2E Flows (HTML → feature.json)
300
+
301
+ ```javascript
302
+ // HTML format: consolidation.e2eFlows[] = [{ name, steps: [{module, action}], actors }]
303
+ // feature.json format: consolidation.e2eFlows[] = [{ name, steps: [{module, action, permission}] }]
304
+
305
+ reverseE2EFlow(htmlFlow, existingFlow) {
306
+ return {
307
+ name: htmlFlow.name,
308
+ steps: (htmlFlow.steps || []).map((s, i) => ({
309
+ module: s.module,
310
+ action: s.action,
311
+ permission: existingFlow?.steps?.[i]?.permission || ""
312
+ }))
313
+ };
314
+ }
315
+ ```
316
+
317
+ ---
318
+
319
+ ## Review Comments Preservation
320
+
321
+ Comments from the review are stored in a new `review` section of the master feature.json:
322
+
323
+ ```javascript
324
+ {
325
+ review: {
326
+ appliedAt: "ISO timestamp",
327
+ sourceVersion: "1.0",
328
+ comments: [
329
+ // Inline structured comments from data.comments[]
330
+ { id, sectionId, cardIndex, author, timestamp, content, status, category }
331
+ ],
332
+ specComments: {
333
+ // Textarea comments keyed as "moduleCode.type.index"
334
+ "Employees.uc.0": "Comment text",
335
+ "Employees.br.1": "Another comment"
336
+ },
337
+ wireframeComments: {
338
+ // Wireframe feedback keyed by module
339
+ "Employees": { "EM-list": "Comment on list wireframe" }
340
+ },
341
+ changeSummary: {
342
+ cadrageModified: true,
343
+ modulesAdded: [],
344
+ modulesRemoved: [],
345
+ modulesModified: ["Employees", "LeaveRequests"],
346
+ commentsCount: 5
347
+ }
348
+ }
349
+ }
350
+ ```
351
+
352
+ ---
353
+
354
+ ## Matching Strategy
355
+
356
+ When applying corrections, always try to **match existing items** before creating new ones:
357
+
358
+ 1. **By ID**: If the review item has an ID (UC-001, BR-VAL-001), find the same ID in feature.json
359
+ 2. **By name**: If no ID match, find by exact name match
360
+ 3. **New item**: If no match found, create a new item with a generated ID
361
+ 4. **Removed items**: Items present in feature.json but absent from review are marked as removed (not deleted)
362
+
363
+ This preserves referential integrity (linked rules, use case references) across the update.
@@ -0,0 +1,57 @@
1
+ # Specification: Auto-Inference Rules
2
+
3
+ > Reference for step-03a-data.md — convention/override depth auto-generation from entity definitions.
4
+
5
+ ## Entity Attribute → SmartTable Column
6
+
7
+ | Attribute Type | Column Format | Sortable | Filterable | Notes |
8
+ |---|---|---|---|---|
9
+ | string + unique | text | yes | yes | clickAction: navigate:detail |
10
+ | string | text | yes | yes | — |
11
+ | enum / status | badge | yes | yes (multi-select) | colorMap from lifeCycles if exists |
12
+ | FK:Entity | text (join .name) | yes | yes (entity-select) | Display related entity name |
13
+ | decimal | currency | yes | no | — |
14
+ | int | number | yes | no | — |
15
+ | datetime | date-relative | yes | yes (date-range) | — |
16
+ | bool | boolean | yes | yes (toggle) | — |
17
+ | text (long) | — | no | no | Hidden in table, visible in detail |
18
+
19
+ ## Entity Attribute → SmartForm Field
20
+
21
+ | Attribute Type | Component | Required from | Notes |
22
+ |---|---|---|---|
23
+ | string | Input | entity.required | — |
24
+ | string (multiline) | TextArea | entity.required | rows: 4 |
25
+ | enum | Select | entity.required | source: enum name |
26
+ | FK:Entity | EntitySelect | entity.required | source: target entity, searchable |
27
+ | decimal | NumberInput | entity.required | — |
28
+ | int | NumberInput | entity.required | — |
29
+ | datetime | DatePicker | entity.required | — |
30
+ | bool | Toggle | — | default: false |
31
+
32
+ ## Auto-Generated Sections by featureType
33
+
34
+ | featureType | Sections generated |
35
+ |---|---|
36
+ | data-centric | list, create, detail |
37
+ | workflow | list, create, detail, edit |
38
+ | integration | list, detail, config |
39
+ | reporting | dashboard |
40
+ | full-module | list, create, detail, edit, dashboard |
41
+
42
+ ## Section Generation Rules
43
+
44
+ 1. **list section:** SmartTable with all non-long-text attributes as columns, actions = [view, edit, delete], defaultSort = { createdAt, desc }
45
+ 2. **create section:** SmartForm with all writable attributes as fields, component inferred from type
46
+ 3. **detail section:** DetailCard with all attributes + child SmartTable for each 1:N relationship
47
+ 4. **edit section:** Same as create but pre-filled (mode: edit)
48
+ 5. **dashboard section:** Trigger 3d (dashboard specification)
49
+
50
+ ## Status/Lifecycle Enhancement
51
+
52
+ If entity has a status/enum field AND lifeCycles exists:
53
+ - list section: status column gets `format: badge`, `colorMap: stateMachine:{Entity}`
54
+ - list section: rowActions get `showWhen` conditions based on state machine transitions
55
+ - detail section: add StatusBadge resource + transition action buttons
56
+
57
+ Write auto-generated sections to `specification.sections[]` via `ba-writer.enrichSection()`
@@ -0,0 +1,85 @@
1
+ # UI: Dashboard Specification
2
+
3
+ > Reference for step-03b-ui.md — section 3d dashboard KPI and chart capture.
4
+
5
+ ## 3d. Dashboard Specification (if section = dashboard)
6
+
7
+ When a "dashboard" section is selected, capture structured KPI and chart data **in addition** to the standard ASCII mockup.
8
+
9
+ 1. **Ask client for KPIs** via AskUserQuestion (batch):
10
+ - KPI name and metric description
11
+ - Visualization type: `kpi-card`, `bar`, `line`, `pie`, `area`, `donut`, `stacked-bar`
12
+ - Data source entity
13
+ - Format: `number`, `currency`, `percent`, `duration`
14
+ - Thresholds (warning/critical) if applicable
15
+
16
+ 2. **Ask client for filters:**
17
+ - Date range filter? Default period? (day/week/month/quarter/year)
18
+ - Entity-based filters? (status, category, etc.)
19
+
20
+ 3. **Ask client for refresh mode:**
21
+ - Static (load on page open)
22
+ - Polling (periodic refresh)
23
+ - SignalR (real-time push)
24
+
25
+ 4. **Store in specification.dashboards[]:**
26
+
27
+ ```json
28
+ {
29
+ "code": "{module}-dashboard",
30
+ "title": "{Module} Dashboard",
31
+ "description": "Vue d'ensemble des métriques {module}",
32
+ "linkedUCs": ["UC-XXX"],
33
+ "refreshMode": "static",
34
+ "defaultPeriod": "month",
35
+ "kpis": [
36
+ {
37
+ "code": "total-items",
38
+ "label": "Total Items",
39
+ "metric": "COUNT(entity)",
40
+ "format": "number",
41
+ "visualization": "kpi-card",
42
+ "dataSource": "Entity",
43
+ "thresholds": { "warning": 100, "critical": 50 }
44
+ },
45
+ {
46
+ "code": "items-by-status",
47
+ "label": "Items by Status",
48
+ "metric": "COUNT(entity) GROUP BY status",
49
+ "format": "number",
50
+ "visualization": "pie",
51
+ "dataSource": "Entity",
52
+ "dimensions": ["status"]
53
+ }
54
+ ],
55
+ "filters": [
56
+ { "field": "dateRange", "type": "dateRange", "label": "Période" },
57
+ { "field": "status", "type": "multiselect", "label": "Statut" }
58
+ ],
59
+ "permissionsRequired": ["business.{app}.{module}.read"]
60
+ }
61
+ ```
62
+
63
+ 5. **ALSO generate the standard ASCII mockup** for the dashboard with KPI cards + chart placeholders:
64
+
65
+ ```
66
+ ╔═══════════════════════════════════════════════════════════════╗
67
+ ║ {Module} > Dashboard Période: [Ce mois ▾] ║
68
+ ╠═══════════════════════════════════════════════════════════════╣
69
+ ║ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ║
70
+ ║ │ KPI #1 │ │ KPI #2 │ │ KPI #3 │ │ KPI #4 │ ║
71
+ ║ │ 1,234 │ │ 567 │ │ 89.2% │ │ 12,400 │ ║
72
+ ║ │ ↑ +12% │ │ ↓ -3% │ │ → 0% │ │ ↑ +5% │ ║
73
+ ║ └──────────┘ └──────────┘ └──────────┘ └──────────┘ ║
74
+ ╠═══════════════════════════════════════════════════════════════╣
75
+ ║ ┌─────────────────────────┐ ┌─────────────────────────┐ ║
76
+ ║ │ [Bar Chart] │ │ [Pie Chart] │ ║
77
+ ║ │ Items by Month │ │ Items by Status │ ║
78
+ ║ │ ████ │ │ ████████ │ ║
79
+ ║ │ ████ ████ │ │ ███ ███ │ ║
80
+ ║ │ ████ ████ ████ │ │ ██ 42% ██ │ ║
81
+ ║ └─────────────────────────┘ └─────────────────────────┘ ║
82
+ ╚═══════════════════════════════════════════════════════════════╝
83
+ ```
84
+
85
+ Store the mockup in specification.wireframes[] AS WELL (for visual reference).