@atlashub/smartstack-cli 4.23.0 → 4.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/skills/ba-generate-html/html/ba-interactive.html +950 -1055
- package/templates/skills/ba-generate-html/html/src/scripts/01-data-init.js +1 -2
- package/templates/skills/ba-generate-html/html/src/scripts/02-navigation.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/03-render-cadrage.js +0 -39
- package/templates/skills/ba-generate-html/html/src/scripts/05-render-specs.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/07-render-handoff.js +0 -1
- package/templates/skills/ba-generate-html/html/src/scripts/08-editing.js +133 -135
- package/templates/skills/ba-generate-html/html/src/scripts/10-comments.js +199 -199
- package/templates/skills/ba-generate-html/html/src/scripts/11-review-panel.js +165 -166
- package/templates/skills/ba-generate-html/html/src/styles/05-modules.css +444 -454
- package/templates/skills/ba-generate-html/html/src/template.html +0 -49
- package/templates/skills/ba-generate-html/references/data-build.md +176 -182
- package/templates/skills/ba-generate-html/references/data-mapping.md +295 -301
- package/templates/skills/ba-generate-html/steps/step-01-collect.md +1 -1
- package/templates/skills/ba-generate-html/steps/step-02-build-data.md +0 -9
- package/templates/skills/derive-prd/SKILL.md +9 -9
- package/templates/skills/derive-prd/references/acceptance-criteria.md +166 -116
- package/templates/skills/derive-prd/references/entity-domain-mapping.md +5 -5
- package/templates/skills/derive-prd/references/handoff-file-templates.md +12 -12
- package/templates/skills/derive-prd/references/handoff-mappings.md +13 -14
- package/templates/skills/derive-prd/references/handoff-seeddata-generation.md +1 -1
- package/templates/skills/derive-prd/references/readiness-scoring.md +41 -50
- package/templates/skills/derive-prd/schemas/handoff-schema.json +2 -2
- package/templates/skills/derive-prd/steps/step-00-validate.md +73 -52
- package/templates/skills/derive-prd/steps/step-01-transform.md +86 -43
- package/templates/skills/ba-generate-html/html/src/partials/cadrage-risks.html +0 -48
|
@@ -29,8 +29,8 @@ Transforms consolidated BA data into structured handoff and PRD files.
|
|
|
29
29
|
|
|
30
30
|
## Input
|
|
31
31
|
|
|
32
|
-
- Consolidated BA feature (`status = "consolidated"`)
|
|
33
|
-
- Source: `docs/{app}/
|
|
32
|
+
- Consolidated BA feature (`status = "consolidated"` or `"specified"`)
|
|
33
|
+
- Source: `docs/{app}/business-analyse/v{X.Y}/index.json` (app-level) + `docs/{app}/{module}/business-analyse/v{X.Y}/` (flat files per module)
|
|
34
34
|
- Usage: `--feature <path>` or auto-detection from `docs/`
|
|
35
35
|
|
|
36
36
|
## Output
|
|
@@ -45,14 +45,14 @@ Transforms consolidated BA data into structured handoff and PRD files.
|
|
|
45
45
|
|
|
46
46
|
## Handoff Categories (8)
|
|
47
47
|
|
|
48
|
-
| Category | Source | Key rules |
|
|
48
|
+
| Category | Source (flat files) | Key rules |
|
|
49
49
|
|----------|--------|-----------|
|
|
50
|
-
| **domain** | `
|
|
51
|
-
| **application** | `
|
|
52
|
-
| **infrastructure** | `
|
|
53
|
-
| **api** |
|
|
54
|
-
| **frontend** | `
|
|
55
|
-
| **seedData** |
|
|
50
|
+
| **domain** | `entities.json > entities[]` | Entities, ValueObjects, Enums |
|
|
51
|
+
| **application** | `usecases.json > useCases[]` | Services, DTOs, Validators |
|
|
52
|
+
| **infrastructure** | `entities.json > entities[]` | EF Configurations, DbSet |
|
|
53
|
+
| **api** | Generated from useCases + entities | Controllers |
|
|
54
|
+
| **frontend** | `screens.json > screens[]` | Pages, Components, Hooks |
|
|
55
|
+
| **seedData** | Generated from entities + permissions | CORE + business |
|
|
56
56
|
| **tests** | All layers | Unit, Integration, Security tests |
|
|
57
57
|
| **documentation** | All layers | Technical docs, user guides, API specs |
|
|
58
58
|
|
|
@@ -1,169 +1,219 @@
|
|
|
1
1
|
# Module Acceptance Criteria (Shared Reference)
|
|
2
2
|
|
|
3
|
-
> **Loaded by:** step-
|
|
4
|
-
> **Purpose:** Define measurable, bash-verifiable acceptance criteria that a module MUST pass
|
|
5
|
-
> **Key principle:** These checks read the REAL JSON files on disk — NOT in-memory data
|
|
3
|
+
> **Loaded by:** step-00-validate (pre-gate), step-01-transform (post-check)
|
|
4
|
+
> **Purpose:** Define measurable, bash-verifiable acceptance criteria that a module MUST pass.
|
|
5
|
+
> **Key principle:** These checks read the REAL JSON files on disk — NOT in-memory data.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Architecture: Flat-File Format
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
`/business-analyse` generates **separate JSON files** per module:
|
|
12
|
+
|
|
13
|
+
| File | Content | Root key |
|
|
14
|
+
|------|---------|----------|
|
|
15
|
+
| `index.json` | Metadata, file references, summary | `metadata`, `files`, `summary` |
|
|
16
|
+
| `entities.json` | Entity definitions | `entities[]` |
|
|
17
|
+
| `rules.json` | Business rules | `rules[]` |
|
|
18
|
+
| `usecases.json` | Use cases | `useCases[]` |
|
|
19
|
+
| `permissions.json` | Roles and permission matrix | `roles[]`, `permissionPaths[]`, `matrix[]` |
|
|
20
|
+
| `screens.json` | UI screen specifications | `screens[]` |
|
|
21
|
+
|
|
22
|
+
The validation script **assembles** these files before checking.
|
|
12
23
|
|
|
13
24
|
---
|
|
14
25
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
|
24
|
-
|
|
25
|
-
| AC-
|
|
26
|
-
| AC-
|
|
27
|
-
| AC-
|
|
28
|
-
| AC-
|
|
29
|
-
| AC-
|
|
30
|
-
| AC-
|
|
31
|
-
| AC-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
## AC Split: Input vs Output
|
|
27
|
+
|
|
28
|
+
ACs are split into two groups based on **when** they can be validated:
|
|
29
|
+
|
|
30
|
+
### Input ACs (checked in step-00-validate)
|
|
31
|
+
|
|
32
|
+
These verify data that `/business-analyse` produces:
|
|
33
|
+
|
|
34
|
+
| # | Criterion | Minimum | Source File | Blocking |
|
|
35
|
+
|---|-----------|---------|-------------|----------|
|
|
36
|
+
| AC-01 | Entities present | 2 | `entities.json > entities[]` | YES |
|
|
37
|
+
| AC-02 | Entity attributes have `type` field | ALL | `entities.json > entities[].attributes[].type` | YES |
|
|
38
|
+
| AC-03 | Use cases present | 2 | `usecases.json > useCases[]` | YES |
|
|
39
|
+
| AC-04 | Business rules present | 2 | `rules.json > rules[]` | YES |
|
|
40
|
+
| AC-05 | Screens present | 1 | `screens.json > screens[]` | YES |
|
|
41
|
+
| AC-06 | Permissions present | 1 | `permissions.json > permissionPaths[]` | YES |
|
|
42
|
+
| AC-07 | Module status consolidated or specified | match | `index.json > metadata.status` | YES |
|
|
43
|
+
|
|
44
|
+
### Output ACs (checked in step-01 post-transform)
|
|
45
|
+
|
|
46
|
+
These verify data that `/derive-prd` step-01 generates:
|
|
47
|
+
|
|
48
|
+
| # | Criterion | Minimum | Location | Blocking |
|
|
49
|
+
|---|-----------|---------|----------|----------|
|
|
50
|
+
| AC-08 | Handoff has 8 categories | 8 | `handoff.filesToCreate` | YES |
|
|
51
|
+
| AC-09 | BR-to-code mapping present | 1 | `handoff.brToCodeMapping[]` | YES |
|
|
52
|
+
| AC-10 | API endpoint summary present | 1 | `handoff.apiEndpointSummary[]` | YES |
|
|
53
|
+
| AC-11 | SeedData entries have category | ALL | `handoff.filesToCreate.seedData[].category` | YES |
|
|
36
54
|
|
|
37
55
|
---
|
|
38
56
|
|
|
39
|
-
##
|
|
57
|
+
## Input Validation Script (step-00)
|
|
40
58
|
|
|
41
|
-
> **Usage:**
|
|
42
|
-
>
|
|
59
|
+
> **Usage:** Validates BA flat files before transformation.
|
|
60
|
+
> Resolves file paths from module `index.json > files` references.
|
|
43
61
|
|
|
44
62
|
```bash
|
|
45
|
-
|
|
63
|
+
MODULE_DIR="{module_ba_dir}"
|
|
46
64
|
node -e "
|
|
47
65
|
const fs = require('fs');
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
const path = require('path');
|
|
67
|
+
const dir = process.argv[1];
|
|
68
|
+
|
|
69
|
+
// Load index.json
|
|
70
|
+
const index = JSON.parse(fs.readFileSync(path.join(dir, 'index.json'), 'utf-8'));
|
|
71
|
+
const files = index.files || {};
|
|
72
|
+
|
|
73
|
+
// Load flat files (with fallbacks)
|
|
74
|
+
function loadFile(key) {
|
|
75
|
+
const ref = files[key];
|
|
76
|
+
if (!ref || !ref.path) return null;
|
|
77
|
+
const filePath = path.join(dir, ref.path);
|
|
78
|
+
if (!fs.existsSync(filePath)) return null;
|
|
79
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const entitiesData = loadFile('entities') || {};
|
|
83
|
+
const usecasesData = loadFile('usecases') || {};
|
|
84
|
+
const rulesData = loadFile('rules') || {};
|
|
85
|
+
const permissionsData = loadFile('permissions') || {};
|
|
86
|
+
const screensData = loadFile('screens') || {};
|
|
87
|
+
|
|
88
|
+
const entities = entitiesData.entities || [];
|
|
89
|
+
const useCases = usecasesData.useCases || [];
|
|
90
|
+
const rules = rulesData.rules || [];
|
|
91
|
+
const permissions = permissionsData.permissionPaths || permissionsData.permissions || [];
|
|
92
|
+
const screens = screensData.screens || [];
|
|
93
|
+
const status = index.metadata?.status || 'unknown';
|
|
68
94
|
|
|
69
95
|
const fails = [];
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// AC-02: Entity
|
|
78
|
-
const badAttrs =
|
|
79
|
-
(e.attributes||[]).filter(a => !a.type).map(a => e.name + '.' + a.name)
|
|
96
|
+
|
|
97
|
+
// AC-01: Entities >= 2
|
|
98
|
+
if (entities.length < 2) {
|
|
99
|
+
fails.push('AC-01: entities = ' + entities.length + ' (min: 2)');
|
|
100
|
+
console.error('FAIL: AC-01: entities >= 2 = ' + entities.length + ' (min: 2)');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// AC-02: Entity attributes have type
|
|
104
|
+
const badAttrs = entities.flatMap(e =>
|
|
105
|
+
(e.attributes || []).filter(a => !a.type).map(a => e.name + '.' + a.name)
|
|
80
106
|
);
|
|
81
107
|
if (badAttrs.length > 0) {
|
|
82
|
-
fails.push(
|
|
83
|
-
console.error('FAIL: AC-02: ' + badAttrs.length + ' attributes without type: ' + badAttrs.slice(0, 5).join(', ')
|
|
108
|
+
fails.push('AC-02: ' + badAttrs.length + ' attributes without type');
|
|
109
|
+
console.error('FAIL: AC-02: ' + badAttrs.length + ' attributes without type: ' + badAttrs.slice(0, 5).join(', '));
|
|
84
110
|
}
|
|
85
111
|
|
|
86
|
-
// AC-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
console.error('FAIL: AC-07: ' + emptyWf.length + ' wireframes have EMPTY content');
|
|
112
|
+
// AC-03: Use cases >= 2
|
|
113
|
+
if (useCases.length < 2) {
|
|
114
|
+
fails.push('AC-03: useCases = ' + useCases.length + ' (min: 2)');
|
|
115
|
+
console.error('FAIL: AC-03: useCases >= 2 = ' + useCases.length + ' (min: 2)');
|
|
91
116
|
}
|
|
92
117
|
|
|
93
|
-
// AC-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
console.
|
|
118
|
+
// AC-04: Business rules >= 2
|
|
119
|
+
if (rules.length < 2) {
|
|
120
|
+
fails.push('AC-04: rules = ' + rules.length + ' (min: 2)');
|
|
121
|
+
console.error('FAIL: AC-04: rules >= 2 = ' + rules.length + ' (min: 2)');
|
|
97
122
|
}
|
|
98
123
|
|
|
99
|
-
// AC-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
console.error('FAIL: AC-15: ' + badRules.length + ' validations have rules as string instead of array');
|
|
124
|
+
// AC-05: Screens >= 1
|
|
125
|
+
if (screens.length < 1) {
|
|
126
|
+
fails.push('AC-05: screens = ' + screens.length + ' (min: 1)');
|
|
127
|
+
console.error('FAIL: AC-05: screens >= 1 = ' + screens.length + ' (min: 1)');
|
|
104
128
|
}
|
|
105
129
|
|
|
106
|
-
// AC-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
console.error('FAIL: AC-16: ' + noMsg.length + ' messages missing "message" field');
|
|
130
|
+
// AC-06: Permissions >= 1
|
|
131
|
+
if (permissions.length < 1) {
|
|
132
|
+
fails.push('AC-06: permissions = ' + permissions.length + ' (min: 1)');
|
|
133
|
+
console.error('FAIL: AC-06: permissions >= 1 = ' + permissions.length + ' (min: 1)');
|
|
111
134
|
}
|
|
112
135
|
|
|
113
|
-
// AC-
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
fails.push(['AC-17: gherkin content invalid', badGherkin.length, 0]);
|
|
118
|
-
console.error('FAIL: AC-17: ' + badGherkin.length + ' gherkin entries missing feature or scenarios[]');
|
|
119
|
-
}
|
|
136
|
+
// AC-07: Status consolidated or specified
|
|
137
|
+
if (status !== 'consolidated' && status !== 'specified') {
|
|
138
|
+
fails.push('AC-07: status = ' + status + ' (expected: consolidated or specified)');
|
|
139
|
+
console.error('FAIL: AC-07: status = ' + status + ' (expected: consolidated or specified)');
|
|
120
140
|
}
|
|
121
141
|
|
|
122
142
|
// Summary
|
|
123
143
|
if (fails.length > 0) {
|
|
124
|
-
console.error('\\nBLOCKING: ' + fails.length + ' acceptance criteria FAILED');
|
|
144
|
+
console.error('\\nBLOCKING: ' + fails.length + ' input acceptance criteria FAILED');
|
|
125
145
|
process.exit(1);
|
|
126
146
|
}
|
|
127
|
-
console.log('PASS: All acceptance criteria met (AC-01 to AC-
|
|
128
|
-
|
|
147
|
+
console.log('PASS: All input acceptance criteria met (AC-01 to AC-07)');
|
|
148
|
+
console.log(' entities: ' + entities.length + ', useCases: ' + useCases.length + ', rules: ' + rules.length + ', screens: ' + screens.length + ', permissions: ' + permissions.length);
|
|
149
|
+
" "$MODULE_DIR"
|
|
129
150
|
```
|
|
130
151
|
|
|
131
152
|
---
|
|
132
153
|
|
|
133
|
-
##
|
|
154
|
+
## Output Validation Script (step-01 post-check)
|
|
134
155
|
|
|
135
|
-
|
|
156
|
+
> **Usage:** Validates handoff data after step-01 transformation.
|
|
136
157
|
|
|
137
|
-
|
|
138
|
-
|
|
158
|
+
```bash
|
|
159
|
+
MODULE_JSON="{module_index_json_path}"
|
|
160
|
+
node -e "
|
|
161
|
+
const fs = require('fs');
|
|
162
|
+
const data = JSON.parse(fs.readFileSync(process.argv[1], 'utf-8'));
|
|
163
|
+
const handoff = data.handoff || {};
|
|
164
|
+
const ftc = handoff.filesToCreate || {};
|
|
165
|
+
|
|
166
|
+
const fails = [];
|
|
167
|
+
|
|
168
|
+
// AC-08: All 8 categories present
|
|
169
|
+
const categories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests', 'documentation'];
|
|
170
|
+
const missing = categories.filter(cat => !ftc[cat]);
|
|
171
|
+
if (missing.length > 0) {
|
|
172
|
+
fails.push('AC-08: missing categories: ' + missing.join(', '));
|
|
173
|
+
console.error('FAIL: AC-08: missing categories: ' + missing.join(', '));
|
|
174
|
+
}
|
|
139
175
|
|
|
140
|
-
|
|
176
|
+
// AC-09: BR-to-code mapping present
|
|
177
|
+
if (!handoff.brToCodeMapping || handoff.brToCodeMapping.length === 0) {
|
|
178
|
+
fails.push('AC-09: brToCodeMapping is empty');
|
|
179
|
+
console.error('FAIL: AC-09: brToCodeMapping is empty');
|
|
180
|
+
}
|
|
141
181
|
|
|
142
|
-
|
|
143
|
-
|
|
182
|
+
// AC-10: API endpoint summary present
|
|
183
|
+
if (!handoff.apiEndpointSummary || handoff.apiEndpointSummary.length === 0) {
|
|
184
|
+
fails.push('AC-10: apiEndpointSummary is empty');
|
|
185
|
+
console.error('FAIL: AC-10: apiEndpointSummary is empty');
|
|
186
|
+
}
|
|
144
187
|
|
|
145
|
-
|
|
188
|
+
// AC-11: SeedData entries have category
|
|
189
|
+
const seedEntries = ftc.seedData || [];
|
|
190
|
+
const noCat = seedEntries.filter(s => !s.category);
|
|
191
|
+
if (noCat.length > 0) {
|
|
192
|
+
fails.push('AC-11: ' + noCat.length + ' seedData entries missing category');
|
|
193
|
+
console.error('FAIL: AC-11: ' + noCat.length + ' seedData entries missing category field');
|
|
194
|
+
}
|
|
146
195
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
196
|
+
if (fails.length > 0) {
|
|
197
|
+
console.error('\\nBLOCKING: ' + fails.length + ' output acceptance criteria FAILED');
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
console.log('PASS: All output acceptance criteria met (AC-08 to AC-11)');
|
|
201
|
+
" "$MODULE_JSON"
|
|
202
|
+
```
|
|
150
203
|
|
|
151
204
|
---
|
|
152
205
|
|
|
153
|
-
## Recovery Actions
|
|
206
|
+
## Recovery Actions
|
|
154
207
|
|
|
155
208
|
| Criterion | Recovery |
|
|
156
209
|
|-----------|----------|
|
|
157
|
-
| AC-01/02 | Re-run
|
|
158
|
-
| AC-03
|
|
159
|
-
| AC-
|
|
160
|
-
| AC-
|
|
161
|
-
| AC-
|
|
162
|
-
| AC-
|
|
163
|
-
| AC-
|
|
164
|
-
| AC-
|
|
165
|
-
| AC-
|
|
166
|
-
| AC-
|
|
167
|
-
| AC-15 | Auto-fix: wrap string in array `[rules]` |
|
|
168
|
-
| AC-16 | Auto-fix: copy `description` → `message` |
|
|
169
|
-
| AC-17 | Re-run step-03 gherkin — ensure each entry has `feature` string + `scenarios` array |
|
|
210
|
+
| AC-01/02 | Re-run `/business-analyse` entity specification |
|
|
211
|
+
| AC-03 | Re-run `/business-analyse` use case specification |
|
|
212
|
+
| AC-04 | Re-run `/business-analyse` business rules specification |
|
|
213
|
+
| AC-05 | Re-run `/business-analyse` screen specification |
|
|
214
|
+
| AC-06 | Re-run `/business-analyse` permission specification |
|
|
215
|
+
| AC-07 | Run `/business-analyse` step-04 consolidation |
|
|
216
|
+
| AC-08 | Re-run `/derive-prd` step-01 transform (missing categories) |
|
|
217
|
+
| AC-09 | Re-run `/derive-prd` step-01 transform (BR mapping) |
|
|
218
|
+
| AC-10 | Re-run `/derive-prd` step-01 transform (API endpoints) |
|
|
219
|
+
| AC-11 | Re-run `/derive-prd` step-01 transform (seedData categories) |
|
|
@@ -12,8 +12,8 @@ Each entity identified during business analysis maps to exactly one file in the
|
|
|
12
12
|
### Entity -> Domain Entity File
|
|
13
13
|
|
|
14
14
|
```
|
|
15
|
-
BA:
|
|
16
|
-
|
|
15
|
+
BA: entities.json > entities[].name = "{EntityName}"
|
|
16
|
+
entities.json > entities[].module = "{ModuleCode}"
|
|
17
17
|
metadata.application = "{AppName}"
|
|
18
18
|
|
|
19
19
|
Domain: src/SmartStack.{AppName}.Domain/{ModuleCode}/Entities/{EntityName}.cs
|
|
@@ -21,7 +21,7 @@ Domain: src/SmartStack.{AppName}.Domain/{ModuleCode}/Entities/{EntityName}.cs
|
|
|
21
21
|
|
|
22
22
|
**Example:**
|
|
23
23
|
```
|
|
24
|
-
BA:
|
|
24
|
+
BA: entities.json > entities[].name = "Employee"
|
|
25
25
|
module = "Employees"
|
|
26
26
|
application = "HumanResources"
|
|
27
27
|
|
|
@@ -31,7 +31,7 @@ Domain: src/SmartStack.HumanResources.Domain/Employees/Entities/Employee.cs
|
|
|
31
31
|
### ValueObject -> Domain ValueObject File
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
BA:
|
|
34
|
+
BA: entities.json > entities[].valueObjects[].name = "{VOName}"
|
|
35
35
|
|
|
36
36
|
Domain: src/SmartStack.{AppName}.Domain/{ModuleCode}/ValueObjects/{VOName}.cs
|
|
37
37
|
```
|
|
@@ -47,7 +47,7 @@ Domain: src/SmartStack.HumanResources.Domain/Employees/ValueObjects/Address.cs
|
|
|
47
47
|
### Enum -> Domain Enum File
|
|
48
48
|
|
|
49
49
|
```
|
|
50
|
-
BA:
|
|
50
|
+
BA: entities.json > entities[].enums[].name = "{EnumName}"
|
|
51
51
|
OR attributes with type "enum" and enumValues[]
|
|
52
52
|
|
|
53
53
|
Domain: src/SmartStack.{AppName}.Domain/{ModuleCode}/Enums/{EnumName}.cs
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 4.1 Domain Files
|
|
8
8
|
|
|
9
|
-
From `
|
|
9
|
+
From `entities.json > entities[]`:
|
|
10
10
|
|
|
11
11
|
```json
|
|
12
12
|
"domain": [
|
|
@@ -18,7 +18,7 @@ Include: Value objects, Enums (`src/Domain/Enums/...`), Domain exceptions (`src/
|
|
|
18
18
|
|
|
19
19
|
## 4.2 Application Files
|
|
20
20
|
|
|
21
|
-
From `
|
|
21
|
+
From `usecases.json > useCases[]`:
|
|
22
22
|
|
|
23
23
|
```json
|
|
24
24
|
"application": [
|
|
@@ -32,7 +32,7 @@ Include: Service per UC cluster, DTOs for API contracts, Validators (FluentValid
|
|
|
32
32
|
|
|
33
33
|
## 4.3 Infrastructure Files
|
|
34
34
|
|
|
35
|
-
From `
|
|
35
|
+
From `entities.json > entities[]`:
|
|
36
36
|
|
|
37
37
|
```json
|
|
38
38
|
"infrastructure": [
|
|
@@ -44,7 +44,7 @@ Include: EF Core config per entity, DbSet in IExtensionsDbContext, DI registrati
|
|
|
44
44
|
|
|
45
45
|
## 4.4 API Files
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Generated from `usecases.json` + `entities.json`:
|
|
48
48
|
|
|
49
49
|
```json
|
|
50
50
|
"api": [
|
|
@@ -56,7 +56,7 @@ Include: One controller per aggregate root, all HTTP methods, error handling
|
|
|
56
56
|
|
|
57
57
|
## 4.5 Frontend Files
|
|
58
58
|
|
|
59
|
-
From `
|
|
59
|
+
From `screens.json > screens[]` and `usecases.json > useCases[]`:
|
|
60
60
|
|
|
61
61
|
> **WIREFRAME TRACEABILITY:** Every frontend file MUST include `linkedWireframes[]` referencing wireframe `screen` identifiers.
|
|
62
62
|
|
|
@@ -86,13 +86,13 @@ From `specification.uiWireframes[]`, `specification.dashboards[]` and `analysis.
|
|
|
86
86
|
|
|
87
87
|
```json
|
|
88
88
|
"seedData": [
|
|
89
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/NavigationApplicationSeedData.cs", "type": "SeedData", "category": "core", "source": "
|
|
90
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/ApplicationRolesSeedData.cs", "type": "SeedData", "category": "core", "source": "
|
|
91
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/NavigationModuleSeedData.cs", "type": "SeedData", "category": "core", "source": "
|
|
92
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/NavigationSectionSeedData.cs", "type": "SeedData", "category": "core", "source": "
|
|
93
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/PermissionsSeedData.cs", "type": "SeedData", "category": "core", "source": "
|
|
94
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/RolesSeedData.cs", "type": "SeedData", "category": "core", "source": "
|
|
95
|
-
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/{Entity}SeedData.cs", "type": "SeedData", "category": "business", "source": "
|
|
89
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/NavigationApplicationSeedData.cs", "type": "SeedData", "category": "core", "source": "generated from permissions.json + screens.json", "module": "shared", "description": "Application-level navigation seed data. Created ONCE per application (FIRST). Provides ApplicationId for modules and roles." },
|
|
90
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/ApplicationRolesSeedData.cs", "type": "SeedData", "category": "core", "source": "generated from permissions.json + screens.json", "module": "shared", "description": "Application-scoped role definitions (admin, manager, contributor, viewer). Created ONCE per application. Provides role entries for SeedRolesAsync()." },
|
|
91
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/NavigationModuleSeedData.cs", "type": "SeedData", "category": "core", "source": "generated from permissions.json + screens.json", "module": "{moduleCode}" },
|
|
92
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/NavigationSectionSeedData.cs", "type": "SeedData", "category": "core", "source": "generated from permissions.json + screens.json", "module": "{moduleCode}", "description": "MANDATORY when sections defined. Seeds section-level navigation entries (list, dashboard, etc.) with full absolute routes." },
|
|
93
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/PermissionsSeedData.cs", "type": "SeedData", "category": "core", "source": "generated from permissions.json + screens.json", "module": "{moduleCode}" },
|
|
94
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/RolesSeedData.cs", "type": "SeedData", "category": "core", "source": "generated from permissions.json + screens.json", "module": "{moduleCode}" },
|
|
95
|
+
{ "path": "src/Infrastructure/Persistence/Seeding/Data/{ModuleName}/{Entity}SeedData.cs", "type": "SeedData", "category": "business", "source": "generated from entities.json", "module": "{moduleCode}" }
|
|
96
96
|
]
|
|
97
97
|
```
|
|
98
98
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Business Rules to Code Mapping
|
|
4
4
|
|
|
5
|
-
Derive from module
|
|
5
|
+
Derive from module `rules.json > rules[]` of **EACH module**.
|
|
6
6
|
|
|
7
7
|
Generate complete mapping for each BR:
|
|
8
8
|
|
|
@@ -26,21 +26,21 @@ Generate complete mapping for each BR:
|
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
For each BR include:
|
|
29
|
-
- **ruleId**: Reference to
|
|
29
|
+
- **ruleId**: Reference to `rules.json > rules[].id`
|
|
30
30
|
- **title**: The rule statement
|
|
31
31
|
- **module**: Which module it belongs to
|
|
32
|
-
- **severity**: "critical", "high", "medium", "low"
|
|
32
|
+
- **severity**: From `rule.severity` (blocking, info, etc.) mapped to "critical", "high", "medium", "low"
|
|
33
33
|
- **implementationPoints**: Array of {layer, component, method, implementation}
|
|
34
34
|
|
|
35
35
|
Layers: Domain, Application, Infrastructure, API, Frontend
|
|
36
36
|
|
|
37
37
|
## Person Extension Mapping
|
|
38
38
|
|
|
39
|
-
When an entity has `personRoleConfig` in its
|
|
39
|
+
When an entity has `personRoleConfig` in its entity data, it MUST be carried into the PRD:
|
|
40
40
|
|
|
41
|
-
| Source (
|
|
42
|
-
|
|
43
|
-
| `
|
|
41
|
+
| Source (entities.json) | Target (PRD) |
|
|
42
|
+
|------------------------|--------------|
|
|
43
|
+
| `entities[].personRoleConfig` | `modules[].entities[].personRoleConfig` |
|
|
44
44
|
| `personRoleConfig.userLinkMode` | Determines scaffold options: `isPersonRole: true, userLinkMode: "{mode}"` |
|
|
45
45
|
| `personRoleConfig.inheritedFields` | Fields to exclude from entity (mandatory) or mark as fallback (optional) |
|
|
46
46
|
|
|
@@ -50,7 +50,8 @@ The `personRoleConfig` object is passed through verbatim to ensure `/apex` and `
|
|
|
50
50
|
|
|
51
51
|
## API Endpoint Summary
|
|
52
52
|
|
|
53
|
-
> **
|
|
53
|
+
> **Generated by step-01 from `usecases.json > useCases[]` + `entities.json > entities[]` + `permissions.json`.**
|
|
54
|
+
> BA does not produce apiEndpoints directly -- they are derived during transformation.
|
|
54
55
|
|
|
55
56
|
```json
|
|
56
57
|
{
|
|
@@ -60,7 +61,6 @@ The `personRoleConfig` object is passed through verbatim to ensure `/apex` and `
|
|
|
60
61
|
"method": "GET",
|
|
61
62
|
"route": "/api/orders",
|
|
62
63
|
"linkedUC": "UC-001",
|
|
63
|
-
"linkedFR": "FR-001",
|
|
64
64
|
"permissions": ["orders.read"],
|
|
65
65
|
"requestSchema": { "type": "query", "params": ["pageNumber", "pageSize", "status"] },
|
|
66
66
|
"responseSchema": { "type": "PaginatedOrderDto[]" },
|
|
@@ -72,7 +72,6 @@ The `personRoleConfig` object is passed through verbatim to ensure `/apex` and `
|
|
|
72
72
|
"method": "POST",
|
|
73
73
|
"route": "/api/orders",
|
|
74
74
|
"linkedUC": "UC-002",
|
|
75
|
-
"linkedFR": "FR-002",
|
|
76
75
|
"permissions": ["orders.create"],
|
|
77
76
|
"requestSchema": { "type": "body", "schema": "CreateOrderDto" },
|
|
78
77
|
"responseSchema": { "type": "OrderDto" },
|
|
@@ -84,11 +83,11 @@ The `personRoleConfig` object is passed through verbatim to ensure `/apex` and `
|
|
|
84
83
|
```
|
|
85
84
|
|
|
86
85
|
For each endpoint:
|
|
87
|
-
- **operation**:
|
|
86
|
+
- **operation**: Derived from use case name
|
|
88
87
|
- **method**: HTTP method (GET, POST, PUT, DELETE, PATCH)
|
|
89
|
-
- **route**:
|
|
90
|
-
- **linkedUC
|
|
91
|
-
- **permissions**: Array of
|
|
88
|
+
- **route**: Generated from app/module path convention
|
|
89
|
+
- **linkedUC**: Use case ID from usecases.json
|
|
90
|
+
- **permissions**: Array of permission paths from permissions.json
|
|
92
91
|
- **requestSchema**: Input contract (query params or body)
|
|
93
92
|
- **responseSchema**: Output contract
|
|
94
93
|
- **errorCodes**: Expected HTTP error codes
|