@atlashub/smartstack-cli 3.7.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.
- package/dist/index.js +365 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
- package/templates/agents/action.md +1 -0
- package/templates/agents/ba-writer.md +33 -0
- package/templates/agents/explore-codebase.md +1 -0
- package/templates/agents/explore-docs.md +1 -0
- package/templates/agents/fix-grammar.md +1 -0
- package/templates/agents/snipper.md +1 -0
- package/templates/skills/admin/SKILL.md +6 -0
- package/templates/skills/ai-prompt/SKILL.md +32 -136
- package/templates/skills/ai-prompt/steps/step-01-implementation.md +122 -0
- package/templates/skills/apex/SKILL.md +120 -0
- package/templates/skills/apex/_shared.md +86 -0
- package/templates/skills/apex/references/agent-teams-protocol.md +164 -0
- package/templates/skills/apex/references/smartstack-layers.md +173 -0
- package/templates/skills/apex/steps/step-00-init.md +156 -0
- package/templates/skills/apex/steps/step-01-analyze.md +169 -0
- package/templates/skills/apex/steps/step-02-plan.md +160 -0
- package/templates/skills/apex/steps/step-03-execute.md +166 -0
- package/templates/skills/apex/steps/step-04-validate.md +138 -0
- package/templates/skills/apex/steps/step-05-examine.md +124 -0
- package/templates/skills/apex/steps/step-06-resolve.md +105 -0
- package/templates/skills/apex/steps/step-07-tests.md +130 -0
- package/templates/skills/apex/steps/step-08-run-tests.md +115 -0
- package/templates/skills/application/SKILL.md +10 -0
- package/templates/skills/application/references/backend-controller-hierarchy.md +58 -0
- package/templates/skills/application/references/backend-entity-seeding.md +72 -0
- package/templates/skills/application/references/backend-verification.md +88 -0
- package/templates/skills/application/references/frontend-verification.md +111 -0
- package/templates/skills/application/references/nav-fallback-procedure.md +200 -0
- package/templates/skills/application/references/provider-template.md +134 -0
- package/templates/skills/application/references/test-frontend.md +73 -0
- package/templates/skills/application/references/test-prerequisites.md +72 -0
- package/templates/skills/application/steps/step-01-navigation.md +7 -198
- package/templates/skills/application/steps/step-03b-provider.md +4 -128
- package/templates/skills/application/steps/step-04-backend.md +20 -350
- package/templates/skills/application/steps/step-05-frontend.md +12 -101
- package/templates/skills/application/steps/step-07-tests.md +12 -132
- package/templates/skills/business-analyse/SKILL.md +11 -2
- package/templates/skills/business-analyse/html/ba-interactive.html +3214 -2246
- package/templates/skills/business-analyse/html/build-html.js +77 -0
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +130 -0
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +22 -0
- package/templates/skills/business-analyse/html/src/scripts/03-render-cadrage.js +208 -0
- package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +211 -0
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +554 -0
- package/templates/skills/business-analyse/html/src/scripts/06-render-consolidation.js +110 -0
- package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +90 -0
- package/templates/skills/business-analyse/html/src/scripts/08-editing.js +45 -0
- package/templates/skills/business-analyse/html/src/scripts/09-export.js +168 -0
- package/templates/skills/business-analyse/html/src/scripts/10-comments.js +171 -0
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +161 -0
- package/templates/skills/business-analyse/html/src/styles/01-variables.css +38 -0
- package/templates/skills/business-analyse/html/src/styles/02-layout.css +101 -0
- package/templates/skills/business-analyse/html/src/styles/03-navigation.css +62 -0
- package/templates/skills/business-analyse/html/src/styles/04-cards.css +196 -0
- package/templates/skills/business-analyse/html/src/styles/05-modules.css +325 -0
- package/templates/skills/business-analyse/html/src/styles/06-wireframes.css +230 -0
- package/templates/skills/business-analyse/html/src/styles/07-comments.css +184 -0
- package/templates/skills/business-analyse/html/src/styles/08-review-panel.css +241 -0
- package/templates/skills/business-analyse/html/src/template.html +623 -0
- package/templates/skills/business-analyse/references/cadrage-structure-cards.md +78 -0
- package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +97 -0
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +92 -0
- package/templates/skills/business-analyse/references/deploy-data-build.md +121 -0
- package/templates/skills/business-analyse/references/deploy-modes.md +49 -0
- package/templates/skills/business-analyse/references/handoff-file-templates.md +119 -0
- package/templates/skills/business-analyse/references/handoff-mappings.md +81 -0
- package/templates/skills/business-analyse/references/html-data-mapping.md +10 -2
- package/templates/skills/business-analyse/references/init-schema-deployment.md +65 -0
- package/templates/skills/business-analyse/references/review-data-mapping.md +363 -0
- package/templates/skills/business-analyse/references/spec-auto-inference.md +57 -0
- package/templates/skills/business-analyse/references/ui-dashboard-spec.md +85 -0
- package/templates/skills/business-analyse/references/ui-resource-cards.md +110 -0
- package/templates/skills/business-analyse/references/validate-incremental-html.md +55 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +35 -68
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +5 -194
- package/templates/skills/business-analyse/steps/step-03a-data.md +6 -49
- package/templates/skills/business-analyse/steps/step-03b-ui.md +12 -178
- package/templates/skills/business-analyse/steps/step-03d-validate.md +3 -48
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +9 -104
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +25 -441
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +19 -187
- package/templates/skills/business-analyse/steps/step-06-review.md +277 -0
- package/templates/skills/cc-agent/references/agent-behavior-patterns.md +95 -0
- package/templates/skills/cc-agent/steps/step-02-generate.md +5 -78
- package/templates/skills/check-version/SKILL.md +7 -0
- package/templates/skills/controller/references/controller-code-templates.md +159 -0
- package/templates/skills/controller/references/permission-sync-templates.md +152 -0
- package/templates/skills/controller/steps/step-03-generate.md +6 -158
- package/templates/skills/controller/steps/step-04-perms.md +5 -144
- package/templates/skills/debug/SKILL.md +7 -0
- package/templates/skills/explore/SKILL.md +6 -0
- package/templates/skills/feature-full/SKILL.md +39 -142
- package/templates/skills/feature-full/steps/step-01-implementation.md +120 -0
- package/templates/skills/gitflow/references/init-config-template.md +135 -0
- package/templates/skills/gitflow/references/init-name-normalization.md +103 -0
- package/templates/skills/gitflow/references/plan-template.md +69 -0
- package/templates/skills/gitflow/references/start-efcore-preflight.md +70 -0
- package/templates/skills/gitflow/references/start-local-config.md +110 -0
- package/templates/skills/gitflow/steps/step-init.md +18 -289
- package/templates/skills/gitflow/steps/step-plan.md +6 -63
- package/templates/skills/gitflow/steps/step-start.md +16 -126
- package/templates/skills/mcp/SKILL.md +9 -213
- package/templates/skills/mcp/steps/step-01-healthcheck.md +108 -0
- package/templates/skills/mcp/steps/step-02-tools.md +73 -0
- package/templates/skills/notification/SKILL.md +7 -0
- package/templates/skills/quick-search/SKILL.md +5 -0
- package/templates/skills/ralph-loop/SKILL.md +99 -381
- package/templates/skills/ralph-loop/references/category-rules.md +259 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +182 -0
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +259 -0
- package/templates/skills/ralph-loop/references/team-orchestration.md +189 -0
- package/templates/skills/ralph-loop/steps/step-00-init.md +111 -383
- package/templates/skills/ralph-loop/steps/step-01-task.md +79 -896
- package/templates/skills/ralph-loop/steps/step-02-execute.md +68 -680
- package/templates/skills/ralph-loop/steps/step-03-commit.md +47 -277
- package/templates/skills/ralph-loop/steps/step-04-check.md +124 -607
- package/templates/skills/ralph-loop/steps/step-05-report.md +68 -367
- package/templates/skills/refactor/SKILL.md +12 -176
- package/templates/skills/refactor/steps/step-01-discover.md +60 -0
- package/templates/skills/refactor/steps/step-02-execute.md +67 -0
- package/templates/skills/review-code/SKILL.md +19 -257
- package/templates/skills/review-code/steps/step-01-smartstack.md +96 -0
- package/templates/skills/review-code/steps/step-02-detailed-review.md +80 -0
- package/templates/skills/review-code/steps/step-03-react.md +44 -0
- package/templates/skills/ui-components/SKILL.md +7 -0
- package/templates/skills/utils/SKILL.md +6 -0
- package/templates/skills/validate/SKILL.md +6 -0
- package/templates/skills/validate-feature/SKILL.md +8 -0
- package/templates/skills/workflow/SKILL.md +40 -118
- package/templates/skills/workflow/steps/step-01-implementation.md +84 -0
|
@@ -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).
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# UI: Resource Structure Cards
|
|
2
|
+
|
|
3
|
+
> Reference for step-03b-ui.md — exact JSON formats for section resources (SmartTable, SmartForm) and wireframes.
|
|
4
|
+
|
|
5
|
+
## specification.sections[] (with resources)
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"code": "list",
|
|
10
|
+
"labels": { "fr": "Liste", "en": "List", "it": "Elenco", "de": "Liste" },
|
|
11
|
+
"route": "/business/{app}/{module}/list",
|
|
12
|
+
"icon": "list",
|
|
13
|
+
"permission": "business.{app}.{module}.read",
|
|
14
|
+
"wireframe": "{module}-list",
|
|
15
|
+
"useCases": ["UC-{PREFIX}-001", "UC-{PREFIX}-002"],
|
|
16
|
+
"businessRules": ["BR-VAL-{PREFIX}-001"],
|
|
17
|
+
"resources": [
|
|
18
|
+
{
|
|
19
|
+
"code": "{module}-grid",
|
|
20
|
+
"type": "SmartTable",
|
|
21
|
+
"entity": "{MainEntity}",
|
|
22
|
+
"permission": "business.{app}.{module}.read",
|
|
23
|
+
"columns": ["name", "status", "createdAt"],
|
|
24
|
+
"columnDefs": [
|
|
25
|
+
{ "field": "code", "label": {"fr": "Code", "en": "Code"}, "format": "text", "sortable": true, "filterable": true, "clickAction": "navigate:detail" },
|
|
26
|
+
{ "field": "name", "label": {"fr": "Nom", "en": "Name"}, "format": "text", "sortable": true, "filterable": true },
|
|
27
|
+
{ "field": "status", "label": {"fr": "Statut", "en": "Status"}, "format": "badge", "sortable": true, "filterable": true, "colorMap": "stateMachine:{Entity}" },
|
|
28
|
+
{ "field": "createdAt", "label": {"fr": "Créé le", "en": "Created"}, "format": "date-relative", "sortable": true }
|
|
29
|
+
],
|
|
30
|
+
"actions": ["view", "edit", "delete"],
|
|
31
|
+
"rowActions": [
|
|
32
|
+
{ "action": "view", "icon": "eye", "permission": "business.{app}.{module}.read" },
|
|
33
|
+
{ "action": "edit", "icon": "edit", "permission": "business.{app}.{module}.update", "showWhen": {"status": ["draft"]} },
|
|
34
|
+
{ "action": "delete", "icon": "trash", "permission": "business.{app}.{module}.delete", "confirm": true }
|
|
35
|
+
],
|
|
36
|
+
"filters": ["status", "dateRange"],
|
|
37
|
+
"defaultSort": { "field": "createdAt", "direction": "desc" },
|
|
38
|
+
"defaultPageSize": 20,
|
|
39
|
+
"emptyState": { "icon": "inbox", "message": {"fr": "Aucun enregistrement", "en": "No records"}, "createAction": true }
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**MANDATORY for SmartTable:** `columnDefs`, `rowActions`, `defaultSort`, `emptyState`
|
|
46
|
+
|
|
47
|
+
## SmartForm resource (for create/edit sections)
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"code": "{module}-form",
|
|
52
|
+
"type": "SmartForm",
|
|
53
|
+
"entity": "{MainEntity}",
|
|
54
|
+
"permission": "business.{app}.{module}.create",
|
|
55
|
+
"fields": [
|
|
56
|
+
{ "name": "code", "component": "Input", "required": true, "validation": "Unique, auto-generated" },
|
|
57
|
+
{ "name": "name", "component": "Input", "required": true },
|
|
58
|
+
{ "name": "type", "component": "Select", "required": true, "source": "EntityTypeEnum" },
|
|
59
|
+
{ "name": "description", "component": "TextArea", "required": false },
|
|
60
|
+
{ "name": "parentId", "component": "EntitySelect", "source": "ParentEntity", "required": true },
|
|
61
|
+
{ "name": "startDate", "component": "DatePicker", "required": true },
|
|
62
|
+
{ "name": "isActive", "component": "Toggle", "default": true }
|
|
63
|
+
],
|
|
64
|
+
"formLayout": {
|
|
65
|
+
"type": "tabs",
|
|
66
|
+
"tabs": [
|
|
67
|
+
{ "code": "general", "label": {"fr": "Général", "en": "General"}, "fields": ["code", "name", "type", "description"] },
|
|
68
|
+
{ "code": "details", "label": {"fr": "Détails", "en": "Details"}, "fields": ["parentId", "startDate", "isActive"] }
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**MANDATORY for SmartForm:** `fields` with `component` type, `formLayout`
|
|
75
|
+
|
|
76
|
+
## specification.uiWireframes[]
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"screen": "{module}-{section}",
|
|
81
|
+
"section": "{section}",
|
|
82
|
+
"description": "Description of the screen",
|
|
83
|
+
"mockupFormat": "ascii",
|
|
84
|
+
"mockup": "╔═══...",
|
|
85
|
+
"elements": ["DataGrid", "FilterBar", "Pagination", "CreateButton"],
|
|
86
|
+
"actions": ["filter", "sort", "create", "view-detail"],
|
|
87
|
+
"permissionsRequired": ["business.{app}.{module}.read"],
|
|
88
|
+
"componentMapping": [
|
|
89
|
+
{ "wireframeElement": "DataGrid", "reactComponent": "SmartTable" },
|
|
90
|
+
{ "wireframeElement": "FilterBar", "reactComponent": "SmartFilter" },
|
|
91
|
+
{ "wireframeElement": "CreateButton", "reactComponent": "Button" }
|
|
92
|
+
],
|
|
93
|
+
"layout": {
|
|
94
|
+
"type": "page",
|
|
95
|
+
"regions": [
|
|
96
|
+
{ "id": "toolbar", "position": "top", "components": [
|
|
97
|
+
{ "type": "FilterBar", "resourceRef": "{module}-filters" },
|
|
98
|
+
{ "type": "ActionMenu", "resourceRef": "{module}-actions", "permission": "business.{app}.{module}.create" }
|
|
99
|
+
]},
|
|
100
|
+
{ "id": "content", "position": "main", "span": 12, "components": [
|
|
101
|
+
{ "type": "SmartTable", "resourceRef": "{module}-grid" }
|
|
102
|
+
]}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**REQUIRED fields:** `screen`, `mockup`, `elements`, `section`, `componentMapping`, `layout` are ALL mandatory.
|
|
109
|
+
A wireframe without `componentMapping` or `layout` will FAIL validation in step 9.
|
|
110
|
+
**layout.regions[].components[].resourceRef** MUST match a `sections[].resources[].code`.
|