@atlashub/smartstack-cli 3.27.0 → 3.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.
Files changed (46) hide show
  1. package/dist/index.js +6 -7
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -3
  4. package/templates/project/api.ts.template +4 -2
  5. package/templates/project/appsettings.json.template +1 -1
  6. package/templates/skills/apex/_shared.md +13 -0
  7. package/templates/skills/apex/references/post-checks.md +228 -6
  8. package/templates/skills/apex/references/smartstack-api.md +67 -17
  9. package/templates/skills/apex/references/smartstack-frontend.md +41 -1
  10. package/templates/skills/apex/references/smartstack-layers.md +40 -10
  11. package/templates/skills/apex/steps/step-02-plan.md +16 -11
  12. package/templates/skills/apex/steps/step-03-execute.md +6 -0
  13. package/templates/skills/apex/steps/step-04-examine.md +4 -2
  14. package/templates/skills/application/references/frontend-verification.md +26 -1
  15. package/templates/skills/application/steps/step-03-roles.md +1 -1
  16. package/templates/skills/application/steps/step-05-frontend.md +24 -8
  17. package/templates/skills/application/templates-frontend.md +41 -22
  18. package/templates/skills/application/templates-seed.md +53 -16
  19. package/templates/skills/business-analyse/SKILL.md +4 -2
  20. package/templates/skills/business-analyse/_shared.md +17 -4
  21. package/templates/skills/business-analyse/react/schema.md +1 -1
  22. package/templates/skills/business-analyse/references/agent-module-prompt.md +11 -9
  23. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +4 -3
  24. package/templates/skills/business-analyse/references/deploy-modes.md +1 -1
  25. package/templates/skills/business-analyse/references/handoff-file-templates.md +4 -4
  26. package/templates/skills/business-analyse/references/robustness-checks.md +12 -9
  27. package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
  28. package/templates/skills/business-analyse/references/ui-resource-cards.md +3 -3
  29. package/templates/skills/business-analyse/references/validation-checklist.md +21 -3
  30. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +33 -5
  31. package/templates/skills/business-analyse/steps/step-03b-ui.md +2 -2
  32. package/templates/skills/business-analyse/steps/step-03c-compile.md +17 -9
  33. package/templates/skills/business-analyse/steps/step-03d-validate.md +1 -1
  34. package/templates/skills/business-analyse/steps/step-04b-analyze.md +5 -3
  35. package/templates/skills/business-analyse/steps/step-05a-handoff.md +24 -16
  36. package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +2 -2
  37. package/templates/skills/business-analyse/templates/tpl-handoff.md +10 -8
  38. package/templates/skills/business-analyse/templates/tpl-progress.md +7 -6
  39. package/templates/skills/ralph-loop/references/category-rules.md +104 -9
  40. package/templates/skills/ralph-loop/references/compact-loop.md +124 -3
  41. package/templates/skills/ralph-loop/references/core-seed-data.md +158 -38
  42. package/templates/skills/ralph-loop/references/task-transform-legacy.md +3 -3
  43. package/templates/skills/ralph-loop/steps/step-02-execute.md +311 -15
  44. package/templates/skills/ralph-loop/steps/step-03-commit.md +2 -2
  45. package/templates/skills/ralph-loop/steps/step-04-check.md +4 -3
  46. package/templates/skills/ralph-loop/steps/step-05-report.md +51 -1
@@ -28,12 +28,13 @@
28
28
  □ Total: X tasks
29
29
 
30
30
  [SEEDDATA-CORE] Core Configuration (MANDATORY)
31
- NavigationModuleConfiguration - Module navigation structure
32
- PermissionsConfiguration - RBAC permissions setup
33
- RolesConfiguration - Predefined roles
34
- TenantConfiguration - Test tenants
35
- UserConfiguration - Test users
36
- Total: 5 CORE tasks
31
+ NavigationApplicationSeedData - Application navigation entry (once per app)
32
+ ApplicationRolesSeedData - Application-scoped roles (once per app)
33
+ NavigationModuleSeedData - Module navigation structure (per module)
34
+ PermissionsSeedData - RBAC permissions (per module)
35
+ RolesSeedData - Role-permission mappings (per module)
36
+ {App}SeedDataProvider - IClientSeedDataProvider (4 methods)
37
+ Total: 2 app-level + 3 per-module + 1 provider
37
38
 
38
39
  [SEEDDATA] Business Reference Data
39
40
  □ Seed {Entity1} reference data
@@ -79,25 +79,62 @@ Execution sequence:
79
79
  > "PermissionsSeedData", "RolesSeedData", or "IClientSeedDataProvider":
80
80
  > **THEN read `references/core-seed-data.md`** — this is MANDATORY, DO NOT improvise.
81
81
 
82
- **Rules:**
83
- - NavigationModuleSeedData.cs: deterministic GUIDs (SHA256), 4 languages (fr, en, it, de)
84
- - PermissionsSeedData.cs: MCP `generate_permissions` first, fallback to template
85
- - RolesSeedData.cs: context-based role mapping (Admin=CRUD, Manager=CRU, Contributor=CR, Viewer=R)
86
- - SeedConstants.cs: shared deterministic GUIDs
87
- - IClientSeedDataProvider: SeedNavigationAsync + SeedPermissionsAsync + SeedRolePermissionsAsync
82
+ **Seed Data Chain (9 files minimum):**
83
+
84
+ Application-level (created ONCE, shared across modules):
85
+ - **NavigationApplicationSeedData.cs**: Application navigation entry (MUST be first). Provides ApplicationId.
86
+ - **ApplicationRolesSeedData.cs**: 4 application-scoped roles (admin, manager, contributor, viewer). Provides role entries for SeedRolesAsync().
87
+
88
+ Per-module:
89
+ - **NavigationModuleSeedData.cs**: deterministic GUIDs (SHA256), 4 languages (fr, en, it, de)
90
+ - **Permissions.cs**: Static permission constants (`Permissions.{Module}.Read`). Referenced by `[RequirePermission]`.
91
+ - **PermissionsSeedData.cs**: MCP `generate_permissions` first, fallback to template
92
+ - **RolesSeedData.cs**: code-based role-permission mapping (Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R)
93
+
94
+ Per-module (MANDATORY when `seedDataCore.navigationSections` exists in feature.json):
95
+ - **NavigationSectionSeedData**: section entries, section translations (4 languages), section-level permissions, and section-level role mappings — all within `NavigationModuleSeedData.cs`, `PermissionsSeedData.cs`, and `RolesSeedData.cs`
96
+ - Section-level permissions: wildcard + CRUD per section (same pattern as module-level)
97
+ - Section-level role mappings: Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R per section
98
+
99
+ Infrastructure:
100
+ - **SeedConstants.cs**: shared deterministic GUIDs (ApplicationId, ModuleIds)
101
+ - **{App}SeedDataProvider.cs**: implements IClientSeedDataProvider with 4 methods
88
102
  - DI: `services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>()`
89
103
 
104
+ **Rules:**
105
+ - IClientSeedDataProvider: SeedNavigationAsync + SeedRolesAsync + SeedPermissionsAsync + SeedRolePermissionsAsync
106
+ - Admin=wildcard(*), Manager=CRU (read+create+update), Contributor=CR (read+create), Viewer=R (read only)
107
+
90
108
  **Business seed data (DevDataSeeder):**
91
109
  - ALL seeded business entities MUST include `TenantId = {tenantGuid}`
92
110
  - Reference entities (types, categories, statuses) MUST set TenantId
93
111
  - Use deterministic TenantId from SeedConstants (NEVER hardcoded inline)
94
112
  - DevDataSeeder MUST implement `IDevDataSeeder` with idempotent `SeedAsync()` method
95
113
 
114
+ **Section route conventions (BLOCKING):**
115
+ - `list` section route = module route (e.g., `/business/human-resources/employees`) — NO `/list` suffix
116
+ - `detail` section route = module route + `/:id` (e.g., `/business/human-resources/employees/:id`) — NOT `/detail/:id`
117
+ - Other sections (dashboard, approve, import) = module route + `/{section-kebab}` (normal)
118
+ - FORBIDDEN: `/{module}/list`, `/{module}/detail/:id` — these are CRUD view modes, not sub-areas
119
+
96
120
  **FORBIDDEN:**
97
121
  - `Guid.NewGuid()` → use deterministic GUIDs
98
122
  - Empty seed data classes with only GUIDs and no seeding methods
99
123
  - Missing translations (must have all 4 languages)
100
124
  - Seeding business entities WITHOUT `TenantId`
125
+ - Navigation section routes ending in `/list` or `/detail/:id`
126
+
127
+ ### POST-CHECK: Navigation translations diacritical marks
128
+
129
+ After generating `NavigationTranslationSeedEntry` strings, verify ALL non-English translations contain proper diacritical marks:
130
+
131
+ - **FR** must use: é, è, ê, ë, à, â, ç, ù, û, ô, î (e.g., "Employés" NOT "Employes", "Activités" NOT "Activites")
132
+ - **DE** must use: ä, ö, ü, ß (e.g., "Aktivitäten" NOT "Aktivitaten")
133
+ - **IT** must use: à, è, é, ì, ò, ù (e.g., "Attività" NOT "Attivita")
134
+
135
+ Cross-reference navigation seed data labels with the corresponding frontend `i18n/index.ts` translations for consistency.
136
+
137
+ **BLOCKING** if any `NavigationTranslationSeedEntry` for fr/de/it contains only ASCII characters where diacritical marks are expected in the target language.
101
138
 
102
139
  ---
103
140
 
@@ -290,6 +327,13 @@ fi
290
327
  - Reference/lookup entities (types, categories, statuses) MUST also have controllers — they are needed for dropdowns and configuration
291
328
  - Count: `controllers created >= entities in module`. If fewer → FAIL
292
329
 
330
+ **Section-level controllers (CONDITIONAL: when `navSections[]` defined in feature.json):**
331
+ - File path: `Api/Controllers/{ContextShort}/{App}/{Section}Controller.cs`
332
+ - NavRoute attribute: `[NavRoute("{context}.{app}.{module}.{section}")]`
333
+ - Permission attribute: `[RequirePermission(Permissions.{Module}.{Section}.{Action})]`
334
+ - Route prefix: `api/{context}/{app}/{module}/{section}`
335
+ - Each section gets its own controller with CRUD endpoints scoped to the section
336
+
293
337
  **FORBIDDEN:**
294
338
  - `[Authorize]` without specific permission → use `[RequirePermission]`
295
339
  - Returning domain entities directly
@@ -305,12 +349,13 @@ fi
305
349
  **FORBIDDEN:** `src/pages/{Module}/` (flat structure without Context/App)
306
350
 
307
351
  **Execution sequence (IN ORDER):**
352
+ 0. **Read back feature.json** (via `prd.source.featurePath`) — The PRD only carries the file list (structural skeleton). The behavioral specs (columnDefs, componentMapping, layout, rowActions, emptyState, tab structure, i18n key-value pairs, dashboard KPIs, state machine transitions) are ONLY in the original feature.json. Without this step, generated code will be generic and miss entity-specific UI details.
308
353
  1. `mcp__smartstack__scaffold_api_client` → API client + types + React Query hook
309
354
  2. `mcp__smartstack__scaffold_routes` (with `outputFormat: "clientRoutes"`) → route registry + route fragments
310
355
  3. **Wire routes to App.tsx (detect pattern: `contextRoutes` array OR JSX `<Route>`):**
311
356
  - **Pattern A** (`contextRoutes: ContextRouteExtensions` in App.tsx): add to `contextRoutes.{context}[]` with RELATIVE paths → auto-injected into both standard + tenant trees
312
357
  - **Pattern B** (JSX `<Route>` in App.tsx): insert `<Route>` entries inside correct Layout wrapper (BOTH standard AND tenant-prefixed `/t/:slug/...` blocks)
313
- 4. Create pages using **`/ui-components` skill** (MANDATORY for entity lists, grids, tables, dashboards, charts). The skill ensures CSS variables, EntityCard, SmartTable, loading/error/empty states, and responsive grid patterns.
358
+ 4. Create pages using **`/ui-components` skill** — **LOAD the skill step files before creating any page.** This is MANDATORY for entity lists, grids, tables, dashboards, charts. The skill ensures CSS variables, EntityCard, SmartTable, loading/error/empty states, and responsive grid patterns. **Pages MUST use `t()` from `useTranslation()` for ALL visible text from the very first line of code.** Do NOT hardcode English strings with the intent of adding i18n later — the i18n keys are created in step 6 based on what keys the pages reference. Pattern: `t('{moduleLower}:actions.create', 'Create')`.
314
359
  5. Create preferences hook: `use{Module}Preferences.ts`
315
360
  6. Generate i18n (4 languages: fr, en, it, de) — see I18n section below for detailed rules
316
361
  7. `npm run typecheck` MUST pass (BLOCKING)
@@ -323,6 +368,18 @@ fi
323
368
  - FK fields: `EntityLookup` for searchable entity selection (NEVER plain text for Guid FK)
324
369
  - Dashboard: `StatCard`, Recharts components
325
370
 
371
+ **Per-page /ui-components validation (MANDATORY before commit):**
372
+ - After creating EACH page, verify it follows /ui-components patterns:
373
+ 1. List pages: uses `DataTable` or `SmartTable` (NOT raw `<table>`)
374
+ 2. List pages: uses `EntityCard` for card/grid views (NOT custom `<div>` cards)
375
+ 3. All pages: ALL colors use CSS variables (`bg-[var(--xxx)]`) — ZERO hardcoded Tailwind colors
376
+ 4. All pages: loading skeleton, error state with retry, empty state are present
377
+ 5. All pages: ALL visible text uses `t()` from `useTranslation()`
378
+ 6. Delete actions: use `ConfirmDialog` component (NOT `window.confirm()`)
379
+ 7. Status displays: use `StatusBadge` with CSS variable colors (NOT inline styled spans)
380
+ - **If ANY check fails: fix the page BEFORE moving to the next page**
381
+ - The POST-CHECKs in step-02 enforce these rules with BLOCKING severity
382
+
326
383
  **Form pages (CRITICAL — ZERO modals/popups/drawers):**
327
384
  - Create form: `EntityCreatePage.tsx` with route `/{module}/create`
328
385
  - Edit form: `EntityEditPage.tsx` with route `/{module}/:id/edit`
@@ -340,6 +397,27 @@ fi
340
397
  | `business.*` | `BusinessLayout` | `/business` |
341
398
  | `personal.*` | `UserLayout` | `/personal/myspace` |
342
399
 
400
+ **Route naming convention (CRITICAL — must match backend):**
401
+ - Frontend route paths MUST use **kebab-case** matching the backend API route convention
402
+ - Convention: `HumanResources` (C# namespace) → `human-resources` (URL segment)
403
+ - ALL multi-word route segments MUST contain hyphens: `time-management`, `human-resources`, `leave-balance`
404
+ - FORBIDDEN: `humanresources`, `timemanagement`, `leavebalance` (concatenated without hyphens)
405
+ - Frontend path `/business/human-resources/clients` matches API `api/business/human-resources/clients`
406
+ - Navigation seed data Route values MUST also use kebab-case
407
+ - The POST-CHECK in step-02 will BLOCK if frontend routes don't match backend kebab-case convention
408
+
409
+ **Section-level pages (CONDITIONAL: when `navSections[]` defined in feature.json):**
410
+ - Page file: `src/pages/{ContextPascal}/{AppPascal}/{Module}/{Section}Page.tsx`
411
+ - Route: nested as child of module route in App.tsx (e.g., `/business/human-resources/projects/timesheets`)
412
+ - Add to `contextRoutes.{context}[]` (Pattern A) or as nested `<Route>` (Pattern B)
413
+ - Each section page has its own route and permission check
414
+
415
+ **React Router mapping for sections:**
416
+ - `list` section → already the module's `index: true` route (NO separate `path: 'list'`)
417
+ - `detail` section → already the module's `path: ':id'` route (NO separate `path: 'detail'`)
418
+ - Other sections → `path: '{section-kebab}'` as child of module route
419
+ - FORBIDDEN frontend paths: `path: 'list'`, `path: 'detail'` — these are handled by the module's index and :id routes
420
+
343
421
  **CSS:** Variables ONLY → `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`
344
422
 
345
423
  **Form error handling (MANDATORY):**
@@ -348,6 +426,13 @@ fi
348
426
  - API errors (4xx, 5xx) MUST show a user-friendly error notification (toast/banner)
349
427
  - Forms MUST preserve user input on error (no data loss on failed submit)
350
428
 
429
+ **Hook error handling pattern (MANDATORY):**
430
+ - ALL hooks MUST preserve server validation errors from axios responses
431
+ - Pattern: `catch (err) { if (axios.isAxiosError(err)) { return err.response?.data; } throw err; }`
432
+ - NEVER discard `err.response.data` — it contains field-level validation errors from FluentValidation
433
+ - Error messages MUST use i18n: `setError(t('{mod}:errors.saveFailed'))` — NEVER hardcoded English strings
434
+ - Toast/notification messages MUST also use i18n
435
+
351
436
  **Dependency verification (BLOCKING):**
352
437
  - BEFORE writing any import, verify the package exists in `package.json`
353
438
  - If package not present: run `npm install {package}` BEFORE writing the import
@@ -372,6 +457,13 @@ useXxx with raw axios inside hooks → hooks MUST use the shared apiCl
372
457
  placeholder="Enter ID" / "Enter GUID" → EntityLookup provides search-based entity selection
373
458
  <Modal>/<Dialog>/<Drawer>/<Popup> for forms → forms are FULL PAGES with own URL routes (/create, /:id/edit)
374
459
  useState(showCreateModal/editDialog) → navigate to form page, NEVER toggle modal visibility
460
+ <table>/<thead>/<tbody> → MUST use SmartTable or DataTable component
461
+ bg-blue-600 / bg-red-500 / etc. → MUST use CSS variables: bg-[var(--color-accent-600)]
462
+ text-green-700 / text-gray-500 / etc. → MUST use CSS variables: text-[var(--success-text)]
463
+ window.confirm() / confirm() → MUST use ConfirmDialog component with i18n
464
+ Hardcoded English text in JSX (>Create<) → MUST use t('{mod}:actions.create', 'Create')
465
+ Hardcoded error strings in hooks → MUST use t('{mod}:errors.loadFailed') in all hooks
466
+ /business/humanresources/ → MUST use kebab-case: /business/human-resources/
375
467
  ```
376
468
 
377
469
  ---
@@ -399,11 +491,14 @@ useState(showCreateModal/editDialog) → navigate to form page, NEVER to
399
491
  **Usage pattern in TSX:** `t('{moduleLower}:actions.create', 'Create')` — ALWAYS namespace prefix + fallback value.
400
492
 
401
493
  **Rules:**
402
- - 4 JSON files: fr, en, it, de — ALL mandatory (not just fr/en)
494
+ - 4 JSON files per module: fr, en, it, de — ALL mandatory (not just fr/en)
495
+ - File structure: `src/i18n/locales/{lang}/{moduleLower}.json` — NEVER inline translations in index.ts
403
496
  - Identical key structures across all languages — same keys, translated values
404
- - All UI labels, validation messages, button text, empty states
497
+ - All UI labels, validation messages, button text, empty states, error messages
405
498
  - Depends on frontend page completion (pages define which keys are needed)
406
499
  - Add entity-specific keys under `labels`, `columns`, `form` for each entity field
500
+ - **Hooks MUST also use i18n** — error messages like "Failed to load" MUST use `t('{mod}:errors.loadFailed')`
501
+ - **FORBIDDEN:** Inline translation objects in `i18n/index.ts` — use separate JSON files per language per module
407
502
  - Reference `smartstack-frontend.md` for the complete template
408
503
 
409
504
  ---
@@ -69,6 +69,7 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
69
69
 
70
70
  1. Mark `task.status = 'in_progress'`, `task.started_at = now`
71
71
  2. **Read `references/category-rules.md`** for category-specific rules
72
+ 2bis. **For frontend tasks:** Also read back the original **feature.json** (via `prd.source.featurePath`) to access wireframe `componentMapping`, `columnDefs`, `layout`, `emptyState`, `rowActions`, and `i18n` keys that the PRD does NOT carry forward. The PRD only has the file list — the behavioral spec is in feature.json.
72
73
  3. Implement the task following SmartStack conventions
73
74
  4. Track `files_created` and `files_modified`
74
75
 
@@ -110,7 +111,7 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
110
111
  |----------|--------|
111
112
  | `infrastructure` with `_migrationMeta` | Migration sequence: `suggest_migration` MCP → `dotnet ef migrations add` → cleanup corrupted artifacts (`for d in src/*/bin?Debug; do [ -d "$d" ] && rm -rf "$d"; done`) → `dotnet ef database update` → `dotnet build` |
112
113
  | `infrastructure` with seed data keywords | **MANDATORY:** Read `references/core-seed-data.md` → implement templates → `dotnet build` |
113
- | `frontend` | MCP-first: `scaffold_api_client` → `scaffold_routes` (outputFormat: clientRoutes) → **wire to App.tsx (detect pattern: `contextRoutes` array OR JSX `<Route>`)** → create pages → `npm run typecheck && npm run lint` |
114
+ | `frontend` | MCP-first: `scaffold_api_client` → `scaffold_routes` (outputFormat: clientRoutes) → **wire to App.tsx** **LOAD `/ui-components` skill** before creating ANY page → create pages using skill patterns (SmartTable, EntityCard, CSS variables, StatusBadge) ALL visible text via `t()` from first line → `npm run typecheck && npm run lint` → **run frontend POST-CHECKs (section 3bis below)** |
114
115
  | `test` | **Create tests:** `scaffold_tests` MCP → **Run:** `dotnet test --verbosity normal` → **Fix loop:** if fail → fix SOURCE CODE → rebuild → retest → repeat until 100% pass |
115
116
  | `validation` | `dotnet clean && dotnet restore && dotnet build` → `dotnet test` (full) → `validate_conventions` MCP |
116
117
 
@@ -161,7 +162,112 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
161
162
  ```
162
163
  If FAIL → fix → re-check → loop until pass
163
164
 
164
- 3bis. **Dependency audit (if frontend tasks in batch):**
165
+ 3bis. **Frontend POST-CHECKs (BLOCKING — if frontend tasks in batch):**
166
+
167
+ > **CRITICAL:** These checks enforce /ui-components compliance, i18n, and route conventions.
168
+ > Without them, generated code silently regresses to raw HTML tables, hardcoded colors, and English-only text.
169
+
170
+ ```bash
171
+ # Resolve paths dynamically (handles web/ prefix)
172
+ PAGE_DIR=$(find . -path "*/src/pages" -not -path "*/node_modules/*" -type d 2>/dev/null | head -1)
173
+ HOOK_DIR=$(find . -path "*/src/hooks" -not -path "*/node_modules/*" -type d 2>/dev/null | head -1)
174
+ COMP_DIR=$(find . -path "*/src/components" -not -path "*/node_modules/*" -type d 2>/dev/null | head -1)
175
+ WEB_SRC=$(find . -name "App.tsx" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
176
+
177
+ if [ -n "$PAGE_DIR" ]; then
178
+ # BLOCKING: No raw HTML <table> — MUST use SmartTable/DataTable
179
+ RAW_TABLES=$(grep -rPn '<table[\s>]|<thead[\s>]|<tbody[\s>]' "$PAGE_DIR" --include="*.tsx" 2>/dev/null)
180
+ if [ -n "$RAW_TABLES" ]; then
181
+ echo "BLOCKING: Raw HTML <table> detected — MUST use SmartTable or DataTable"
182
+ echo "$RAW_TABLES" | head -5
183
+ # FIX REQUIRED before commit
184
+ fi
185
+
186
+ # BLOCKING: No hardcoded Tailwind colors — MUST use CSS variables
187
+ HARDCODED_COLORS=$(grep -rPn '(?:bg|text|border|ring)-(?:red|blue|green|yellow|orange|purple|pink|indigo|teal|cyan|emerald|violet|fuchsia|rose|amber|lime|sky|slate|gray|zinc|neutral|stone)-\d{2,3}' "$PAGE_DIR" "$COMP_DIR" --include="*.tsx" 2>/dev/null | head -10)
188
+ if [ -n "$HARDCODED_COLORS" ]; then
189
+ echo "BLOCKING: Hardcoded Tailwind colors — MUST use CSS variables (bg-[var(--bg-secondary)])"
190
+ echo "$HARDCODED_COLORS" | head -5
191
+ # FIX REQUIRED before commit
192
+ fi
193
+
194
+ # BLOCKING: No window.confirm() — use ConfirmDialog component
195
+ BAD_CONFIRM=$(grep -rPn 'window\.confirm\s*\(' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | grep -v '//')
196
+ if [ -n "$BAD_CONFIRM" ]; then
197
+ echo "BLOCKING: window.confirm() detected — use ConfirmDialog component with i18n"
198
+ echo "$BAD_CONFIRM"
199
+ # FIX REQUIRED before commit
200
+ fi
201
+
202
+ # BLOCKING: No hardcoded English UI text in JSX
203
+ HARDCODED_TEXT=$(grep -rPn '>\s*(Create|Edit|Delete|Save|Cancel|Search|Loading|Error|No .* found|Are you sure|Submit|Back|Actions|Status)\s*<' "$PAGE_DIR" --include="*.tsx" 2>/dev/null | grep -v test | grep -v '//' | head -10)
204
+ if [ -n "$HARDCODED_TEXT" ]; then
205
+ echo "BLOCKING: Hardcoded English text — ALL visible text MUST use t() from useTranslation()"
206
+ echo "$HARDCODED_TEXT" | head -5
207
+ # FIX REQUIRED before commit
208
+ fi
209
+
210
+ # BLOCKING: No modals/drawers for forms — forms are full pages
211
+ MODAL_IMPORTS=$(grep -rPn "import.*\b(Modal|Dialog|Drawer|Popup|Sheet)\b" "$PAGE_DIR" --include="*.tsx" 2>/dev/null)
212
+ if [ -n "$MODAL_IMPORTS" ]; then
213
+ echo "BLOCKING: Form modals/dialogs detected — forms MUST be full pages with own URL"
214
+ echo "$MODAL_IMPORTS"
215
+ # FIX REQUIRED before commit
216
+ fi
217
+ fi
218
+
219
+ if [ -n "$HOOK_DIR" ]; then
220
+ # BLOCKING: Hooks must use i18n for error messages
221
+ HARDCODED_ERRORS=$(grep -rPn "(setError|throw new Error)\(['\"][A-Z]" "$HOOK_DIR" --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v "t(" | head -10)
222
+ if [ -n "$HARDCODED_ERRORS" ]; then
223
+ echo "BLOCKING: Hardcoded error messages in hooks — MUST use t('{mod}:errors.xxx')"
224
+ echo "$HARDCODED_ERRORS" | head -5
225
+ # FIX REQUIRED before commit
226
+ fi
227
+ fi
228
+
229
+ # BLOCKING: i18n file structure — 4 languages with module-specific JSON files
230
+ if [ -n "$WEB_SRC" ]; then
231
+ I18N_DIR="$WEB_SRC/i18n/locales"
232
+ if [ -d "$I18N_DIR" ]; then
233
+ for LANG in fr en it de; do
234
+ if [ ! -d "$I18N_DIR/$LANG" ]; then
235
+ echo "BLOCKING: Missing i18n locale directory: $I18N_DIR/$LANG"
236
+ # FIX REQUIRED before commit
237
+ fi
238
+ MODULE_JSONS=$(find "$I18N_DIR/$LANG" -name "*.json" ! -name "common.json" ! -name "navigation.json" 2>/dev/null)
239
+ if [ -z "$MODULE_JSONS" ]; then
240
+ echo "BLOCKING: No module translation files in $I18N_DIR/$LANG/"
241
+ # FIX REQUIRED before commit
242
+ fi
243
+ done
244
+ else
245
+ echo "BLOCKING: Missing i18n/locales directory"
246
+ # FIX REQUIRED before commit
247
+ fi
248
+ fi
249
+
250
+ # Cross-validate route conventions (frontend vs backend)
251
+ APP_TSX=$(find . -name "App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
252
+ API_CONTROLLERS=$(find . -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
253
+ if [ -n "$APP_TSX" ] && [ -n "$API_CONTROLLERS" ]; then
254
+ API_SEGMENTS=$(grep -ohP '\[Route\("api/([^"]+)"\)\]' $API_CONTROLLERS | sed 's/\[Route("api\///;s/")\]//' | tr '/' '\n' | sort -u)
255
+ CLIENT_PATHS=$(grep -ohP "path:\s*['\"]([^'\"]+)['\"]" "$APP_TSX" | sed "s/path:\s*['\"]//;s/['\"]//" | sort -u)
256
+ for SEG in $API_SEGMENTS; do
257
+ if echo "$SEG" | grep -qP '[a-z]+-[a-z]+'; then
258
+ NO_HYPHEN=$(echo "$SEG" | tr -d '-')
259
+ if echo "$CLIENT_PATHS" | grep -q "$NO_HYPHEN"; then
260
+ echo "BLOCKING: Frontend uses '$NO_HYPHEN' but backend uses '$SEG' (kebab-case mismatch)"
261
+ # FIX REQUIRED before commit
262
+ fi
263
+ fi
264
+ done
265
+ fi
266
+ ```
267
+ If ANY POST-CHECK fails → fix the code → re-run ALL checks → loop until ALL pass.
268
+ **NEVER commit with failing POST-CHECKs.**
269
+
270
+ 3ter. **Dependency audit (if frontend tasks in batch):**
165
271
  ```bash
166
272
  cd {frontend_dir}
167
273
  npm ls --depth=0 2>&1 | grep "MISSING" && echo "FAIL: missing deps" && exit 1
@@ -203,7 +309,22 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
203
309
  ```
204
310
  If FAIL → migration is broken → fix → rebuild → DO NOT commit
205
311
 
206
- 5bis. **Core Seed Data Integrity (BLOCKING — if seed data tasks in batch):**
312
+ 5bis. **Navigation section route CRUD suffix check (BLOCKING — if seed data tasks in batch):**
313
+ ```bash
314
+ # Detect /list or /detail/:id in navigation section routes
315
+ SEED_NAV_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" 2>/dev/null)
316
+ if [ -n "$SEED_NAV_FILES" ]; then
317
+ CRUD_ROUTES=$(grep -rn 'Route.*=.*\/list\b\|Route.*=.*\/detail' $SEED_NAV_FILES 2>/dev/null | grep -v '//.*Route')
318
+ if [ -n "$CRUD_ROUTES" ]; then
319
+ echo "BLOCKING: Navigation section routes contain /list or /detail/:id suffixes"
320
+ echo "Convention: list → module route (no suffix), detail → module route + /:id"
321
+ echo "$CRUD_ROUTES"
322
+ # FIX REQUIRED before commit
323
+ fi
324
+ fi
325
+ ```
326
+
327
+ 5ter. **Core Seed Data Integrity (BLOCKING — if seed data tasks in batch):**
207
328
  ```bash
208
329
  # Verify NavigationApplicationSeedData.cs exists
209
330
  APP_SEED=$(find . -path "*/Seeding/Data/NavigationApplicationSeedData.cs" 2>/dev/null | head -1)