@atlashub/smartstack-cli 4.28.0 → 4.29.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/apex/references/frontend-route-wiring-app-tsx.md +29 -7
- package/templates/skills/apex/references/post-checks.md +42 -0
- package/templates/skills/apex/references/smartstack-frontend.md +23 -8
- package/templates/skills/apex/references/smartstack-layers.md +35 -19
- package/templates/skills/apex/steps/step-03-execute.md +10 -1
- package/templates/skills/apex/steps/step-04-examine.md +4 -0
- package/templates/skills/business-analyse/questionnaire/01-context.md +12 -12
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +45 -45
- package/templates/skills/business-analyse/questionnaire/03-data-ui.md +39 -39
- package/templates/skills/business-analyse/questionnaire/05-cross-module.md +32 -32
- package/templates/skills/business-analyse/questionnaire.md +11 -11
- package/templates/skills/business-analyse/steps/step-00-init.md +2 -2
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +3 -3
- package/templates/skills/business-analyse/steps/step-02-structure.md +2 -2
- package/templates/skills/business-analyse/steps/step-03-specify.md +15 -15
package/package.json
CHANGED
|
@@ -56,20 +56,42 @@ Read App.tsx and detect which pattern is used:
|
|
|
56
56
|
|
|
57
57
|
→ Add routes to `applicationRoutes.{application}[]` with **RELATIVE** paths (no leading `/`)
|
|
58
58
|
|
|
59
|
+
> **CRITICAL — Include Module Segment:** Paths are relative to `/{application}/`.
|
|
60
|
+
> For a 3-level hierarchy (app → module → sections), paths MUST be `{module_kebab}/{section_kebab}`.
|
|
61
|
+
> Using just `{section_kebab}` omits the module segment → route resolves to `/{app}/{section}` instead
|
|
62
|
+
> of `/{app}/{module}/{section}` → mismatch with backend navigation seed data → 404.
|
|
63
|
+
|
|
59
64
|
```tsx
|
|
60
65
|
const applicationRoutes: ApplicationRouteExtensions = {
|
|
61
66
|
'human-resources': [
|
|
62
67
|
// existing routes...
|
|
68
|
+
// Paths include module segment: employee-management/employees (NOT just employees)
|
|
63
69
|
{ path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
|
|
64
70
|
{ path: '{module_kebab}/{section_kebab}/create', element: <Create{EntityName}Page /> },
|
|
65
71
|
{ path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
|
|
66
|
-
{ path: '{module_kebab}/{section_kebab}/:id/edit', element: <
|
|
72
|
+
{ path: '{module_kebab}/{section_kebab}/:id/edit', element: <Edit{EntityName}Page /> },
|
|
67
73
|
|
|
68
74
|
// Parent redirect routes (MANDATORY — prevents /login redirect on parent navigation)
|
|
69
75
|
{ path: '{module_kebab}', element: <Navigate to="{module_kebab}/{first_section_kebab}" replace /> },
|
|
70
76
|
{ path: '', element: <Navigate to="{first_module_kebab}/{first_section_kebab}" replace /> },
|
|
71
77
|
],
|
|
72
78
|
};
|
|
79
|
+
|
|
80
|
+
// Concrete example: app=human-resources, module=employee-management, sections=employees,absences
|
|
81
|
+
const applicationRoutes: ApplicationRouteExtensions = {
|
|
82
|
+
'human-resources': [
|
|
83
|
+
{ path: 'employee-management/employees', element: <EmployeesPage /> }, // ✅
|
|
84
|
+
{ path: 'employee-management/employees/create', element: <CreateEmployeePage /> }, // ✅
|
|
85
|
+
{ path: 'employee-management/employees/:id', element: <EmployeeDetailPage /> }, // ✅
|
|
86
|
+
// ...absences...
|
|
87
|
+
{ path: 'employee-management', element: <Navigate to="employee-management/employees" replace /> },
|
|
88
|
+
{ path: '', element: <Navigate to="employee-management/employees" replace /> },
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// ❌ WRONG — missing module segment:
|
|
93
|
+
// { path: 'employees', ... } → resolves to /human-resources/employees (backend expects /human-resources/employee-management/employees)
|
|
94
|
+
```
|
|
73
95
|
```
|
|
74
96
|
|
|
75
97
|
Routes are automatically injected into BOTH standard (`/{application}/...`) and tenant-prefixed (`/t/:slug/{application}/...`) route trees by `mergeRoutes()`. No manual duplication needed.
|
|
@@ -162,10 +184,10 @@ For each application, add:
|
|
|
162
184
|
{ path: '{module}', element: <Navigate to="{module}/{first_section}" replace /> }
|
|
163
185
|
```
|
|
164
186
|
|
|
165
|
-
**Example:** For NavRoutes `human-resources.employees
|
|
187
|
+
**Example:** For NavRoutes `human-resources.employee-management.employees` and `human-resources.employee-management.absences`:
|
|
166
188
|
```tsx
|
|
167
|
-
{ path: '
|
|
168
|
-
{ path: '', element: <Navigate to="employees
|
|
189
|
+
{ path: 'employee-management', element: <Navigate to="employee-management/employees" replace /> },
|
|
190
|
+
{ path: '', element: <Navigate to="employee-management/employees" replace /> },
|
|
169
191
|
```
|
|
170
192
|
|
|
171
193
|
The `to` prop is resolved relative to the **parent route** (`/{application}`), so always use the full path from the application root.
|
|
@@ -186,12 +208,12 @@ The `to` prop is resolved relative to the **parent route** (`/{application}`), s
|
|
|
186
208
|
{ path: '/human-resources/employees/management', element: <EmployeePage /> },
|
|
187
209
|
];
|
|
188
210
|
```
|
|
189
|
-
Custom application routes go in `applicationRoutes` with RELATIVE paths:
|
|
211
|
+
Custom application routes go in `applicationRoutes` with RELATIVE paths (including module segment):
|
|
190
212
|
```tsx
|
|
191
|
-
// ✅ CORRECT
|
|
213
|
+
// ✅ CORRECT — module segment included
|
|
192
214
|
const applicationRoutes: ApplicationRouteExtensions = {
|
|
193
215
|
'human-resources': [
|
|
194
|
-
{ path: 'employees
|
|
216
|
+
{ path: 'employee-management/employees', element: <EmployeesPage /> },
|
|
195
217
|
],
|
|
196
218
|
};
|
|
197
219
|
```
|
|
@@ -1884,6 +1884,48 @@ if [ -n "$CTRL_FILES" ]; then
|
|
|
1884
1884
|
fi
|
|
1885
1885
|
```
|
|
1886
1886
|
|
|
1887
|
+
### POST-CHECK C52: Frontend route paths must include module segment (BLOCKING)
|
|
1888
|
+
|
|
1889
|
+
> **Source:** APEX regression — frontend routes used `employees` instead of `employee-management/employees`,
|
|
1890
|
+
> causing mismatch with backend navigation seed data routes (`/human-resources/employee-management/employees`).
|
|
1891
|
+
> Nav links produced 404 because React Router had no matching route for the full path.
|
|
1892
|
+
|
|
1893
|
+
```bash
|
|
1894
|
+
# Compare frontend route paths in App.tsx against backend navigation seed data routes
|
|
1895
|
+
APP_TSX=$(find . -path "*/src/App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
|
|
1896
|
+
if [ -n "$APP_TSX" ]; then
|
|
1897
|
+
# Extract all route paths from applicationRoutes
|
|
1898
|
+
ROUTE_PATHS=$(grep -oP "path:\s*'[^']+'" "$APP_TSX" | grep -v "^path: ''" | grep -v ":id" | grep -v "create" | grep -v "edit" | sed "s/path: '//;s/'//")
|
|
1899
|
+
|
|
1900
|
+
# Find navigation seed data files to get backend routes
|
|
1901
|
+
NAV_SEED_FILES=$(find src/ -name "*NavigationSeedData.cs" -o -name "*NavigationModuleSeedData.cs" 2>/dev/null)
|
|
1902
|
+
if [ -n "$NAV_SEED_FILES" ]; then
|
|
1903
|
+
# Extract module codes from seed data
|
|
1904
|
+
MODULE_CODES=$(grep -oP 'Code\s*=\s*"\K[^"]+' $NAV_SEED_FILES 2>/dev/null | sort -u)
|
|
1905
|
+
|
|
1906
|
+
for route in $ROUTE_PATHS; do
|
|
1907
|
+
# Skip redirect paths (empty or just module)
|
|
1908
|
+
if [ -z "$route" ]; then continue; fi
|
|
1909
|
+
|
|
1910
|
+
# Check if route contains a slash (module/section pattern)
|
|
1911
|
+
if ! echo "$route" | grep -q "/"; then
|
|
1912
|
+
# Single segment route — check if it matches a section code (not a module code)
|
|
1913
|
+
IS_MODULE=false
|
|
1914
|
+
for mod in $MODULE_CODES; do
|
|
1915
|
+
if [ "$route" = "$mod" ]; then IS_MODULE=true; break; fi
|
|
1916
|
+
done
|
|
1917
|
+
if [ "$IS_MODULE" = false ]; then
|
|
1918
|
+
echo "BLOCKING: Frontend route '$route' is missing module segment"
|
|
1919
|
+
echo " Expected: '{module}/{route}' (e.g., 'employee-management/$route')"
|
|
1920
|
+
echo " Backend navigation seed data defines routes with full hierarchy: /app/module/section"
|
|
1921
|
+
echo " Frontend routes must match: module/section (relative to app root)"
|
|
1922
|
+
fi
|
|
1923
|
+
fi
|
|
1924
|
+
done
|
|
1925
|
+
fi
|
|
1926
|
+
fi
|
|
1927
|
+
```
|
|
1928
|
+
|
|
1887
1929
|
---
|
|
1888
1930
|
|
|
1889
1931
|
## Architecture — Clean Architecture Layer Isolation
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
16
|
// Named exports — use .then() to wrap
|
|
17
|
+
// Path: @/pages/{App}/{Module}/{Section}/{Page}
|
|
17
18
|
const EmployeesPage = lazy(() =>
|
|
18
|
-
import('@/pages/HumanResources/Employees/EmployeesPage')
|
|
19
|
+
import('@/pages/HumanResources/EmployeeManagement/Employees/EmployeesPage')
|
|
19
20
|
.then(m => ({ default: m.EmployeesPage }))
|
|
20
21
|
);
|
|
21
22
|
|
|
@@ -49,7 +50,7 @@ element: (
|
|
|
49
50
|
**Incorrect patterns:**
|
|
50
51
|
```tsx
|
|
51
52
|
// WRONG: static import in route file
|
|
52
|
-
import { EmployeesPage } from '@/pages/HumanResources/Employees/EmployeesPage';
|
|
53
|
+
import { EmployeesPage } from '@/pages/HumanResources/EmployeeManagement/Employees/EmployeesPage';
|
|
53
54
|
|
|
54
55
|
// WRONG: no Suspense wrapper
|
|
55
56
|
element: <EmployeesPage />
|
|
@@ -64,8 +65,9 @@ In the client `App.tsx` (where application routes are defined), all page imports
|
|
|
64
65
|
|
|
65
66
|
**Correct — Lazy imports in client App.tsx:**
|
|
66
67
|
```tsx
|
|
68
|
+
// Path includes module level: {App}/{Module}/{Section}/{Page}
|
|
67
69
|
const ClientsListPage = lazy(() =>
|
|
68
|
-
import('@/pages/HumanResources/Clients/ClientsListPage')
|
|
70
|
+
import('@/pages/HumanResources/ClientManagement/Clients/ClientsListPage')
|
|
69
71
|
.then(m => ({ default: m.ClientsListPage }))
|
|
70
72
|
);
|
|
71
73
|
```
|
|
@@ -73,7 +75,7 @@ const ClientsListPage = lazy(() =>
|
|
|
73
75
|
**Do not use — Static imports in client App.tsx:**
|
|
74
76
|
```tsx
|
|
75
77
|
// WRONG: Static import kills code splitting
|
|
76
|
-
import { ClientsListPage } from '@/pages/HumanResources/Clients/ClientsListPage';
|
|
78
|
+
import { ClientsListPage } from '@/pages/HumanResources/ClientManagement/Clients/ClientsListPage';
|
|
77
79
|
```
|
|
78
80
|
|
|
79
81
|
> **Note:** The `smartstackRoutes.tsx` from the npm package may use static imports internally — this is acceptable for the package. But client `App.tsx` code MUST always use lazy imports for business pages.
|
|
@@ -698,18 +700,19 @@ export function EntityEditPage() {
|
|
|
698
700
|
|
|
699
701
|
```tsx
|
|
700
702
|
// In route files — form pages are also lazy-loaded
|
|
703
|
+
// Path: @/pages/{App}/{Module}/{Section}/{Page}
|
|
701
704
|
const EntityCreatePage = lazy(() =>
|
|
702
|
-
import('@/pages/HumanResources/Employees/EntityCreatePage')
|
|
705
|
+
import('@/pages/HumanResources/EmployeeManagement/Employees/EntityCreatePage')
|
|
703
706
|
.then(m => ({ default: m.EntityCreatePage }))
|
|
704
707
|
);
|
|
705
708
|
const EntityEditPage = lazy(() =>
|
|
706
|
-
import('@/pages/HumanResources/Employees/EntityEditPage')
|
|
709
|
+
import('@/pages/HumanResources/EmployeeManagement/Employees/EntityEditPage')
|
|
707
710
|
.then(m => ({ default: m.EntityEditPage }))
|
|
708
711
|
);
|
|
709
712
|
|
|
710
|
-
// Route registration —
|
|
713
|
+
// Route registration — Pattern B (JSX nested children):
|
|
711
714
|
{
|
|
712
|
-
path: 'employees',
|
|
715
|
+
path: 'employee-management/employees',
|
|
713
716
|
children: [
|
|
714
717
|
{ index: true, element: <Suspense fallback={<PageLoader />}><EmployeesPage /></Suspense> },
|
|
715
718
|
{ path: 'create', element: <Suspense fallback={<PageLoader />}><EntityCreatePage /></Suspense> },
|
|
@@ -718,6 +721,18 @@ const EntityEditPage = lazy(() =>
|
|
|
718
721
|
]
|
|
719
722
|
}
|
|
720
723
|
|
|
724
|
+
// Route registration — Pattern A (applicationRoutes flat paths):
|
|
725
|
+
// CRITICAL: paths are RELATIVE to /{app}/ and MUST include the module segment
|
|
726
|
+
const applicationRoutes: ApplicationRouteExtensions = {
|
|
727
|
+
'human-resources': [
|
|
728
|
+
{ path: 'employee-management/employees', element: <EmployeesPage /> }, // ✅ includes module
|
|
729
|
+
{ path: 'employee-management/employees/create', element: <CreateEmployeePage /> }, // ✅
|
|
730
|
+
{ path: 'employee-management/employees/:id', element: <EmployeeDetailPage /> }, // ✅
|
|
731
|
+
{ path: 'employee-management/employees/:id/edit', element: <EditEmployeePage /> }, // ✅
|
|
732
|
+
// ❌ WRONG: { path: 'employees', ... } — missing module segment → 404 on nav click
|
|
733
|
+
],
|
|
734
|
+
};
|
|
735
|
+
|
|
721
736
|
// Section-level routes — children of the module route (when module has sections)
|
|
722
737
|
//
|
|
723
738
|
// > **IMPORTANT:** The `list` and `detail` sections do NOT generate additional route entries.
|
|
@@ -315,39 +315,55 @@ const [loading, setLoading] = useState(true);
|
|
|
315
315
|
|
|
316
316
|
**Order (MANDATORY):**
|
|
317
317
|
|
|
318
|
-
1. Index/list route (path: `'
|
|
319
|
-
2. Create route (`'{section}/create'`)
|
|
320
|
-
3. Static sections (`'{
|
|
321
|
-
4. Dynamic routes (`'{section}/:id'`, `'{section}/:id/edit'`)
|
|
322
|
-
5.
|
|
318
|
+
1. Index/list route (path: `'{module}/{section}'`)
|
|
319
|
+
2. Create route (`'{module}/{section}/create'`)
|
|
320
|
+
3. Static sections (`'{module}/{section}/dashboard'`, etc.)
|
|
321
|
+
4. Dynamic routes (`'{module}/{section}/:id'`, `'{module}/{section}/:id/edit'`)
|
|
322
|
+
5. Module redirect (`'{module}'` → `'{module}/{first_section}'`)
|
|
323
|
+
6. Application redirect (`''` → `'{first_module}/{first_section}'`) — ALWAYS LAST
|
|
323
324
|
|
|
324
325
|
```tsx
|
|
325
|
-
// ✅ CORRECT — static before dynamic
|
|
326
|
+
// ✅ CORRECT — module segment included, static before dynamic
|
|
327
|
+
// (inside applicationRoutes['human-resources'], paths are relative to /human-resources/)
|
|
328
|
+
{ path: 'employee-management/employees', element: <EmployeesPage /> },
|
|
329
|
+
{ path: 'employee-management/employees/create', element: <CreateEmployeePage /> },
|
|
330
|
+
{ path: 'employee-management/employees/dashboard', element: <EmployeeDashboardPage /> },
|
|
331
|
+
{ path: 'employee-management/employees/:id', element: <EmployeeDetailPage /> },
|
|
332
|
+
{ path: 'employee-management/employees/:id/edit', element: <EditEmployeePage /> },
|
|
333
|
+
{ path: 'employee-management', element: <Navigate to="employee-management/employees" replace /> },
|
|
334
|
+
{ path: '', element: <Navigate to="employee-management/employees" replace /> },
|
|
335
|
+
|
|
336
|
+
// ❌ WRONG — missing module segment (resolves to /human-resources/employees instead of /human-resources/employee-management/employees)
|
|
326
337
|
{ path: 'employees', element: <EmployeesPage /> },
|
|
327
|
-
{ path: 'employees/create', element: <CreateEmployeePage /> },
|
|
328
|
-
{ path: 'employees/dashboard', element: <EmployeeDashboardPage /> },
|
|
329
|
-
{ path: 'employees/:id', element: <EmployeeDetailPage /> },
|
|
330
|
-
{ path: 'employees/:id/edit', element: <EditEmployeePage /> },
|
|
331
|
-
{ path: '', element: <Navigate to="employees" replace /> },
|
|
332
338
|
|
|
333
339
|
// ❌ WRONG — :id before dashboard → dashboard is unreachable (matched as id="dashboard")
|
|
334
|
-
{ path: 'employees/:id', element: <EmployeeDetailPage /> },
|
|
335
|
-
{ path: 'employees/dashboard', element: <EmployeeDashboardPage /> }, // NEVER REACHED
|
|
340
|
+
{ path: 'employee-management/employees/:id', element: <EmployeeDetailPage /> },
|
|
341
|
+
{ path: 'employee-management/employees/dashboard', element: <EmployeeDashboardPage /> }, // NEVER REACHED
|
|
336
342
|
```
|
|
337
343
|
|
|
338
344
|
POST-CHECK C49 detects this anti-pattern and BLOCKS.
|
|
339
345
|
|
|
340
346
|
### Section Routes (when module has sections)
|
|
341
347
|
|
|
342
|
-
If the module defines `{sections}`, generate frontend routes for EACH section as children of the
|
|
348
|
+
If the module defines `{sections}`, generate frontend routes for EACH section as children of the application route.
|
|
349
|
+
|
|
350
|
+
> **CRITICAL — Module Segment Required:** Route paths in `applicationRoutes['{app}']` are RELATIVE to the application root.
|
|
351
|
+
> They MUST include the module segment: `{module-kebab}/{section-kebab}`, NOT just `{section-kebab}`.
|
|
352
|
+
> Without the module segment, the route resolves to `/{app}/{section}` instead of `/{app}/{module}/{section}`,
|
|
353
|
+
> causing a mismatch with backend navigation seed data routes → nav links produce 404s.
|
|
343
354
|
|
|
344
355
|
```tsx
|
|
345
|
-
//
|
|
356
|
+
// Routes in applicationRoutes['human-resources'] — RELATIVE paths include module segment
|
|
346
357
|
// IMPORTANT: static routes BEFORE dynamic routes (see Route Ordering rule above)
|
|
347
|
-
|
|
348
|
-
{ path: '{section-kebab}
|
|
349
|
-
{ path: '{section-kebab}
|
|
350
|
-
{ path: '{section-kebab}/:id
|
|
358
|
+
// Example: app=human-resources, module=employee-management, section=employees
|
|
359
|
+
{ path: '{module-kebab}/{section-kebab}', element: <Suspense fallback={<PageLoader />}><{Section}Page /></Suspense> },
|
|
360
|
+
{ path: '{module-kebab}/{section-kebab}/create', element: <Suspense fallback={<PageLoader />}><Create{Section}Page /></Suspense> },
|
|
361
|
+
{ path: '{module-kebab}/{section-kebab}/:id', element: <Suspense fallback={<PageLoader />}><{Section}DetailPage /></Suspense> },
|
|
362
|
+
{ path: '{module-kebab}/{section-kebab}/:id/edit', element: <Suspense fallback={<PageLoader />}><Edit{Section}Page /></Suspense> },
|
|
363
|
+
|
|
364
|
+
// Concrete example:
|
|
365
|
+
// { path: 'employee-management/employees', element: ... }, → /human-resources/employee-management/employees ✅
|
|
366
|
+
// { path: 'employees', element: ... }, → /human-resources/employees ❌ WRONG (missing module)
|
|
351
367
|
```
|
|
352
368
|
|
|
353
369
|
Section pages live in `src/pages/{AppPascal}/{Module}/{Section}/`.
|
|
@@ -427,6 +427,11 @@ For each module:
|
|
|
427
427
|
→ Read App.tsx and detect the routing pattern
|
|
428
428
|
→ Pattern A (`applicationRoutes: ApplicationRouteExtensions`): add routes to `applicationRoutes['{application_kebab}'][]` with RELATIVE paths
|
|
429
429
|
→ Pattern B (JSX `<Route>`): nest routes inside `<Route path="/{application}" element={<AppLayout />}>` + duplicate in tenant block
|
|
430
|
+
→ **CRITICAL — Module Segment Required:** Route paths MUST include the module segment.
|
|
431
|
+
For a 3-level hierarchy (app → module → sections), paths are `{module_kebab}/{section_kebab}`.
|
|
432
|
+
Example: `employee-management/employees` NOT just `employees`.
|
|
433
|
+
Without the module segment, routes resolve to `/{app}/{section}` instead of `/{app}/{module}/{section}`,
|
|
434
|
+
causing mismatch with backend navigation seed data → nav links produce 404s.
|
|
430
435
|
→ **BEFORE wiring:** Verify route ordering — static routes (`create`, `dashboard`, `departments`) MUST come BEFORE dynamic routes (`:id`, `:id/edit`). Redirect routes (`Navigate`) MUST be LAST. See `references/smartstack-layers.md` "RULE — Frontend Route Ordering".
|
|
431
436
|
→ Do not add business routes to `clientRoutes[]` — it is only for non-app routes (`/about`, `/pricing`)
|
|
432
437
|
→ All business applications use `<AppLayout />` as layout wrapper
|
|
@@ -482,7 +487,9 @@ For each module:
|
|
|
482
487
|
5. Verify: `grep -q "{module_namespace}" src/**/i18n/config.ts` → must match
|
|
483
488
|
- Permissions: Call MCP generate_permissions for the module permission root (2 segments: {app}.{module}),
|
|
484
489
|
then also call MCP generate_permissions for each section (3 segments: {app}.{module}.{section}).
|
|
485
|
-
- Section routes: Add section child routes to
|
|
490
|
+
- Section routes: Add section child routes to `applicationRoutes['{app_kebab}']`.
|
|
491
|
+
Route paths MUST include the module segment: `{module_kebab}/{section_kebab}` (e.g., `employee-management/employees`).
|
|
492
|
+
Do NOT use just `{section_kebab}` (e.g., `employees`) — this omits the module level and causes 404s.
|
|
486
493
|
Wire PermissionGuard for section routes with section-level permissions.
|
|
487
494
|
- MUST use src/pages/{App}/{Module}/ hierarchy (NOT flat)
|
|
488
495
|
|
|
@@ -519,6 +526,7 @@ IF NOT economy_mode AND entities.length > 1:
|
|
|
519
526
|
- API client: MCP scaffold_api_client
|
|
520
527
|
- Routes: MCP scaffold_routes (outputFormat: "applicationRoutes", dryRun: false) → MUST generate navRoutes.generated.ts
|
|
521
528
|
- Wire Routes to App.tsx (BLOCKING): detect Pattern A/B, wire accordingly
|
|
529
|
+
→ CRITICAL: Route paths MUST include module segment: {module_kebab}/{section_kebab} (e.g., employee-management/employees, NOT just employees)
|
|
522
530
|
→ See references/frontend-route-wiring-app-tsx.md for full patterns
|
|
523
531
|
→ Verify: mcp__smartstack__validate_frontend_routes (scope: "routes")
|
|
524
532
|
- Pages: /ui-components skill (ALL 4 types: List, Detail, Create, Edit)
|
|
@@ -539,6 +547,7 @@ ELSE:
|
|
|
539
547
|
1. MCP scaffold_api_client
|
|
540
548
|
2. MCP scaffold_routes (outputFormat: 'applicationRoutes')
|
|
541
549
|
3. Wire routes to App.tsx (Pattern A/B — see references/frontend-route-wiring-app-tsx.md)
|
|
550
|
+
CRITICAL: paths MUST include module segment: {module_kebab}/{section_kebab} (e.g., employee-management/employees)
|
|
542
551
|
4. **INVOKE Skill("ui-components")** — pass entity context:
|
|
543
552
|
- Entity: {EntityName}, Module: {ModuleName}, App: {AppName}
|
|
544
553
|
- Page types: List, Detail, Create, Edit (+ Dashboard if applicable)
|
|
@@ -65,6 +65,9 @@ Verify:
|
|
|
65
65
|
- Routes nested inside correct Layout wrapper
|
|
66
66
|
- Route paths match controller patterns
|
|
67
67
|
- No orphan routes
|
|
68
|
+
- Route paths include module segment (e.g., 'employee-management/employees', NOT just 'employees')
|
|
69
|
+
→ Compare frontend route paths in App.tsx against backend NavigationSeedData routes
|
|
70
|
+
→ If backend defines route /app/module/section, frontend must use module/section (relative)
|
|
68
71
|
```
|
|
69
72
|
|
|
70
73
|
### 3b. Frontend Page Completeness
|
|
@@ -196,6 +199,7 @@ AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
|
|
|
196
199
|
| I18n registration | Namespaces registered in i18n config (POST-CHECK C39) | PASS / N/A |
|
|
197
200
|
| Validators DI | FluentValidation registered in DI (POST-CHECK C40) | PASS / N/A |
|
|
198
201
|
| Route/NavRoute conflict | No [Route] alongside [NavRoute] on controllers (POST-CHECK C43) | PASS / N/A |
|
|
202
|
+
| Route module segment | Frontend routes include module segment matching seed data (POST-CHECK C52) | PASS / N/A |
|
|
199
203
|
| Role-permission matrix | Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R (POST-CHECK C44) | PASS / N/A |
|
|
200
204
|
| PermissionAction enum | No Enum.Parse, only typed enum values 0-10 (POST-CHECK C45) | PASS / N/A |
|
|
201
205
|
| Navigation translations | 4 langs per level, section/resource translations present (POST-CHECK C46) | PASS / N/A |
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Catégorie 1 : Contexte métier
|
|
2
2
|
|
|
3
|
-
> **Usage :** Questions fondamentales pour comprendre le besoin
|
|
3
|
+
> **Usage :** Questions fondamentales pour comprendre le besoin métier
|
|
4
4
|
> **Quand charger :** TOUJOURS (noyau)
|
|
5
|
-
> **Objectif :** Comprendre le processus
|
|
5
|
+
> **Objectif :** Comprendre le processus métier, les frictions, et la vision cible
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## 1.1 Le processus
|
|
9
|
+
## 1.1 Le processus métier
|
|
10
10
|
|
|
11
|
-
| # | Question | Type de
|
|
11
|
+
| # | Question | Type de réponse |
|
|
12
12
|
|---|----------|-----------------|
|
|
13
|
-
| Q1.1 |
|
|
13
|
+
| Q1.1 | Décrivez en quelques phrases le processus métier que cette application doit gérer. Qu'est-ce qui se passe, qui intervient, et quel est le résultat attendu ? | Texte libre |
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
## 1.2 Les points de friction
|
|
18
18
|
|
|
19
|
-
| # | Question | Type de
|
|
19
|
+
| # | Question | Type de réponse |
|
|
20
20
|
|---|----------|-----------------|
|
|
21
|
-
| Q1.4 | Quels sont les points de friction actuels ? Qu'est-ce qui bloque, ralentit, ou
|
|
21
|
+
| Q1.4 | Quels sont les points de friction actuels ? Qu'est-ce qui bloque, ralentit, ou génère des erreurs dans ce processus ? | Description des frictions |
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
-
## 1.3 La vision
|
|
25
|
+
## 1.3 La vision souhaitée
|
|
26
26
|
|
|
27
|
-
| # | Question | Type de
|
|
27
|
+
| # | Question | Type de réponse |
|
|
28
28
|
|---|----------|-----------------|
|
|
29
|
-
| Q1.8 | Qu'est-ce qui doit changer ? Si le
|
|
29
|
+
| Q1.8 | Qu'est-ce qui doit changer ? Si le problème était résolu demain, que feriez-vous différemment dans votre journée de travail ? | Description du changement concret |
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
## Mapping vers le cadrage
|
|
34
34
|
|
|
35
|
-
|
|
|
35
|
+
| Réponse | Alimente |
|
|
36
36
|
|---------|----------|
|
|
37
37
|
| Q1.1 | `cadrage.problem` |
|
|
38
38
|
| Q1.4 | `cadrage.asIs` |
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Catégorie 2 : Parties prenantes et périmètre
|
|
2
2
|
|
|
3
|
-
> **Usage :** Identifier les profils utilisateurs, leurs droits, et
|
|
3
|
+
> **Usage :** Identifier les profils utilisateurs, leurs droits, et délimiter le périmètre fonctionnel
|
|
4
4
|
> **Quand charger :** TOUJOURS (noyau)
|
|
5
|
-
> **Objectif :** Comprendre QUI utilise le
|
|
5
|
+
> **Objectif :** Comprendre QUI utilise le système, avec quels DROITS, et QUOI il doit faire
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## 2.1 Identification des utilisateurs
|
|
10
10
|
|
|
11
|
-
> **But :** Identifier les types de profils/
|
|
11
|
+
> **But :** Identifier les types de profils/rôles qui interagiront avec le système.
|
|
12
12
|
|
|
13
|
-
| # | Question | Type de
|
|
13
|
+
| # | Question | Type de réponse |
|
|
14
14
|
|---|----------|-----------------|
|
|
15
|
-
| Q2.1 | Qui sont les types de profils qui utiliseront ce
|
|
15
|
+
| Q2.1 | Qui sont les types de profils qui utiliseront ce système ? Décrivez leurs rôles et ce qu'ils font. | Liste de profils utilisateurs |
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
## 2.2
|
|
19
|
+
## 2.2 Tâches par profil
|
|
20
20
|
|
|
21
|
-
> **But :** Comprendre
|
|
21
|
+
> **But :** Comprendre concrètement ce que chaque type d'utilisateur fait.
|
|
22
22
|
|
|
23
|
-
| # | Question | Type de
|
|
23
|
+
| # | Question | Type de réponse |
|
|
24
24
|
|---|----------|-----------------|
|
|
25
|
-
| Q2.5 | Pour chaque type d'utilisateur : quelles sont les 3
|
|
25
|
+
| Q2.5 | Pour chaque type d'utilisateur : quelles sont les 3 à 5 tâches principales qu'il doit accomplir avec ce système ? | Tâches par profil utilisateur |
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## 2.3 Les niveaux d'
|
|
29
|
+
## 2.3 Les niveaux d'accès
|
|
30
30
|
|
|
31
|
-
> **But :**
|
|
31
|
+
> **But :** Définir qui peut voir quoi et faire quoi.
|
|
32
32
|
|
|
33
|
-
| # | Question | Type de
|
|
33
|
+
| # | Question | Type de réponse |
|
|
34
34
|
|---|----------|-----------------|
|
|
35
|
-
| Q2.9 | Tous les utilisateurs doivent-ils voir les
|
|
36
|
-
| Q2.10 | Qui a le droit de modifier ou supprimer des informations ? Tout le monde ou seulement certaines personnes ? |
|
|
37
|
-
| Q2.11 | Y a-t-il des actions sensibles qui
|
|
35
|
+
| Q2.9 | Tous les utilisateurs doivent-ils voir les mêmes informations ? Si non, qui voit quoi ? | Règles de visibilité des données |
|
|
36
|
+
| Q2.10 | Qui a le droit de modifier ou supprimer des informations ? Tout le monde ou seulement certaines personnes ? | Règles de modification |
|
|
37
|
+
| Q2.11 | Y a-t-il des actions sensibles qui nécessitent une validation par un supérieur ? | Liste des actions à valider |
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
## 2.4
|
|
41
|
+
## 2.4 Périmètre fonctionnel
|
|
42
42
|
|
|
43
|
-
> **But :** Lister tout ce que le
|
|
43
|
+
> **But :** Lister tout ce que le système doit faire et ne pas faire, avec des priorités claires.
|
|
44
44
|
|
|
45
|
-
| # | Question | Type de
|
|
45
|
+
| # | Question | Type de réponse |
|
|
46
46
|
|---|----------|-----------------|
|
|
47
|
-
| Q2.12 | Listez toutes les
|
|
48
|
-
| Q2.13 | Parmi cette liste, quelles sont les
|
|
49
|
-
| Q2.15 | Y a-t-il des choses que le
|
|
47
|
+
| Q2.12 | Listez toutes les fonctionnalités que vous souhaitez dans ce système. Ne vous censurez pas. | Liste libre de fonctionnalités |
|
|
48
|
+
| Q2.13 | Parmi cette liste, quelles sont les fonctionnalités INDISPENSABLES ? Celles sans lesquelles le système n'a aucun intérêt ? | Liste de fonctionnalités vitales |
|
|
49
|
+
| Q2.15 | Y a-t-il des choses que le système ne doit explicitement PAS faire ? Des limites claires à poser ? | Liste d'exclusions |
|
|
50
50
|
|
|
51
|
-
**Test de
|
|
52
|
-
> Pour chaque
|
|
53
|
-
> "Si on enlevait cette
|
|
51
|
+
**Test de priorité :**
|
|
52
|
+
> Pour chaque fonctionnalité classée comme indispensable, poser la question :
|
|
53
|
+
> "Si on enlevait cette fonctionnalité, le système aurait-il encore de la valeur ?"
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
@@ -58,42 +58,42 @@
|
|
|
58
58
|
|
|
59
59
|
> **But :** Comprendre le flux de travail principal de bout en bout.
|
|
60
60
|
|
|
61
|
-
| # | Question | Type de
|
|
61
|
+
| # | Question | Type de réponse |
|
|
62
62
|
|---|----------|-----------------|
|
|
63
|
-
| Q2.16 |
|
|
64
|
-
| Q2.17 |
|
|
65
|
-
| Q2.18 | Que se passe-t-il quand quelque chose ne se
|
|
63
|
+
| Q2.16 | Décrivez le parcours typique d'un utilisateur du début à la fin : il ouvre le système, que fait-il en premier ? | Liste d'étapes ordonnées |
|
|
64
|
+
| Q2.17 | À quels moments l'utilisateur doit-il prendre une décision ? Quelles sont les options possibles ? | Points de décision et options |
|
|
65
|
+
| Q2.18 | Que se passe-t-il quand quelque chose ne se déroule pas comme prévu ? Quels sont les cas particuliers ? | Scénarios alternatifs |
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
69
|
-
## Guide d'
|
|
69
|
+
## Guide d'élicitation approfondi
|
|
70
70
|
|
|
71
71
|
### Techniques de relance
|
|
72
72
|
|
|
73
|
-
| Question | Si la
|
|
73
|
+
| Question | Si la réponse est vague | Relance recommandée |
|
|
74
74
|
|----------|------------------------|---------------------|
|
|
75
|
-
| Q2.1 (utilisateurs) | Un seul type
|
|
76
|
-
| Q2.5 (
|
|
77
|
-
| Q2.9 (
|
|
78
|
-
| Q2.13 (indispensable) | Tout est indispensable | "Si vous ne pouviez garder que 3
|
|
79
|
-
| Q2.15 (exclusions) | "Je ne vois pas" | "Certains utilisateurs pourraient-ils s'attendre
|
|
80
|
-
| Q2.16 (parcours) | Moins de 3
|
|
75
|
+
| Q2.1 (utilisateurs) | Un seul type mentionné | "Pensez aux différents moments de la journée : qui saisit ? Qui consulte les rapports ? Qui gère les cas particuliers ?" |
|
|
76
|
+
| Q2.5 (tâches) | Tâches génériques | "Quand il arrive le matin et ouvre le système, quelle est sa première action ?" |
|
|
77
|
+
| Q2.9 (visibilité) | Réponse ambiguë | "Un employé du service A peut-il voir les données du service B ? Un stagiaire voit-il la même chose qu'un directeur ?" |
|
|
78
|
+
| Q2.13 (indispensable) | Tout est indispensable | "Si vous ne pouviez garder que 3 fonctionnalités pour un premier lancement, lesquelles ?" |
|
|
79
|
+
| Q2.15 (exclusions) | "Je ne vois pas" | "Certains utilisateurs pourraient-ils s'attendre à des fonctionnalités que vous ne souhaitez PAS inclure ?" |
|
|
80
|
+
| Q2.16 (parcours) | Moins de 3 étapes | "Détaillons : l'utilisateur arrive sur l'écran d'accueil. Que voit-il ? Où clique-t-il ?" |
|
|
81
81
|
|
|
82
|
-
### Signaux d'alerte
|
|
82
|
+
### Signaux d'alerte à détecter
|
|
83
83
|
|
|
84
|
-
| Signal du client |
|
|
84
|
+
| Signal du client | Problème sous-jacent | Action de l'analyste |
|
|
85
85
|
|------------------|---------------------|----------------------|
|
|
86
|
-
| "Tous les utilisateurs font la
|
|
87
|
-
| "Tout le monde doit tout voir" |
|
|
88
|
-
| Tout est indispensable (> 10 vitaux) |
|
|
89
|
-
| Aucune exclusion
|
|
90
|
-
| Parcours
|
|
86
|
+
| "Tous les utilisateurs font la même chose" | Rôles non différenciés | "Qui peut supprimer ? Qui ne fait que consulter ? Qui valide ?" |
|
|
87
|
+
| "Tout le monde doit tout voir" | Sécurité non réfléchie | "Même les stagiaires ? Les prestataires externes ? Les données salariales ?" |
|
|
88
|
+
| Tout est indispensable (> 10 vitaux) | Priorités non définies | Appliquer le test de priorité |
|
|
89
|
+
| Aucune exclusion identifiée | Périmètre non borné | "Y a-t-il des aspects qui relèvent d'un autre projet ou d'une version future ?" |
|
|
90
|
+
| Parcours linéaire sans alternative | Seul le cas idéal est décrit | "Que se passe-t-il à l'étape X si la condition Y n'est pas remplie ?" |
|
|
91
91
|
|
|
92
92
|
---
|
|
93
93
|
|
|
94
94
|
## Mapping vers le cadrage
|
|
95
95
|
|
|
96
|
-
|
|
|
96
|
+
| Réponse | Alimente |
|
|
97
97
|
|---------|----------|
|
|
98
98
|
| Q2.1, Q2.5 | `cadrage.stakeholders[]` |
|
|
99
99
|
| Q2.9-Q2.11 | `cadrage.applicationRoles[]` |
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Catégorie 3 : Données et interface
|
|
2
2
|
|
|
3
|
-
> **Usage :**
|
|
4
|
-
> **Quand charger :** Par module, lors de la
|
|
5
|
-
> **Objectif :** Comprendre les
|
|
3
|
+
> **Usage :** Définir les entités, les règles de données et l'expérience utilisateur
|
|
4
|
+
> **Quand charger :** Par module, lors de la spécification (step-03)
|
|
5
|
+
> **Objectif :** Comprendre les données manipulées et comment elles sont présentées
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -10,69 +10,69 @@
|
|
|
10
10
|
|
|
11
11
|
| # | Question | Type de reponse |
|
|
12
12
|
|---|----------|-----------------|
|
|
13
|
-
| Q3.1 | Quelles sont les
|
|
14
|
-
| Q3.2 | Pour chaque
|
|
15
|
-
| Q3.3 | Quelles relations existent entre les
|
|
16
|
-
| Q3.5 | Pour chaque
|
|
17
|
-
| Q3.6 | Si auto-
|
|
13
|
+
| Q3.1 | Quelles sont les entités principales gérées par ce module ? | Liste d'entités |
|
|
14
|
+
| Q3.2 | Pour chaque entité : quels sont les attributs importants ? | Par entité |
|
|
15
|
+
| Q3.3 | Quelles relations existent entre les entités ? (appartient à, contient, référence) | Schéma relationnel |
|
|
16
|
+
| Q3.5 | Pour chaque entité : le Code doit-il être auto-généré ou saisi par l'utilisateur ? | Par entité |
|
|
17
|
+
| Q3.6 | Si auto-généré : quelle stratégie ? (séquentiel, timestamp, année, UUID court) | Par entité |
|
|
18
18
|
|
|
19
|
-
## 3.2
|
|
19
|
+
## 3.2 Règles de données
|
|
20
20
|
|
|
21
|
-
| # | Question | Type de
|
|
21
|
+
| # | Question | Type de réponse |
|
|
22
22
|
|---|----------|-----------------|
|
|
23
|
-
| Q3.7 | Quelles validations sur les
|
|
24
|
-
| Q3.8 | Y a-t-il des
|
|
25
|
-
| Q3.9 |
|
|
23
|
+
| Q3.7 | Quelles validations sur les données ? (champs obligatoires, formats, plages de valeurs) | Liste de règles |
|
|
24
|
+
| Q3.8 | Y a-t-il des règles inter-champs ? (date fin > date début, montant selon statut) | Liste de contraintes |
|
|
25
|
+
| Q3.9 | Données sensibles à protéger ? (données personnelles, financières, médicales) | Liste + niveau |
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## 3.3 Interface et
|
|
29
|
+
## 3.3 Interface et écrans
|
|
30
30
|
|
|
31
|
-
| # | Question | Type de
|
|
31
|
+
| # | Question | Type de réponse |
|
|
32
32
|
|---|----------|-----------------|
|
|
33
|
-
| Q3.10 |
|
|
34
|
-
| Q3.11 |
|
|
35
|
-
| Q3.12 | Informations
|
|
36
|
-
| Q3.13 | Actions possibles par
|
|
33
|
+
| Q3.10 | Périphériques cibles ? (desktop, mobile, tablette) | Liste |
|
|
34
|
+
| Q3.11 | Écrans principaux nécessaires pour ce module ? | Liste d'écrans |
|
|
35
|
+
| Q3.12 | Informations clés par écran ? Quelles colonnes dans la liste, quels champs dans le formulaire ? | Par écran |
|
|
36
|
+
| Q3.13 | Actions possibles par écran ? (créer, éditer, supprimer, valider, exporter, changer statut) | Par écran |
|
|
37
37
|
|
|
38
38
|
## 3.4 Tableaux de bord
|
|
39
39
|
|
|
40
|
-
| # | Question | Type de
|
|
40
|
+
| # | Question | Type de réponse |
|
|
41
41
|
|---|----------|-----------------|
|
|
42
42
|
| Q3.14 | Des tableaux de bord ou indicateurs sont-ils requis pour ce module ? | Oui/Non + description |
|
|
43
|
-
| Q3.15 | KPIs
|
|
44
|
-
| Q3.16 | Types de graphiques
|
|
43
|
+
| Q3.15 | KPIs à afficher ? (nom, métrique, format, seuils d'alerte) | Par dashboard |
|
|
44
|
+
| Q3.16 | Types de graphiques souhaités ? (barres, lignes, camembert, cartes KPI) | Par KPI |
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
## Guide d'
|
|
48
|
+
## Guide d'élicitation approfondi
|
|
49
49
|
|
|
50
50
|
### Techniques de relance
|
|
51
51
|
|
|
52
|
-
| Question | Si la
|
|
52
|
+
| Question | Si la réponse est vague | Relance recommandée |
|
|
53
53
|
|----------|------------------------|---------------------|
|
|
54
|
-
| Q3.1 (
|
|
55
|
-
| Q3.1 (
|
|
56
|
-
| Q3.2 (attributs) | Champs techniques (ID, CreatedDate) | "Les champs techniques sont auto-
|
|
57
|
-
| Q3.3 (relations) | "1:N" sans
|
|
58
|
-
| Q3.11 (
|
|
59
|
-
| Q3.13 (actions) | "CRUD classique" | "Actions
|
|
54
|
+
| Q3.1 (entités) | Une seule entité | "Cette entité a-t-elle des sous-éléments ? (lignes de détail, pièces jointes, historique)" |
|
|
55
|
+
| Q3.1 (entités) | Mention de "User" | "L'utilisateur est géré par la plateforme. Décrivez l'entité MÉTIER (Client, Employee, Contact...)" |
|
|
56
|
+
| Q3.2 (attributs) | Champs techniques (ID, CreatedDate) | "Les champs techniques sont auto-gérés. Quels sont les attributs MÉTIER ?" |
|
|
57
|
+
| Q3.3 (relations) | "1:N" sans détail | "Un {Parent} peut avoir combien de {Children} max ? Un {Child} peut-il exister sans {Parent} ?" |
|
|
58
|
+
| Q3.11 (écrans) | "Un écran de liste" | "Avec pages dédiées pour création et édition ? Détail en page avec onglets ?" |
|
|
59
|
+
| Q3.13 (actions) | "CRUD classique" | "Actions métier spécifiques ? (valider, dupliquer, archiver, changer statut, assigner)" |
|
|
60
60
|
| Q3.14 (dashboards) | "Juste des chiffres" | "Les tendances ne seraient-elles pas plus lisibles en graphique ?" |
|
|
61
61
|
|
|
62
|
-
### Anti-patterns
|
|
62
|
+
### Anti-patterns à détecter
|
|
63
63
|
|
|
64
64
|
| Signal | Anti-pattern | Action |
|
|
65
65
|
|--------|-------------|--------|
|
|
66
|
-
|
|
|
67
|
-
| Attributs Id, TenantId, CreatedBy | Champs techniques comme
|
|
66
|
+
| Entité "User" avec attributs métier | Confusion User/Identity | La plateforme gère les Users via Identity |
|
|
67
|
+
| Attributs Id, TenantId, CreatedBy | Champs techniques comme métier | Ces champs sont auto-générés par AuditableEntity |
|
|
68
68
|
| "Un seul gros formulaire avec tout" | Formulaire monolithique | Proposer des onglets ou wizard par section logique |
|
|
69
|
-
| Actions sans confirmation | Actions destructives non
|
|
69
|
+
| Actions sans confirmation | Actions destructives non protégées | "La suppression nécessite-t-elle une confirmation ?" |
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
73
73
|
## RBAC Exclusion
|
|
74
74
|
|
|
75
|
-
> Les concepts suivants sont
|
|
75
|
+
> Les concepts suivants sont gérés par le système RBAC de la plateforme et NE DOIVENT PAS être modélisés comme attributs d'entité :
|
|
76
76
|
|
|
77
77
|
| Concept | Wrong (attribut) | Correct (RBAC) |
|
|
78
78
|
|---------|-----------------|----------------|
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
|
|
85
85
|
## Mapping vers le feature
|
|
86
86
|
|
|
87
|
-
|
|
|
87
|
+
| Réponse | Alimente |
|
|
88
88
|
|---------|----------|
|
|
89
|
-
| Q3.1-Q3.3, Q3.5-Q3.6 | `entities.json` (
|
|
90
|
-
| Q3.7-Q3.9 | `rules.json` (
|
|
89
|
+
| Q3.1-Q3.3, Q3.5-Q3.6 | `entities.json` (entités, attributs, relations, codePattern) |
|
|
90
|
+
| Q3.7-Q3.9 | `rules.json` (règles métier de validation et sécurité) |
|
|
91
91
|
| Q3.10-Q3.13 | `screens.json` (sections, resources, colonnes, actions) |
|
|
92
92
|
| Q3.14-Q3.16 | `screens.json` (sections dashboard, KPI resources) |
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Catégorie 5 : Impact cross-module
|
|
2
2
|
|
|
3
|
-
> **Usage :** Analyser l'impact sur les modules existants et les
|
|
4
|
-
> **Quand charger :** TOUJOURS pour les nouveaux modules (pas les
|
|
5
|
-
> **Objectif :**
|
|
3
|
+
> **Usage :** Analyser l'impact sur les modules existants et les dépendances partagées
|
|
4
|
+
> **Quand charger :** TOUJOURS pour les nouveaux modules (pas les améliorations)
|
|
5
|
+
> **Objectif :** Détecter les interactions, les entités partagées et les impacts d'intégration
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
## 5.1
|
|
9
|
+
## 5.1 Dépendances avec les modules existants
|
|
10
10
|
|
|
11
|
-
| # | Question | Type de
|
|
11
|
+
| # | Question | Type de réponse |
|
|
12
12
|
|---|----------|-----------------|
|
|
13
13
|
| Q5.1 | Avec quels modules existants ce nouveau module interagit-il ? | Liste de modules |
|
|
14
|
-
| Q5.2 | Quelles
|
|
15
|
-
| Q5.3 | Y a-t-il des
|
|
16
|
-
| Q5.4 | Ce module produira-t-il des
|
|
14
|
+
| Q5.2 | Quelles données sont partagées entre modules ? (entités, tables de référence) | Par module |
|
|
15
|
+
| Q5.3 | Y a-t-il des entités existantes que ce module va référencer ? (relations FK) | Liste de références |
|
|
16
|
+
| Q5.4 | Ce module produira-t-il des événements que d'autres modules consomment ? | Liste d'événements |
|
|
17
17
|
|
|
18
|
-
## 5.2
|
|
18
|
+
## 5.2 Évaluation d'impact
|
|
19
19
|
|
|
20
|
-
| # | Question | Type de
|
|
20
|
+
| # | Question | Type de réponse |
|
|
21
21
|
|---|----------|-----------------|
|
|
22
|
-
| Q5.5 | Les modules existants doivent-ils
|
|
23
|
-
| Q5.6 | Y a-t-il des composants UI ou des changements de navigation
|
|
24
|
-
| Q5.7 | Ce module affectera-t-il les permissions ou
|
|
25
|
-
| Q5.8 | Y a-t-il des
|
|
22
|
+
| Q5.5 | Les modules existants doivent-ils être modifiés pour supporter ce nouveau module ? | Liste de changements |
|
|
23
|
+
| Q5.6 | Y a-t-il des composants UI ou des changements de navigation partagés ? | Liste |
|
|
24
|
+
| Q5.7 | Ce module affectera-t-il les permissions ou rôles existants ? Quel impact sur l'intégration ? | Oui/Non + détail |
|
|
25
|
+
| Q5.8 | Y a-t-il des entités partagées modifiées par plusieurs modules ? Quel impact sur l'intégration ? | Évaluation de l'impact |
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -30,40 +30,40 @@
|
|
|
30
30
|
|
|
31
31
|
| Besoin | Pattern | Exemple |
|
|
32
32
|
|--------|---------|---------|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
| Notification
|
|
36
|
-
|
|
|
33
|
+
| Référence une entité | Navigation property + FK | `Order.ClientId -> Client` |
|
|
34
|
+
| Données de référence partagées | Entité partagée dans Domain | `Status`, `Category` |
|
|
35
|
+
| Notification événementielle | MediatR notification | `OrderCreatedNotification` |
|
|
36
|
+
| Requête cross-module | DTO en lecture seule | `IClientQueryService` |
|
|
37
37
|
| Lien de navigation | NavRoute entry | `business/{app}/{module}` |
|
|
38
|
-
| Permission
|
|
38
|
+
| Permission partagée | Hiérarchie de permissions | `{app}.*` covers all modules |
|
|
39
39
|
|
|
40
40
|
---
|
|
41
41
|
|
|
42
|
-
## Guide d'
|
|
42
|
+
## Guide d'élicitation
|
|
43
43
|
|
|
44
44
|
### Techniques de relance
|
|
45
45
|
|
|
46
|
-
| Question | Si la
|
|
46
|
+
| Question | Si la réponse est vague | Relance recommandée |
|
|
47
47
|
|----------|------------------------|---------------------|
|
|
48
|
-
| Q5.1 (interactions) | "Aucun" | "Ce module est totalement
|
|
49
|
-
| Q5.2 (
|
|
50
|
-
| Q5.3 (FK
|
|
51
|
-
| Q5.4 (
|
|
52
|
-
| Q5.8 (impact) | "Pas d'impact" | "Deux modules modifient-ils la
|
|
48
|
+
| Q5.1 (interactions) | "Aucun" | "Ce module est totalement isolé ? Pas de lien avec des clients, produits, utilisateurs d'autres modules ?" |
|
|
49
|
+
| Q5.2 (données partagées) | "Je ne sais pas" | Utiliser le `{codebase_context}` : "J'ai trouvé les entités {list}. Ce module a-t-il besoin de les référencer ?" |
|
|
50
|
+
| Q5.3 (FK références) | Vague | "Une {entity} de ce module appartient-elle à un {existing_entity} ?" |
|
|
51
|
+
| Q5.4 (événements) | "Non" | "Quand un {entity} est créé/modifié/supprimé, faut-il notifier un autre module ?" |
|
|
52
|
+
| Q5.8 (impact) | "Pas d'impact" | "Deux modules modifient-ils la même entité ? Quel est l'impact sur l'intégration ?" |
|
|
53
53
|
|
|
54
|
-
### Anti-patterns
|
|
54
|
+
### Anti-patterns à détecter
|
|
55
55
|
|
|
56
56
|
| Signal | Anti-pattern | Action |
|
|
57
57
|
|--------|-------------|--------|
|
|
58
|
-
| Module totalement
|
|
59
|
-
| Duplication d'
|
|
60
|
-
| Modification d'
|
|
58
|
+
| Module totalement isolé | Silo de données | Rare qu'un module métier n'ait aucune connexion. Vérifier avec le codebase context. |
|
|
59
|
+
| Duplication d'entité existante | Entité dupliquée | Si `Client` existe déjà, ne pas créer `Customer`. Référencer l'existant. |
|
|
60
|
+
| Modification d'entité d'un autre module | Couplage fort | Utiliser des événements (MediatR) plutôt que des modifications directes. |
|
|
61
61
|
|
|
62
62
|
---
|
|
63
63
|
|
|
64
64
|
## Mapping vers la consolidation
|
|
65
65
|
|
|
66
|
-
|
|
|
66
|
+
| Réponse | Alimente |
|
|
67
67
|
|---------|----------|
|
|
68
68
|
| Q5.1-Q5.4 | `consolidation.crossModuleInteractions[]`, `consolidation.sharedEntities[]` |
|
|
69
69
|
| Q5.5-Q5.8 | `consolidation.impactAssessment[]`, `consolidation.permissionCoherence` |
|
|
@@ -53,27 +53,27 @@
|
|
|
53
53
|
|
|
54
54
|
### Phase de cadrage (step-01)
|
|
55
55
|
|
|
56
|
-
1. **
|
|
56
|
+
1. **Début :** Commencer par 01-context (contexte métier, identité application)
|
|
57
57
|
2. **Adapter :** Sauter les questions non pertinentes selon le contexte
|
|
58
|
-
3. **Approfondir :** Poser des questions de relance sur les
|
|
59
|
-
4. **Challenger :** Ne pas accepter "on verra plus tard" sur les
|
|
60
|
-
5. **Par lots :**
|
|
58
|
+
3. **Approfondir :** Poser des questions de relance sur les réponses vagues
|
|
59
|
+
4. **Challenger :** Ne pas accepter "on verra plus tard" sur les fonctionnalités indispensables
|
|
60
|
+
5. **Par lots :** Présenter 3 a 4 questions par interaction (AskUserQuestion)
|
|
61
61
|
|
|
62
62
|
### Phase de specification (step-03)
|
|
63
63
|
|
|
64
|
-
1. **Par module :** Charger 03-data-ui pour chaque module en cours de
|
|
65
|
-
2. **Cross-module :** Charger 05-cross-module si le module a des
|
|
64
|
+
1. **Par module :** Charger 03-data-ui pour chaque module en cours de spécification
|
|
65
|
+
2. **Cross-module :** Charger 05-cross-module si le module a des dépendances identifiées en step-02
|
|
66
66
|
|
|
67
67
|
### Questions de relance
|
|
68
68
|
|
|
69
|
-
Pour chaque
|
|
69
|
+
Pour chaque réponse vague, utiliser :
|
|
70
70
|
- "Pouvez-vous me donner un exemple concret ?"
|
|
71
71
|
- "Comment mesurez-vous cela aujourd'hui ?"
|
|
72
|
-
- "Que se passe-t-il si cette
|
|
73
|
-
- "Qui est
|
|
72
|
+
- "Que se passe-t-il si cette règle n'est pas respectée ?"
|
|
73
|
+
- "Qui est impacté par cette décision ?"
|
|
74
74
|
|
|
75
75
|
### Filtre de pertinence
|
|
76
76
|
|
|
77
|
-
Chaque question
|
|
78
|
-
> "La
|
|
77
|
+
Chaque question conservée passe ce test :
|
|
78
|
+
> "La réponse change-t-elle quelque chose dans le système a construire ?"
|
|
79
79
|
> Oui -> Conserver | Non -> Supprimer
|
|
@@ -239,7 +239,7 @@ Determine the language for analysis and code generation.
|
|
|
239
239
|
|
|
240
240
|
**Check config:**
|
|
241
241
|
- Retrieve `language` from `.business-analyse/config.json`
|
|
242
|
-
- Default: "fr" (
|
|
242
|
+
- Default: "fr" (Français)
|
|
243
243
|
|
|
244
244
|
**If not in config:**
|
|
245
245
|
```
|
|
@@ -247,7 +247,7 @@ Ask via AskUserQuestion:
|
|
|
247
247
|
question: "Quelle langue pour l'analyse ?"
|
|
248
248
|
header: "Langue"
|
|
249
249
|
options:
|
|
250
|
-
- label: "
|
|
250
|
+
- label: "Français (fr)"
|
|
251
251
|
- label: "English (en)"
|
|
252
252
|
- label: "Italiano (it)"
|
|
253
253
|
- label: "Deutsch (de)"
|
|
@@ -32,16 +32,16 @@ Frame the analysis scope at the **application level** through an interactive con
|
|
|
32
32
|
## EXECUTION FLOW — 5 PHASES
|
|
33
33
|
|
|
34
34
|
```
|
|
35
|
-
Phase 1:
|
|
35
|
+
Phase 1: ÉCOUTE → Read brief + codebase pre-research + silent pre-analysis
|
|
36
36
|
Phase 2: REFORMULATION → Rephrase the need back to the client for validation
|
|
37
37
|
Phase 3: APPROFONDISSEMENT → Challenge assumptions with targeted questionnaires
|
|
38
38
|
Phase 4: ANTICIPATION → Suggest unexpressed needs from domain expertise
|
|
39
|
-
Phase 5:
|
|
39
|
+
Phase 5: PÉRIMÈTRE → Bound scope with roles, coverage matrix (sections + resources)
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
## PHASE 1:
|
|
44
|
+
## PHASE 1: ÉCOUTE (Listen)
|
|
45
45
|
|
|
46
46
|
### 1. Read Current State
|
|
47
47
|
|
|
@@ -168,7 +168,7 @@ Write via ba-writer:
|
|
|
168
168
|
{
|
|
169
169
|
"code": "Employees",
|
|
170
170
|
"applicationCode": "HumanResources",
|
|
171
|
-
"name": "
|
|
171
|
+
"name": "Employés",
|
|
172
172
|
"featureType": "data-centric",
|
|
173
173
|
"priority": "must",
|
|
174
174
|
"entities": ["Employee", "Contract"],
|
|
@@ -179,7 +179,7 @@ Write via ba-writer:
|
|
|
179
179
|
}
|
|
180
180
|
],
|
|
181
181
|
"dependencies": [
|
|
182
|
-
{ "from": "Absences", "to": "Employees", "description": "Une absence
|
|
182
|
+
{ "from": "Absences", "to": "Employees", "description": "Une absence référence un employé" }
|
|
183
183
|
]
|
|
184
184
|
}
|
|
185
185
|
```
|
|
@@ -44,18 +44,18 @@ For each entity identified in step 02:
|
|
|
44
44
|
```json
|
|
45
45
|
{
|
|
46
46
|
"name": "Employee",
|
|
47
|
-
"description": "
|
|
47
|
+
"description": "Représente un employé de l'entreprise",
|
|
48
48
|
"attributes": [
|
|
49
49
|
{ "name": "code", "type": "string", "required": true, "description": "Identifiant unique" },
|
|
50
|
-
{ "name": "userId", "type": "guid", "required": true, "description": "
|
|
51
|
-
{ "name": "departmentId", "type": "guid", "required": true, "description": "
|
|
50
|
+
{ "name": "userId", "type": "guid", "required": true, "description": "Référence vers l'utilisateur" },
|
|
51
|
+
{ "name": "departmentId", "type": "guid", "required": true, "description": "Département d'affectation" },
|
|
52
52
|
{ "name": "hireDate", "type": "date", "required": true, "description": "Date d'embauche" },
|
|
53
|
-
{ "name": "position", "type": "string", "description": "Poste
|
|
54
|
-
{ "name": "status", "type": "enum", "options": ["Active", "Inactive", "OnLeave", "Terminated"], "description": "Statut de l'
|
|
53
|
+
{ "name": "position", "type": "string", "description": "Poste occupé" },
|
|
54
|
+
{ "name": "status", "type": "enum", "options": ["Active", "Inactive", "OnLeave", "Terminated"], "description": "Statut de l'employé" }
|
|
55
55
|
],
|
|
56
56
|
"relationships": [
|
|
57
|
-
{ "target": "Department", "type": "ManyToOne", "description": "Appartient
|
|
58
|
-
{ "target": "Contract", "type": "OneToMany", "description": "
|
|
57
|
+
{ "target": "Department", "type": "ManyToOne", "description": "Appartient à un département" },
|
|
58
|
+
{ "target": "Contract", "type": "OneToMany", "description": "Possède plusieurs contrats" }
|
|
59
59
|
]
|
|
60
60
|
}
|
|
61
61
|
```
|
|
@@ -69,7 +69,7 @@ For each entity/process, identify rules:
|
|
|
69
69
|
"id": "BR-VAL-EMPLOYEES-001",
|
|
70
70
|
"name": "Validation date embauche",
|
|
71
71
|
"category": "validation",
|
|
72
|
-
"statement": "La date d'embauche ne peut pas
|
|
72
|
+
"statement": "La date d'embauche ne peut pas être dans le futur",
|
|
73
73
|
"example": "Date embauche = 2027-01-01 → erreur car > date du jour",
|
|
74
74
|
"entities": ["Employee"],
|
|
75
75
|
"severity": "blocking"
|
|
@@ -85,19 +85,19 @@ For each stakeholder action:
|
|
|
85
85
|
```json
|
|
86
86
|
{
|
|
87
87
|
"id": "UC-EMPLOYEES-001",
|
|
88
|
-
"name": "
|
|
88
|
+
"name": "Créer un employé",
|
|
89
89
|
"actor": "Responsable RH",
|
|
90
90
|
"preconditions": ["L'utilisateur a la permission HumanResources.Employees.Create"],
|
|
91
91
|
"steps": [
|
|
92
|
-
"L'utilisateur ouvre la page de
|
|
93
|
-
"Il remplit les champs obligatoires (nom,
|
|
92
|
+
"L'utilisateur ouvre la page de création",
|
|
93
|
+
"Il remplit les champs obligatoires (nom, département, date embauche)",
|
|
94
94
|
"Il valide le formulaire",
|
|
95
|
-
"Le
|
|
96
|
-
"Le
|
|
95
|
+
"Le système vérifie les règles métier (BR-VAL-EMPLOYEES-001)",
|
|
96
|
+
"Le système crée l'employé et affiche la fiche"
|
|
97
97
|
],
|
|
98
|
-
"alternative": "Si les
|
|
98
|
+
"alternative": "Si les données sont invalides, le système affiche les erreurs",
|
|
99
99
|
"businessRules": ["BR-VAL-EMPLOYEES-001"],
|
|
100
|
-
"result": "L'
|
|
100
|
+
"result": "L'employé est créé avec le statut 'Actif'"
|
|
101
101
|
}
|
|
102
102
|
```
|
|
103
103
|
|