@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.
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -3
- package/templates/project/api.ts.template +4 -2
- package/templates/project/appsettings.json.template +1 -1
- package/templates/skills/apex/_shared.md +13 -0
- package/templates/skills/apex/references/post-checks.md +228 -6
- package/templates/skills/apex/references/smartstack-api.md +67 -17
- package/templates/skills/apex/references/smartstack-frontend.md +41 -1
- package/templates/skills/apex/references/smartstack-layers.md +40 -10
- package/templates/skills/apex/steps/step-02-plan.md +16 -11
- package/templates/skills/apex/steps/step-03-execute.md +6 -0
- package/templates/skills/apex/steps/step-04-examine.md +4 -2
- package/templates/skills/application/references/frontend-verification.md +26 -1
- package/templates/skills/application/steps/step-03-roles.md +1 -1
- package/templates/skills/application/steps/step-05-frontend.md +24 -8
- package/templates/skills/application/templates-frontend.md +41 -22
- package/templates/skills/application/templates-seed.md +53 -16
- package/templates/skills/business-analyse/SKILL.md +4 -2
- package/templates/skills/business-analyse/_shared.md +17 -4
- package/templates/skills/business-analyse/react/schema.md +1 -1
- package/templates/skills/business-analyse/references/agent-module-prompt.md +11 -9
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +4 -3
- package/templates/skills/business-analyse/references/deploy-modes.md +1 -1
- package/templates/skills/business-analyse/references/handoff-file-templates.md +4 -4
- package/templates/skills/business-analyse/references/robustness-checks.md +12 -9
- package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
- package/templates/skills/business-analyse/references/ui-resource-cards.md +3 -3
- package/templates/skills/business-analyse/references/validation-checklist.md +21 -3
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +33 -5
- package/templates/skills/business-analyse/steps/step-03b-ui.md +2 -2
- package/templates/skills/business-analyse/steps/step-03c-compile.md +17 -9
- package/templates/skills/business-analyse/steps/step-03d-validate.md +1 -1
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +5 -3
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +24 -16
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +2 -2
- package/templates/skills/business-analyse/templates/tpl-handoff.md +10 -8
- package/templates/skills/business-analyse/templates/tpl-progress.md +7 -6
- package/templates/skills/ralph-loop/references/category-rules.md +104 -9
- package/templates/skills/ralph-loop/references/compact-loop.md +124 -3
- package/templates/skills/ralph-loop/references/core-seed-data.md +158 -38
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +3 -3
- package/templates/skills/ralph-loop/steps/step-02-execute.md +311 -15
- package/templates/skills/ralph-loop/steps/step-03-commit.md +2 -2
- package/templates/skills/ralph-loop/steps/step-04-check.md +4 -3
- 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
|
-
□
|
|
32
|
-
□
|
|
33
|
-
□
|
|
34
|
-
□
|
|
35
|
-
□
|
|
36
|
-
|
|
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
|
-
**
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
|
|
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**
|
|
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
|
|
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. **
|
|
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. **
|
|
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)
|