@atlashub/smartstack-cli 4.74.0 → 4.75.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 +111 -36
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +14 -3
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-reader.md +17 -15
- package/templates/agents/ba-writer.md +49 -51
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/backend-checks.sh +21 -7
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +47 -10
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/apex/references/post-checks.md +5 -2
- package/templates/skills/apex/references/smartstack-frontend.md +53 -7
- package/templates/skills/apex/steps/step-00-init.md +74 -0
- package/templates/skills/apex/steps/step-03-execute.md +16 -4
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +39 -6
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +50 -5
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +102 -2
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/business-analyse/SKILL.md +14 -0
- package/templates/skills/business-analyse/_shared.md +27 -0
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +34 -26
- package/templates/skills/business-analyse/questionnaire/01-context.md +13 -9
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +20 -27
- package/templates/skills/business-analyse/questionnaire.md +86 -9
- package/templates/skills/business-analyse/references/03-json-schemas.md +213 -0
- package/templates/skills/business-analyse/references/03-post-check-validation.md +144 -0
- package/templates/skills/business-analyse/references/03-smartstack-entity-guards.md +32 -0
- package/templates/skills/business-analyse/references/04-cross-module-validation.md +95 -0
- package/templates/skills/business-analyse/references/04-file-allocation.md +162 -0
- package/templates/skills/business-analyse/references/04-naming-audit-checks.md +174 -0
- package/templates/skills/business-analyse/references/04-semantic-validation-matrix.md +118 -0
- package/templates/skills/business-analyse/references/domain-research-playbook.md +234 -0
- package/templates/skills/business-analyse/references/entity-sourcing-presentation.md +166 -0
- package/templates/skills/business-analyse/references/init-resume-logic.md +70 -0
- package/templates/skills/business-analyse/references/module-completeness-challenge.md +174 -0
- package/templates/skills/business-analyse/references/multi-app-detection.md +149 -0
- package/templates/skills/business-analyse/references/portal-classification.md +52 -0
- package/templates/skills/business-analyse/references/validation-checklist.md +30 -1
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +37 -4
- package/templates/skills/business-analyse/steps/step-00-init.md +22 -190
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +365 -269
- package/templates/skills/business-analyse/steps/step-02-structure.md +98 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +652 -229
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +308 -287
- package/templates/skills/business-analyse-design/SKILL.md +10 -0
- package/templates/skills/business-analyse-design/references/screens-post-check.md +221 -0
- package/templates/skills/business-analyse-design/references/screens-type-mapping.md +138 -0
- package/templates/skills/business-analyse-design/references/smartcomponents-templates.md +225 -0
- package/templates/skills/{business-analyse → business-analyse-design}/references/spec-auto-inference.md +117 -117
- package/templates/skills/business-analyse-design/steps/step-01-screens.md +36 -162
- package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +8 -7
- package/templates/skills/business-analyse-design/steps/step-03-navigation.md +89 -42
- package/templates/skills/business-analyse-develop/references/compact-loop.md +9 -0
- package/templates/skills/business-analyse-develop/references/handoff-quality-gate.md +132 -0
- package/templates/skills/business-analyse-develop/references/prd-v3-transformation.md +326 -0
- package/templates/skills/business-analyse-develop/references/report-reconciliation.md +140 -0
- package/templates/skills/business-analyse-develop/references/report-template.md +142 -0
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +5 -177
- package/templates/skills/business-analyse-develop/steps/step-02-execute.md +17 -4
- package/templates/skills/business-analyse-develop/steps/step-03-commit.md +6 -2
- package/templates/skills/business-analyse-develop/steps/step-04-check.md +6 -0
- package/templates/skills/business-analyse-develop/steps/step-05-report.md +3 -269
- package/templates/skills/business-analyse-handoff/SKILL.md +10 -0
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +208 -0
- package/templates/skills/business-analyse-handoff/references/context-isolation-pattern.md +47 -0
- package/templates/skills/business-analyse-handoff/references/handoff-file-inventory.md +49 -0
- package/templates/skills/business-analyse-handoff/references/handoff-global-validation.md +142 -0
- package/templates/skills/business-analyse-handoff/references/prd-validation-checks.md +125 -0
- package/templates/skills/business-analyse-handoff/references/project-index-update.md +98 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +9 -160
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +10 -99
- package/templates/skills/business-analyse-html/SKILL.md +10 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +306 -81
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +15 -2
- package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +6 -46
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +88 -33
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +116 -0
- package/templates/skills/business-analyse-html/html/src/styles/10-diagrams.css +73 -0
- package/templates/skills/business-analyse-html/html/src/template.html +2 -0
- package/templates/skills/business-analyse-html/references/02-embedded-artifacts-building.md +144 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +141 -0
- package/templates/skills/business-analyse-html/references/02-mapping-tables.md +442 -0
- package/templates/skills/business-analyse-html/references/02-normalization-helpers.md +139 -0
- package/templates/skills/business-analyse-html/references/02-screen-format-detection.md +283 -0
- package/templates/skills/business-analyse-html/references/02-self-check-validation.md +199 -0
- package/templates/skills/business-analyse-html/references/data-build.md +22 -1
- package/templates/skills/business-analyse-html/references/data-mapping.md +40 -5
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +12 -555
- package/templates/skills/business-analyse-review/SKILL.md +10 -0
- package/templates/skills/business-analyse-status/SKILL.md +8 -0
- package/templates/skills/dev-start/SKILL.md +143 -307
- package/templates/skills/efcore/SKILL.md +13 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# POST-CHECK Validation (step-03-specify)
|
|
2
|
+
|
|
3
|
+
Before advancing to step 04, run these validations for EACH module:
|
|
4
|
+
|
|
5
|
+
```javascript
|
|
6
|
+
const errors = [];
|
|
7
|
+
const warnings = [];
|
|
8
|
+
|
|
9
|
+
for (const mod of modules) {
|
|
10
|
+
// mod.dir = resolveModuleDir(applicationCode, mod.code)
|
|
11
|
+
// e.g., docs/projet-rh/v1.0/human-resources/employees/
|
|
12
|
+
const ent = READ(mod.dir + '/entities.json')?.entities || [];
|
|
13
|
+
const ucs = READ(mod.dir + '/usecases.json')?.useCases || [];
|
|
14
|
+
const brs = READ(mod.dir + '/rules.json')?.rules || [];
|
|
15
|
+
const perms = READ(mod.dir + '/permissions.json');
|
|
16
|
+
const sections = mod.anticipatedSections || [];
|
|
17
|
+
const sectionCodes = new Set(sections.map(s => s.code));
|
|
18
|
+
|
|
19
|
+
// Mandatory checks (BLOCKING)
|
|
20
|
+
if (ent.length === 0) errors.push(mod.code + ": 0 entities");
|
|
21
|
+
if (ucs.length === 0) errors.push(mod.code + ": 0 use cases");
|
|
22
|
+
if (brs.length === 0) errors.push(mod.code + ": 0 business rules");
|
|
23
|
+
if (!perms?.permissionPaths?.length) errors.push(mod.code + ": no permissions");
|
|
24
|
+
|
|
25
|
+
// sectionCode validation
|
|
26
|
+
for (const uc of ucs) {
|
|
27
|
+
if (!uc.sectionCode) errors.push(mod.code + ": UC '" + uc.id + "' missing sectionCode");
|
|
28
|
+
else if (!sectionCodes.has(uc.sectionCode)) errors.push(mod.code + ": UC '" + uc.id + "' sectionCode '" + uc.sectionCode + "' not in anticipatedSections");
|
|
29
|
+
}
|
|
30
|
+
for (const br of brs) {
|
|
31
|
+
if (!br.sectionCode) errors.push(mod.code + ": BR '" + br.id + "' missing sectionCode");
|
|
32
|
+
else if (!sectionCodes.has(br.sectionCode)) errors.push(mod.code + ": BR '" + br.id + "' sectionCode '" + br.sectionCode + "' not in anticipatedSections");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Entity attribute checks
|
|
36
|
+
for (const e of ent) {
|
|
37
|
+
for (const a of (e.attributes || [])) {
|
|
38
|
+
if (!a.type) warnings.push(mod.code + ": entity " + e.name + " attr '" + a.name + "' missing type");
|
|
39
|
+
if (a.type === 'enum' && !a.defaultValue) errors.push(mod.code + ": enum attr '" + a.name + "' missing defaultValue");
|
|
40
|
+
// FK naming convention: must end with "Id"
|
|
41
|
+
if ((a.type === 'guid' || a.type === 'string') && a.foreignKey && !a.name.endsWith('Id'))
|
|
42
|
+
warnings.push(mod.code + ": entity " + e.name + " FK attr '" + a.name + "' should end with 'Id'");
|
|
43
|
+
}
|
|
44
|
+
// Person Extension Pattern check
|
|
45
|
+
const personFields = ['firstName', 'lastName', 'email', 'phoneNumber', 'phone'];
|
|
46
|
+
const foundPersonFields = (e.attributes || []).filter(a => personFields.includes(a.name));
|
|
47
|
+
if (foundPersonFields.length >= 3 && !e.personRoleConfig) {
|
|
48
|
+
errors.push(mod.code + ": entity '" + e.name + "' has " + foundPersonFields.length +
|
|
49
|
+
" person fields (" + foundPersonFields.map(f => f.name).join(", ") +
|
|
50
|
+
") but no personRoleConfig — use Person Extension Pattern (entity-architecture-decision.md section 0). " +
|
|
51
|
+
"Person fields (firstName, lastName, email) belong on auth_Users, not on the domain entity.");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Canonical usecases key check
|
|
56
|
+
const rawUCFile = READ(mod.dir + '/usecases.json');
|
|
57
|
+
if (rawUCFile && !rawUCFile.useCases && rawUCFile.usecases) {
|
|
58
|
+
errors.push(mod.code + ": usecases.json uses 'usecases' key instead of canonical 'useCases' — fix before proceeding");
|
|
59
|
+
}
|
|
60
|
+
// Check steps serialization format
|
|
61
|
+
for (const uc of ucs) {
|
|
62
|
+
if (uc.steps && Array.isArray(uc.steps) && uc.steps.length > 0 && typeof uc.steps[0] === 'object') {
|
|
63
|
+
errors.push(mod.code + ": UC '" + uc.id + "' uses steps[] with objects — must use mainScenario[] with strings");
|
|
64
|
+
}
|
|
65
|
+
if (uc.actor && !uc.primaryActor) {
|
|
66
|
+
warnings.push(mod.code + ": UC '" + uc.id + "' uses 'actor' instead of canonical 'primaryActor'");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Cross-reference checks
|
|
71
|
+
for (const uc of ucs) {
|
|
72
|
+
for (const brRef of (uc.businessRules || [])) {
|
|
73
|
+
if (!brs.find(br => br.id === brRef)) warnings.push(mod.code + ": UC '" + uc.id + "' references non-existent BR '" + brRef + "'");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Section permission checks
|
|
78
|
+
for (const section of sections) {
|
|
79
|
+
if (section.sectionType === 'view') {
|
|
80
|
+
const viewPerms = (perms?.permissionPaths || []).filter(p => p.includes('.' + section.code + '.'));
|
|
81
|
+
if (viewPerms.length > 0) errors.push(mod.code + ": view section '" + section.code + "' has " + viewPerms.length + " permissions (should inherit)");
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Quality gate: UC count (C6 — BLOCKING if < 4, WARNING if < 6)
|
|
86
|
+
if (ucs.length > 0 && ucs.length < 4) {
|
|
87
|
+
errors.push(mod.code + ": only " + ucs.length + " use cases (minimum: 4)");
|
|
88
|
+
} else if (ucs.length > 0 && ucs.length < 6) {
|
|
89
|
+
warnings.push(mod.code + ": only " + ucs.length + " use cases (recommended: >= 6)");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Quality gate: Permission path count (C7 — WARNING if < 5)
|
|
93
|
+
const permPaths = perms?.permissionPaths || [];
|
|
94
|
+
if (permPaths.length > 0 && permPaths.length < 5) {
|
|
95
|
+
warnings.push(mod.code + ": only " + permPaths.length + " permission paths (recommended: >= 5 — check for missing Export/Import)");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Quality gate: Entity count (C9 — WARNING if single entity)
|
|
99
|
+
if (ent.length === 1) {
|
|
100
|
+
warnings.push(mod.code + ": single entity module — verify this is intentional (config/lookup OK)");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Quality gate: BR-CALC must have formula (C13 — BLOCKING)
|
|
104
|
+
for (const br of brs) {
|
|
105
|
+
if ((br.category === 'calculation' || (br.id && br.id.includes('CALC'))) && !br.formula) {
|
|
106
|
+
errors.push(mod.code + ": BR '" + br.id + "' is a calculation rule but missing 'formula' field");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Quality gate: Computed attributes must have BR-CALC (C11 — BLOCKING)
|
|
111
|
+
for (const e of ent) {
|
|
112
|
+
for (const a of (e.attributes || [])) {
|
|
113
|
+
if (a.computed === true) {
|
|
114
|
+
const hasBRCalc = brs.some(br =>
|
|
115
|
+
(br.category === 'calculation' || (br.id && br.id.includes('CALC'))) &&
|
|
116
|
+
(br.entities || []).includes(e.name)
|
|
117
|
+
);
|
|
118
|
+
if (!hasBRCalc) errors.push(mod.code + ": " + e.name + ".'" + a.name + "' is computed:true but no BR-CALC references " + e.name);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Quality gate: Versioned attributes detection (C15 — WARNING)
|
|
124
|
+
for (const e of ent) {
|
|
125
|
+
for (const a of (e.attributes || [])) {
|
|
126
|
+
if (['salary', 'rate', 'grade', 'price', 'tarif'].some(k => a.name.toLowerCase().includes(k))) {
|
|
127
|
+
if (!e.versionedAttributes?.length)
|
|
128
|
+
warnings.push(mod.code + ": " + e.name + ".'" + a.name + "' may need versioning but no versionedAttributes defined");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (errors.length > 0) {
|
|
135
|
+
Display("POST-CHECK FAILED (" + errors.length + " errors):");
|
|
136
|
+
errors.forEach(e => Display(" ✗ " + e));
|
|
137
|
+
BLOCKING_ERROR("Fix all errors before advancing to step 04");
|
|
138
|
+
}
|
|
139
|
+
if (warnings.length > 0) {
|
|
140
|
+
Display("POST-CHECK warnings (" + warnings.length + "):");
|
|
141
|
+
warnings.forEach(w => Display(" ⚠ " + w));
|
|
142
|
+
}
|
|
143
|
+
Display("POST-CHECK PASS: " + modules.length + " modules validated");
|
|
144
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# SmartStack Entity Convention Guards (step-03-specify)
|
|
2
|
+
|
|
3
|
+
Before finalizing each entity, apply these rules:
|
|
4
|
+
|
|
5
|
+
## B-bis-1. Person Extension Pattern
|
|
6
|
+
|
|
7
|
+
(ref: `entity-architecture-decision.md` section 0)
|
|
8
|
+
|
|
9
|
+
IF the entity matches a person role (Employee, Customer, Manager, Consultant, etc.):
|
|
10
|
+
- **DO NOT** add firstName, lastName, email, phoneNumber as direct attributes
|
|
11
|
+
- **DO** add `userId` (type: `string`, FK to auth_Users — ASP.NET Identity uses string IDs)
|
|
12
|
+
- **DO** add `personRoleConfig` metadata with variant (mandatory/optional)
|
|
13
|
+
- Personal fields come from User, not from the domain entity
|
|
14
|
+
|
|
15
|
+
## B-bis-2. Versioned Sensitive Data
|
|
16
|
+
|
|
17
|
+
IF the entity has attributes that change over time with audit requirements (salary, rate, grade):
|
|
18
|
+
- **DO NOT** put them directly on the entity as single fields
|
|
19
|
+
- **DO** extract into a versioned satellite table (e.g., Employee → Salary with effectiveDate)
|
|
20
|
+
- Mark with `"versionedAttributes"` in entity spec
|
|
21
|
+
|
|
22
|
+
## B-bis-3. SmartStack Socle Entities (NEVER redefine)
|
|
23
|
+
|
|
24
|
+
- Users/Identity → `auth_Users` (managed by SmartStack Identity)
|
|
25
|
+
- Tenants → `tenant_Tenants` (managed by SmartStack Core)
|
|
26
|
+
- Departments → `ref_Departments` or `rh_Departments` (check if exists in target DB)
|
|
27
|
+
|
|
28
|
+
## B-bis-4. Foreign Key Conventions
|
|
29
|
+
|
|
30
|
+
- All FK attributes MUST end with `Id` suffix (e.g., `departmentId`, `userId`)
|
|
31
|
+
- FK to Identity users MUST use type `string` (ASP.NET Identity convention, NOT guid)
|
|
32
|
+
- FK to domain entities MUST use type `guid`
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Cross-Module Validation Rules
|
|
2
|
+
|
|
3
|
+
> **Purpose:** Define FK validation, circular dependency detection, and dependency graph checks
|
|
4
|
+
> that must be executed before consolidation approval.
|
|
5
|
+
|
|
6
|
+
## Module Index Files & Granular Data Loading
|
|
7
|
+
|
|
8
|
+
For each completed module, read `index.json` and discover granular files:
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
const moduleFiles = {
|
|
12
|
+
entities: "entities.json",
|
|
13
|
+
rules: "rules.json",
|
|
14
|
+
usecases: "usecases.json",
|
|
15
|
+
permissions: "permissions.json",
|
|
16
|
+
screens: "screens.json"
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
for (const module of completedModules) {
|
|
20
|
+
const index = ba-reader.readSection(module.code, "index");
|
|
21
|
+
module.files = index.files;
|
|
22
|
+
// Load only files needed for consolidation
|
|
23
|
+
module.entities = ba-reader.readSection(module.code, "entities");
|
|
24
|
+
module.permissions = ba-reader.readSection(module.code, "permissions");
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Foreign Key References & Shared Entities Validation
|
|
29
|
+
|
|
30
|
+
Build entity registry and validate cross-module references:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
const entityRegistry = {};
|
|
34
|
+
for (const module of completedModules) {
|
|
35
|
+
entityRegistry[module.code] = {
|
|
36
|
+
entities: module.entities.map(e => ({
|
|
37
|
+
name: e.name,
|
|
38
|
+
attributes: e.attributes.map(a => a.name),
|
|
39
|
+
pk: e.attributes.find(a => a.name === "Id" || a.unique)?.name || "Id"
|
|
40
|
+
}))
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Detect shared entities
|
|
45
|
+
const sharedEntities = [];
|
|
46
|
+
for (const module of completedModules) {
|
|
47
|
+
for (const entity of module.entities) {
|
|
48
|
+
for (const rel of entity.relationships || []) {
|
|
49
|
+
if (rel.target.includes(".")) {
|
|
50
|
+
const [targetModule, targetEntity] = rel.target.split(".");
|
|
51
|
+
if (!entityRegistry[targetModule]) {
|
|
52
|
+
BLOCKING_ERROR(`Module ${module.code}: references non-existent module "${targetModule}"`);
|
|
53
|
+
}
|
|
54
|
+
sharedEntities.push({
|
|
55
|
+
entity: targetEntity,
|
|
56
|
+
definedIn: targetModule,
|
|
57
|
+
referencedBy: module.code,
|
|
58
|
+
referenceType: rel.type
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Circular Dependency Detection
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
const cycles = detectCycles(dependencyGraph);
|
|
70
|
+
if (cycles.length > 0) {
|
|
71
|
+
BLOCKING_ERROR("Circular dependencies detected:");
|
|
72
|
+
for (const cycle of cycles) {
|
|
73
|
+
ERROR(` ${cycle.join(" → ")}`);
|
|
74
|
+
}
|
|
75
|
+
ACTIONS: Review dependencies, move shared entities to Core module, or use event-driven communication
|
|
76
|
+
STOP - DO NOT PROCEED
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Cross-Module Interactions Display
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
═══════════════════════════════════════════════════════════════
|
|
84
|
+
CROSS-MODULE INTERACTIONS VALIDATED
|
|
85
|
+
═══════════════════════════════════════════════════════════════
|
|
86
|
+
|
|
87
|
+
| Source Module | Target | Type | Status |
|
|
88
|
+
|---------------|--------|------|--------|
|
|
89
|
+
| Orders | Customers.Customer | FK (N:1) | ✓ RESOLVED |
|
|
90
|
+
| Invoices | Customers.Customer | FK (N:1) | ✓ RESOLVED |
|
|
91
|
+
|
|
92
|
+
Total: {count} cross-module references
|
|
93
|
+
Shared entities: {count}
|
|
94
|
+
═══════════════════════════════════════════════════════════════
|
|
95
|
+
```
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# File Allocation Rules
|
|
2
|
+
|
|
3
|
+
> **Critical reference:** Defines which validation data belongs in `consolidation.json` vs `validation.json`.
|
|
4
|
+
> Mixing contents across files is a BLOCKING ERROR.
|
|
5
|
+
|
|
6
|
+
## Strict Allocation Table
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
+==============================================================================+
|
|
10
|
+
| FILE ALLOCATION REFERENCE — MANDATORY |
|
|
11
|
+
+==============================================================================+
|
|
12
|
+
| |
|
|
13
|
+
| consolidation.json contient UNIQUEMENT : |
|
|
14
|
+
| - crossModuleInteractions |
|
|
15
|
+
| - sharedEntities |
|
|
16
|
+
| - permissionCoherence |
|
|
17
|
+
| - e2eFlows |
|
|
18
|
+
| - decision (approval) |
|
|
19
|
+
| |
|
|
20
|
+
| validation.json contient UNIQUEMENT : |
|
|
21
|
+
| - semanticChecks |
|
|
22
|
+
| - contractChecks |
|
|
23
|
+
| - namingAudit |
|
|
24
|
+
| - acceptanceCriteria |
|
|
25
|
+
| - globalRiskAssessment |
|
|
26
|
+
| |
|
|
27
|
+
| INTERDICTION de melanger les contenus entre les deux fichiers. |
|
|
28
|
+
| Toute cle ecrite dans le mauvais fichier = ERREUR BLOQUANTE. |
|
|
29
|
+
| |
|
|
30
|
+
+==============================================================================+
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Data Structures
|
|
34
|
+
|
|
35
|
+
### consolidation.json structure
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
{
|
|
39
|
+
crossModuleInteractions: [
|
|
40
|
+
{
|
|
41
|
+
fromModule: string,
|
|
42
|
+
toModule: string,
|
|
43
|
+
interactionType: "FK-reference|event|shared-lookup",
|
|
44
|
+
description: string,
|
|
45
|
+
entities: string[]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
sharedEntities: [
|
|
49
|
+
{
|
|
50
|
+
entity: string,
|
|
51
|
+
ownerModule: string,
|
|
52
|
+
referencedBy: string[],
|
|
53
|
+
sharedFields: string[]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
permissionCoherence: {
|
|
57
|
+
rolesConsistent: boolean,
|
|
58
|
+
pathFormatConsistent: boolean,
|
|
59
|
+
hierarchyRespected: boolean,
|
|
60
|
+
conflicts: any[],
|
|
61
|
+
warnings: any[]
|
|
62
|
+
},
|
|
63
|
+
e2eFlows: [
|
|
64
|
+
{
|
|
65
|
+
name: string,
|
|
66
|
+
modules: string[],
|
|
67
|
+
steps: object[]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
decision: {
|
|
71
|
+
approved: boolean,
|
|
72
|
+
reason: string,
|
|
73
|
+
approvedBy: string,
|
|
74
|
+
approvedAt: string
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### validation.json structure
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
{
|
|
83
|
+
semanticChecks: [
|
|
84
|
+
{
|
|
85
|
+
check: string,
|
|
86
|
+
status: "PASS|WARNING|ERROR",
|
|
87
|
+
details: string[]
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
contractChecks: [
|
|
91
|
+
{
|
|
92
|
+
module: string,
|
|
93
|
+
check: string,
|
|
94
|
+
details: string
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
namingAudit: {
|
|
98
|
+
auditedAt: string,
|
|
99
|
+
issues: object[],
|
|
100
|
+
approved: boolean,
|
|
101
|
+
renames: object[]
|
|
102
|
+
},
|
|
103
|
+
acceptanceCriteria: [
|
|
104
|
+
{
|
|
105
|
+
module: string,
|
|
106
|
+
criteria: string,
|
|
107
|
+
type: "functional|business-rule|performance|security"
|
|
108
|
+
}
|
|
109
|
+
],
|
|
110
|
+
globalRiskAssessment: [
|
|
111
|
+
{
|
|
112
|
+
risk: string,
|
|
113
|
+
severity: "low|medium|high",
|
|
114
|
+
mitigation?: string
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Data Writing Pattern
|
|
121
|
+
|
|
122
|
+
Write consolidation.json:
|
|
123
|
+
```javascript
|
|
124
|
+
ba-writer.enrichSection({
|
|
125
|
+
featureId: {feature_id},
|
|
126
|
+
section: "consolidation",
|
|
127
|
+
data: {
|
|
128
|
+
crossModuleInteractions: [...],
|
|
129
|
+
sharedEntities: [...],
|
|
130
|
+
permissionCoherence: {...},
|
|
131
|
+
e2eFlows: [...],
|
|
132
|
+
decision: {...}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Write validation.json:
|
|
138
|
+
```javascript
|
|
139
|
+
ba-writer.enrichSection({
|
|
140
|
+
featureId: {feature_id},
|
|
141
|
+
section: "validation",
|
|
142
|
+
data: {
|
|
143
|
+
semanticChecks: [...],
|
|
144
|
+
contractChecks: [...],
|
|
145
|
+
namingAudit: {...},
|
|
146
|
+
acceptanceCriteria: [...],
|
|
147
|
+
globalRiskAssessment: [...]
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Validation Checklist
|
|
153
|
+
|
|
154
|
+
Before writing either file, verify:
|
|
155
|
+
|
|
156
|
+
- ✓ No keys from consolidation.json appear in validation.json
|
|
157
|
+
- ✓ No keys from validation.json appear in consolidation.json
|
|
158
|
+
- ✓ All cross-module FK references are in consolidation.json (not validation.json)
|
|
159
|
+
- ✓ All semantic check results are in validation.json (not consolidation.json)
|
|
160
|
+
- ✓ All naming audit results are in validation.json (not consolidation.json)
|
|
161
|
+
- ✓ Client approval decision is in consolidation.json (not validation.json)
|
|
162
|
+
- ✓ Risk assessment is in validation.json (not consolidation.json)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Naming Audit Checks
|
|
2
|
+
|
|
3
|
+
> **Purpose:** Validate that all application names, module codes, entity names, and permission paths follow conventions,
|
|
4
|
+
> derive logically from their labels, and are free of collisions.
|
|
5
|
+
|
|
6
|
+
## Naming Registry Collection
|
|
7
|
+
|
|
8
|
+
Collect all names from the BA:
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
const namingRegistry = {
|
|
12
|
+
application: {
|
|
13
|
+
label: application_name,
|
|
14
|
+
code: applicationCode, // PascalCase
|
|
15
|
+
route: toKebabCase(applicationCode) // kebab-case
|
|
16
|
+
},
|
|
17
|
+
modules: completedModules.map(m => ({
|
|
18
|
+
label: m.name,
|
|
19
|
+
code: m.code, // PascalCase
|
|
20
|
+
route: toKebabCase(m.code) // kebab-case
|
|
21
|
+
})),
|
|
22
|
+
entities: completedModules.flatMap(m =>
|
|
23
|
+
m.entities.map(e => ({
|
|
24
|
+
name: e.name, // PascalCase (C# class name)
|
|
25
|
+
module: m.code,
|
|
26
|
+
tableName: e.tableName || pluralize(e.name) // Plural convention
|
|
27
|
+
}))
|
|
28
|
+
),
|
|
29
|
+
permissionRoots: [...new Set(
|
|
30
|
+
permissionPaths.map(p => p.path.split('.').slice(0, 2).join('.'))
|
|
31
|
+
)]
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Naming Recap Display
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
═══════════════════════════════════════════════════════════════
|
|
39
|
+
NAMING AUDIT — {application_name}
|
|
40
|
+
═══════════════════════════════════════════════════════════════
|
|
41
|
+
|
|
42
|
+
APPLICATION
|
|
43
|
+
| Label | Code (PascalCase) | Route (kebab-case) |
|
|
44
|
+
|-------|-------------------|--------------------|
|
|
45
|
+
| {application_name} | {applicationCode} | /{route} |
|
|
46
|
+
|
|
47
|
+
MODULES
|
|
48
|
+
| # | Label | Code (PascalCase) | Route (kebab-case) |
|
|
49
|
+
|---|-------|-------------------|--------------------|
|
|
50
|
+
{for each module: index | label | code | /app-route/module-route}
|
|
51
|
+
|
|
52
|
+
ENTITIES
|
|
53
|
+
| Entity (PascalCase) | Module | Table (plural) |
|
|
54
|
+
|----------------------|--------|----------------|
|
|
55
|
+
{for each entity: name | module | tableName}
|
|
56
|
+
|
|
57
|
+
PERMISSION ROOTS
|
|
58
|
+
{for each root: path}
|
|
59
|
+
═══════════════════════════════════════════════════════════════
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Coherence Checks
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const namingIssues = [];
|
|
66
|
+
|
|
67
|
+
// 1. Duplicate entity names across modules
|
|
68
|
+
const entityNames = namingRegistry.entities.map(e => e.name);
|
|
69
|
+
const duplicates = entityNames.filter((n, i) => entityNames.indexOf(n) !== i);
|
|
70
|
+
if (duplicates.length > 0) {
|
|
71
|
+
namingIssues.push({ severity: "ERROR", issue: `Duplicate entity names: ${[...new Set(duplicates)].join(', ')}` });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 2. Module code vs label coherence (code should derive logically from label)
|
|
75
|
+
for (const mod of namingRegistry.modules) {
|
|
76
|
+
if (!mod.code || mod.code.length < 2) {
|
|
77
|
+
namingIssues.push({ severity: "ERROR", issue: `Module "${mod.label}" has invalid code: "${mod.code}"` });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 3. Permission root alignment with module codes
|
|
82
|
+
for (const root of namingRegistry.permissionRoots) {
|
|
83
|
+
const [appSegment, moduleSegment] = root.split('.');
|
|
84
|
+
const matchingModule = namingRegistry.modules.find(m =>
|
|
85
|
+
m.code.toLowerCase() === moduleSegment.toLowerCase()
|
|
86
|
+
);
|
|
87
|
+
if (!matchingModule) {
|
|
88
|
+
namingIssues.push({ severity: "WARNING", issue: `Permission root "${root}" has no matching module code` });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 4. Route collision detection
|
|
93
|
+
const allRoutes = namingRegistry.modules.map(m =>
|
|
94
|
+
`/${namingRegistry.application.route}/${m.route}`
|
|
95
|
+
);
|
|
96
|
+
const routeDuplicates = allRoutes.filter((r, i) => allRoutes.indexOf(r) !== i);
|
|
97
|
+
if (routeDuplicates.length > 0) {
|
|
98
|
+
namingIssues.push({ severity: "ERROR", issue: `Route collisions: ${routeDuplicates.join(', ')}` });
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## MCP Validation
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
mcp__smartstack__validate_conventions({
|
|
106
|
+
checks: ["tables"],
|
|
107
|
+
context: {
|
|
108
|
+
applicationCode: applicationCode,
|
|
109
|
+
modules: namingRegistry.modules.map(m => m.code),
|
|
110
|
+
entities: namingRegistry.entities.map(e => e.name)
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
→ Merge MCP findings into namingIssues[]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## User Confirmation Flow
|
|
118
|
+
|
|
119
|
+
**IF namingIssues.length > 0:**
|
|
120
|
+
|
|
121
|
+
Display issues table:
|
|
122
|
+
```
|
|
123
|
+
| # | Severity | Issue |
|
|
124
|
+
|---|----------|-------|
|
|
125
|
+
{for each issue}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Ask via AskUserQuestion:
|
|
129
|
+
```
|
|
130
|
+
question: "{language == 'fr'
|
|
131
|
+
? 'Validez-vous les noms ci-dessus pour l\\'ensemble de l\\'application ?'
|
|
132
|
+
: 'Do you approve all the names above for the entire application?'}"
|
|
133
|
+
header: "Naming Audit"
|
|
134
|
+
options:
|
|
135
|
+
- label: "{language == 'fr' ? 'Approuvé' : 'Approved'}"
|
|
136
|
+
description: "{language == 'fr' ? 'Tous les noms sont corrects' : 'All names are correct'}"
|
|
137
|
+
- label: "{language == 'fr' ? 'Renommer certains éléments' : 'Rename some elements'}"
|
|
138
|
+
description: "{language == 'fr' ? 'Corriger des noms avant de finaliser' : 'Fix names before finalizing'}"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**IF "Renommer certains éléments":**
|
|
142
|
+
|
|
143
|
+
Ask via AskUserQuestion (open-ended):
|
|
144
|
+
```
|
|
145
|
+
question: "{language == 'fr'
|
|
146
|
+
? 'Quels éléments souhaitez-vous renommer ? (ex: \"Module Ventes → Commerce\", \"Entity Invoice → BillingDocument\")'
|
|
147
|
+
: 'Which elements do you want to rename? (e.g., \"Module Sales → Commerce\", \"Entity Invoice → BillingDocument\")'}"
|
|
148
|
+
header: "Renaming"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Process user response:
|
|
152
|
+
1. Parse rename instructions
|
|
153
|
+
2. Update `applicationCode`, module codes, entity names, permission paths accordingly in JSON files via ba-writer
|
|
154
|
+
3. Re-run coherence checks on updated names
|
|
155
|
+
4. Re-run MCP validation on updated names
|
|
156
|
+
5. Re-display the naming recap table for final confirmation
|
|
157
|
+
|
|
158
|
+
**IF "Approuvé":**
|
|
159
|
+
|
|
160
|
+
Store naming audit result in `validation.json`:
|
|
161
|
+
```javascript
|
|
162
|
+
ba-writer.enrichSection({
|
|
163
|
+
featureId: {feature_id},
|
|
164
|
+
section: "namingAudit",
|
|
165
|
+
data: {
|
|
166
|
+
auditedAt: now(),
|
|
167
|
+
issues: namingIssues,
|
|
168
|
+
approved: true,
|
|
169
|
+
renames: [] // or list of applied renames
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Continue to next section.
|