@atlashub/smartstack-cli 3.22.0 → 3.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/mcp-entry.mjs +143 -174
  2. package/dist/mcp-entry.mjs.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/mcp-scaffolding/component.tsx.hbs +21 -1
  5. package/templates/skills/apex/SKILL.md +21 -0
  6. package/templates/skills/apex/references/smartstack-api.md +507 -0
  7. package/templates/skills/apex/references/smartstack-frontend.md +1081 -0
  8. package/templates/skills/apex/references/smartstack-layers.md +166 -20
  9. package/templates/skills/apex/steps/step-00-init.md +27 -14
  10. package/templates/skills/apex/steps/step-01-analyze.md +45 -3
  11. package/templates/skills/apex/steps/step-02-plan.md +5 -1
  12. package/templates/skills/apex/steps/step-03-execute.md +51 -9
  13. package/templates/skills/apex/steps/step-04-validate.md +251 -0
  14. package/templates/skills/apex/steps/step-05-examine.md +7 -0
  15. package/templates/skills/apex/steps/step-07-tests.md +48 -5
  16. package/templates/skills/business-analyse/_shared.md +6 -6
  17. package/templates/skills/business-analyse/patterns/suggestion-catalog.md +1 -1
  18. package/templates/skills/business-analyse/questionnaire/07-ui.md +3 -3
  19. package/templates/skills/business-analyse/references/cadrage-pre-analysis.md +1 -1
  20. package/templates/skills/business-analyse/references/entity-architecture-decision.md +3 -3
  21. package/templates/skills/business-analyse/references/handoff-file-templates.md +13 -5
  22. package/templates/skills/business-analyse/references/spec-auto-inference.md +14 -14
  23. package/templates/skills/business-analyse/steps/step-01-cadrage.md +2 -2
  24. package/templates/skills/business-analyse/steps/step-02-decomposition.md +1 -1
  25. package/templates/skills/business-analyse/steps/step-03a1-setup.md +2 -2
  26. package/templates/skills/business-analyse/steps/step-03b-ui.md +2 -1
  27. package/templates/skills/business-analyse/steps/step-05a-handoff.md +15 -4
  28. package/templates/skills/business-analyse/templates/tpl-frd.md +2 -2
  29. package/templates/skills/business-analyse/templates-frd.md +2 -2
  30. package/templates/skills/ralph-loop/references/category-rules.md +45 -7
  31. package/templates/skills/ralph-loop/references/compact-loop.md +2 -2
  32. package/templates/skills/ralph-loop/references/core-seed-data.md +10 -0
  33. package/templates/skills/ralph-loop/steps/step-02-execute.md +110 -1
  34. package/templates/skills/validate-feature/steps/step-05-db-validation.md +86 -1
@@ -17,8 +17,9 @@
17
17
  | Validate | MCP `validate_conventions` |
18
18
 
19
19
  **Rules:**
20
- - Inherit `AuditableEntity`, implement `IHasData` for multi-tenant
21
- - Audit fields: CreatedAt, CreatedBy, ModifiedAt, ModifiedBy
20
+ - Inherit `BaseEntity`, implement `ITenantEntity` + `IAuditableEntity`
21
+ - See `references/smartstack-api.md` for exact BaseEntity API (Id, CreatedAt, UpdatedAt only)
22
+ - No Code/IsDeleted/RowVersion in BaseEntity — add business properties yourself
22
23
  - Domain events for state changes
23
24
  - Value objects for composite values
24
25
 
@@ -49,7 +50,8 @@
49
50
 
50
51
  ## Layer 1 — Application (parallel with API)
51
52
 
52
- **Services:** `Application/Services/{ContextPascal}/{App}/{Module}/`
53
+ **Services:** `Application/Services/{ContextPascal}/{App}/{Module}/` (interface)
54
+ **Service impls:** `Infrastructure/Services/{ContextPascal}/{App}/{Module}/` (implementation)
53
55
  **DTOs:** `Application/DTOs/{ContextPascal}/{App}/{Module}/`
54
56
  **Validators:** `Application/Validators/{ContextPascal}/{App}/{Module}/`
55
57
 
@@ -60,10 +62,13 @@
60
62
  | Validate | MCP `validate_conventions` |
61
63
 
62
64
  **Rules:**
65
+ - **ALL services MUST inject `ICurrentUser` and filter by `TenantId`** (see `smartstack-api.md` Service Pattern)
66
+ - **ALL services MUST inject `ILogger<T>`** for production diagnostics
63
67
  - CQRS with MediatR
64
68
  - FluentValidation for all commands
65
69
  - DTOs separate from domain entities
66
70
  - Service interfaces in Application, implementations in Infrastructure
71
+ - **FORBIDDEN:** `tenantId: Guid.Empty`, queries without TenantId filter, services without ICurrentUser
67
72
 
68
73
  ---
69
74
 
@@ -96,40 +101,107 @@
96
101
 
97
102
  **Folder:** `Infrastructure/Persistence/Seeding/Data/{ModulePascal}/`
98
103
 
104
+ > **Detailed templates:** See ralph-loop `references/core-seed-data.md` for complete C# code templates.
105
+ > Navigation hierarchy: Context → Application → Module → Section → Resource (ALL levels need seed data).
106
+
99
107
  | Action | Tool |
100
108
  |--------|------|
101
109
  | Generate permissions | MCP `generate_permissions` (PRIMARY) |
102
- | Navigation seed | Template below |
103
- | Roles seed | Template below |
104
- | Provider | Template below |
105
-
106
- ### Seed Data Chain (5 files)
107
-
108
- 1. **NavigationModuleSeedData.cs** — Deterministic GUIDs (SHA256), 4 languages
109
- 2. **PermissionsSeedData.cs** — MCP `generate_permissions` first, fallback template
110
- 3. **RolesSeedData.cs** — Context-based: Admin=CRUD, Manager=CRU, Contributor=CR, Viewer=R
111
- 4. **SeedConstants.cs** — Shared deterministic GUIDs
112
- 5. **{App}SeedDataProvider.cs** — Implements IClientSeedDataProvider
113
- - SeedNavigationAsync + SeedPermissionsAsync + SeedRolePermissionsAsync
110
+ | Navigation seed | Templates below |
111
+ | Roles seed | Templates below |
112
+ | Provider | Templates below |
113
+
114
+ ### Seed Data Chain (7 files minimum)
115
+
116
+ 1. **NavigationApplicationSeedData.cs** — Application-level navigation entry (MUST be first)
117
+ 2. **NavigationModuleSeedData.cs** — Deterministic GUIDs (SHA256), 4 languages (fr, en, it, de)
118
+ 3. **NavigationSectionSeedData.cs** — Section-level navigation (if sections defined)
119
+ 4. **NavigationResourceSeedData.cs** — Resource-level navigation (if resources defined)
120
+ 5. **PermissionsSeedData.cs** — MCP `generate_permissions` first, fallback template
121
+ 6. **RolesSeedData.cs** — Context-based: Admin=CRUD, Manager=CRU, Contributor=CR, Viewer=R
122
+ 7. **{App}SeedDataProvider.cs** — Implements IClientSeedDataProvider
123
+ - `SeedNavigationAsync()` — seeds Application → Module → Section → Resource + translations
124
+ - `SeedPermissionsAsync()` + `SeedRolePermissionsAsync()`
114
125
  - DI: `services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()`
115
126
 
127
+ ### Deterministic GUID Pattern
128
+
129
+ ```csharp
130
+ // Use SHA256 for deterministic GUIDs (reproducible across environments)
131
+ public static readonly Guid ModuleId = GenerateDeterministicGuid("nav-module-{app}-{module}");
132
+
133
+ private static Guid GenerateDeterministicGuid(string input)
134
+ {
135
+ var hash = System.Security.Cryptography.SHA256.HashData(
136
+ System.Text.Encoding.UTF8.GetBytes(input));
137
+ var bytes = new byte[16];
138
+ Array.Copy(hash, bytes, 16);
139
+ return new Guid(bytes);
140
+ }
141
+ ```
142
+
143
+ ### Route Convention (CRITICAL — Full Paths Required)
144
+
145
+ > **Routes stored in DB drive the platform menu AND application-tracking.**
146
+ > Short routes (e.g., `humanresources`) cause **400 Bad Request** on every page navigation.
147
+
148
+ **Route format: `/{context}/{app-kebab}/{module-kebab}/{section-kebab}`**
149
+
150
+ | Level | Code (C#) | Route (DB) |
151
+ |-------|-----------|-----------|
152
+ | Application | `humanresources` | `/business/human-resources` |
153
+ | Module | `employees` | `/business/human-resources/employees` |
154
+ | Section | `departments` | `/business/human-resources/employees/departments` |
155
+ | Resource | `export` | `/business/human-resources/employees/departments/export` |
156
+
157
+ **Platform examples (verified from SmartStack.app):**
158
+ - `/platform/administration` (not `administration`)
159
+ - `/platform/administration/users` (not `users`)
160
+ - `/personal/myspace/profile` (not `profile`)
161
+
162
+ - PascalCase for C# code identifiers (`HumanResources`)
163
+ - **kebab-case** for ALL URL routes in seed data (`human-resources`)
164
+ - **Routes MUST start with `/`** and include full parent hierarchy
165
+ - Helper: `ToKebabCase()` transforms PascalCase → kebab-case
166
+
167
+ ```csharp
168
+ private static string ToKebabCase(string value)
169
+ => System.Text.RegularExpressions.Regex.Replace(value, "(?<!^)([A-Z])", "-$1").ToLowerInvariant();
170
+
171
+ // Route construction:
172
+ var appRoute = $"/{ToKebabCase(contextCode)}/{ToKebabCase(appCode)}";
173
+ // → "/business/human-resources"
174
+
175
+ var moduleRoute = $"{appRoute}/{ToKebabCase(moduleCode)}";
176
+ // → "/business/human-resources/employees"
177
+
178
+ var sectionRoute = $"{moduleRoute}/{ToKebabCase(sectionCode)}";
179
+ // → "/business/human-resources/employees/departments"
180
+ ```
181
+
116
182
  **FORBIDDEN:**
117
183
  - `Guid.NewGuid()` → use deterministic GUIDs (SHA256)
118
184
  - Missing translations (must have fr, en, it, de)
119
185
  - Empty seed classes with no seeding logic
186
+ - PascalCase in route URLs → always kebab-case
187
+ - Missing NavigationApplicationSeedData → menu invisible
188
+ - **Short routes without `/` prefix** → `"humanresources"` must be `"/business/human-resources"`
189
+ - **Routes without parent hierarchy** → `"employees"` must be `"/business/human-resources/employees"`
120
190
 
121
191
  ---
122
192
 
123
193
  ## Layer 2 — Frontend (parallel with I18n)
124
194
 
195
+ > **Detailed patterns:** See `references/smartstack-frontend.md` for complete code templates.
196
+
125
197
  **Pages:** `src/pages/{ContextPascal}/{AppPascal}/{Module}/`
126
198
  **Components:** `src/components/{Module}/`
127
199
 
128
200
  | Action | Tool |
129
201
  |--------|------|
130
202
  | API client | MCP `scaffold_api_client` |
131
- | Routes | MCP `scaffold_routes` |
132
- | Complex pages | /ui-components skill |
203
+ | Routes | MCP `scaffold_routes` (outputFormat: `clientRoutes`) |
204
+ | Complex pages | /ui-components skill + `smartstack-frontend.md` patterns |
133
205
  | Validate routes | MCP `validate_frontend_routes` |
134
206
 
135
207
  **Layout mapping:**
@@ -140,21 +212,95 @@
140
212
  | `business.*` | `BusinessLayout` | `/business` |
141
213
  | `personal.*` | `UserLayout` | `/personal/myspace` |
142
214
 
215
+ ### Lazy Loading (MANDATORY)
216
+
217
+ ALL page components MUST be lazy-loaded using `React.lazy()`:
218
+
219
+ ```tsx
220
+ const EmployeesPage = lazy(() =>
221
+ import('@/pages/Business/HumanResources/Employees/EmployeesPage')
222
+ .then(m => ({ default: m.EmployeesPage }))
223
+ );
224
+
225
+ // Route element — ALWAYS wrap with Suspense
226
+ element: <Suspense fallback={<PageLoader />}><EmployeesPage /></Suspense>
227
+ ```
228
+
229
+ ### Page Structure Pattern
230
+
231
+ All pages MUST follow: hooks → useEffect(load) → loading state → error state → content.
232
+
233
+ ```tsx
234
+ // 1. Hooks at top
235
+ const { t } = useTranslation(['{module}']);
236
+ // 2. State
237
+ const [loading, setLoading] = useState(true);
238
+ // 3. useCallback + useEffect for data loading
239
+ // 4. if (loading) return <Loader2 spinner />
240
+ // 5. if (error) return <error UI with retry>
241
+ // 6. return <content with CSS variables>
242
+ ```
243
+
244
+ ### Components & CSS
245
+
143
246
  **Components:** SmartTable, SmartFilter, EntityCard, SmartForm, StatCard (NEVER raw HTML)
144
- **CSS:** Variables only → `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`
247
+ **CSS:** Variables only → `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`, `border-[var(--border-color)]`
248
+ **Loader:** `Loader2` from `lucide-react` for spinners, `PageLoader` for Suspense fallback
249
+
250
+ ### FK Fields in Forms (CRITICAL)
251
+
252
+ Any entity property that is a FK Guid (e.g., `EmployeeId`, `DepartmentId`) MUST use the `EntityLookup` component — NEVER a plain text input. Users cannot type GUIDs manually.
253
+
254
+ ```tsx
255
+ // CORRECT — EntityLookup for FK field
256
+ <EntityLookup
257
+ apiEndpoint="/api/business/human-resources/employees"
258
+ value={formData.employeeId}
259
+ onChange={(id) => handleChange('employeeId', id)}
260
+ label={t('module:form.employee', 'Employee')}
261
+ mapOption={(item) => ({ id: item.id, label: item.name, sublabel: item.code })}
262
+ required
263
+ />
264
+
265
+ // WRONG — plain text input for FK GUID
266
+ <input type="text" value={formData.employeeId} placeholder="Enter employee ID" />
267
+ ```
268
+
269
+ **Backend requirement:** Each target entity's GetAll endpoint MUST accept `?search=` parameter. See `smartstack-api.md` Service Pattern.
270
+
271
+ See `references/smartstack-frontend.md` section 6 for the full `EntityLookup` component definition and usage patterns.
145
272
 
146
273
  **FORBIDDEN:**
147
274
  - `src/pages/{Module}/` (flat, missing Context/App)
148
275
  - `import axios` → use `@/services/api/apiClient`
149
276
  - `<table>` → use SmartTable
150
- - Hardcoded colors → use CSS variables
277
+ - `<input type="text">` for FK Guid fields → use `EntityLookup`
278
+ - Placeholder "Enter ID" or "Enter GUID" → use `EntityLookup`
279
+ - Hardcoded Tailwind colors (`bg-white`, `text-gray-900`) → use CSS variables
280
+ - Static page imports in route files → use `React.lazy()`
281
+ - `<Suspense>` without `fallback` prop
151
282
  - Only fr/en → MUST have 4 languages
283
+ - `t('key')` without namespace prefix → use `t('ns:key', 'fallback')`
284
+ - Hardcoded user-facing strings in JSX → use `t()`
152
285
 
153
286
  ---
154
287
 
155
288
  ## Layer 2 — I18n
156
289
 
157
- 4 JSON files: fr, en, it, de identical key structures.
290
+ > **Template:** See `references/smartstack-frontend.md` Section 2 for complete JSON template.
291
+
292
+ 4 JSON files per module namespace: fr, en, it, de — identical key structures.
293
+
294
+ **Location:** `src/i18n/locales/{lang}/{module}.json`
295
+
296
+ **Required keys:** `title`, `description`, `actions`, `labels`, `columns`, `form`, `errors`, `validation`, `messages`, `empty`
297
+
298
+ **Usage pattern:**
299
+ ```tsx
300
+ const { t } = useTranslation(['{module}']);
301
+ t('{module}:title', 'Module Title') // ALWAYS with fallback
302
+ t('{module}:actions.create', 'Create entity') // ALWAYS with namespace prefix
303
+ ```
158
304
 
159
305
  ---
160
306
 
@@ -7,6 +7,14 @@ next_step: steps/step-01-analyze.md
7
7
 
8
8
  # Step 0: Initialize
9
9
 
10
+ **Before anything else**, display the version banner:
11
+
12
+ ```
13
+ ═══════════════════════════════════════════════════════════════
14
+ SmartStack APEX — v{{SMARTSTACK_VERSION}}
15
+ ═══════════════════════════════════════════════════════════════
16
+ ```
17
+
10
18
  ## LOAD SHARED
11
19
 
12
20
  Read `_shared.md` for SmartStack detection patterns and MCP tools reference.
@@ -133,20 +141,25 @@ IF save_mode:
133
141
  ## 7. Display Context Summary
134
142
 
135
143
  ```
136
- **APEX SmartStack - Initialization Complete**
137
-
138
- **Task:** {task_description}
139
- **Context:** {context_code} / {app_name} / {module_code}
140
- **Sections:** {sections}
141
-
142
- **Sources:**
143
- - PRD: {prd_path || "none"}
144
- - Feature: {feature_path || "none"}
145
-
146
- **Flags:** {active_flags}
147
- **MCP:** {available|degraded}
148
- **Needs migration:** {yes|no}
149
- **Needs seed data:** {yes|no}
144
+ ═══════════════════════════════════════════════════════════════
145
+ APEX INITIALIZATION COMPLETE
146
+ SmartStack CLI v{{SMARTSTACK_VERSION}}
147
+ ═══════════════════════════════════════════════════════════════
148
+
149
+ | Field | Value |
150
+ |--------------------|----------------------------------------------|
151
+ | Task | {task_description} |
152
+ | Context | {context_code} / {app_name} / {module_code} |
153
+ | Sections | {sections} |
154
+ | PRD | {prd_path || "none"} |
155
+ | Feature | {feature_path || "none"} |
156
+ | Flags | {active_flags} |
157
+ | MCP | {available|degraded} |
158
+ | Needs migration | {yes|no} |
159
+ | Needs seed data | {yes|no} |
160
+
161
+ NEXT STEP: step-01-analyze
162
+ ═══════════════════════════════════════════════════════════════
150
163
  ```
151
164
 
152
165
  ---
@@ -12,10 +12,28 @@ next_step: steps/step-02-plan.md
12
12
 
13
13
  ## LOAD CONDITIONALLY
14
14
 
15
+ - **ALWAYS** read `references/smartstack-api.md` — BaseEntity API, entity/config/controller patterns
15
16
  - If NOT `{economy_mode}`: read `references/agent-teams-protocol.md`
16
17
 
17
18
  ---
18
19
 
20
+ ## 0. Fresh Project Detection (Early Exit)
21
+
22
+ ```
23
+ IF .smartstack/init-state.json exists:
24
+ Read it → check if project was recently initialized
25
+ Glob("src/**/Entities/**/*.cs") → count entity files
26
+
27
+ IF entity count == 0 AND no PRD AND no feature.json:
28
+ → SKIP full code exploration (sections 2-3)
29
+ → Declare: "Fresh project — all elements need to be CREATED"
30
+ → Jump directly to section 4 (Gap Analysis) with all items marked "create"
31
+ ```
32
+
33
+ This saves ~2 minutes of Glob searches on an empty project.
34
+
35
+ ---
36
+
19
37
  ## 1. Context Sources
20
38
 
21
39
  Read available context (in order of priority):
@@ -118,7 +136,31 @@ Identify:
118
136
 
119
137
  ---
120
138
 
121
- ## 4. Gap Analysis
139
+ ## 4. FK Field Detection
140
+
141
+ For each entity found (or to be created), identify FK relationships:
142
+
143
+ ```
144
+ For each entity in analysis results:
145
+ - List properties ending in "Id" with a matching navigation property (e.g., EmployeeId + Employee)
146
+ - Record: { fkProperty, targetEntity, isRequired }
147
+
148
+ Output:
149
+ fkFields: [
150
+ { entity: "TimeEntry", fkProperty: "EmployeeId", targetEntity: "Employee", isRequired: true },
151
+ { entity: "TimeEntry", fkProperty: "ProjectId", targetEntity: "Project", isRequired: true }
152
+ ]
153
+ ```
154
+
155
+ **Why:** FK fields drive two critical downstream requirements:
156
+ 1. **Frontend:** Each FK field MUST use `EntityLookup` component (NEVER plain text input for GUIDs)
157
+ 2. **Backend:** Each target entity's GetAll endpoint MUST support `?search=` query parameter
158
+
159
+ These are propagated to step-02 (plan) and step-03 (execute).
160
+
161
+ ---
162
+
163
+ ## 5. Gap Analysis
122
164
 
123
165
  Compare what EXISTS vs what the TASK REQUIRES:
124
166
 
@@ -131,7 +173,7 @@ For each element in the task description:
131
173
 
132
174
  ---
133
175
 
134
- ## 5. Analysis Summary
176
+ ## 6. Analysis Summary
135
177
 
136
178
  ```
137
179
  **APEX SmartStack - Analysis Complete**
@@ -158,7 +200,7 @@ For each element in the task description:
158
200
 
159
201
  ---
160
202
 
161
- ## 6. Save Output (if save_mode)
203
+ ## 7. Save Output (if save_mode)
162
204
 
163
205
  Write to `{output_dir}/01-analyze.md` with analysis results.
164
206
 
@@ -63,9 +63,13 @@ For EACH file in the plan, specify HOW it will be created/modified:
63
63
  | # | File | Action | Tool |
64
64
  |---|------|--------|------|
65
65
  | 10 | src/pages/{Ctx}/{App}/{Mod}/ListPage.tsx | create | /ui-components skill |
66
+ | 10b | src/pages/{Ctx}/{App}/{Mod}/CreatePage.tsx | create | /ui-components skill (EntityLookup for FK fields) |
67
+ | 10c | src/pages/{Ctx}/{App}/{Mod}/EditPage.tsx | create | /ui-components skill (EntityLookup for FK fields) |
66
68
  | 11 | src/services/api/{module}Api.ts | create | MCP scaffold_api_client |
67
69
  | 12 | src/routes/{module}.tsx | create | MCP scaffold_routes |
68
- | 13 | src/locales/fr/{module}.json | create | manual (4 languages) |
70
+ | 13 | src/i18n/locales/{lang}/{module}.json | create | ref smartstack-frontend.md (4 languages: fr, en, it, de) |
71
+
72
+ **FK Field Guidance:** If step-01 identified `fkFields[]`, every Create/Edit page MUST use `EntityLookup` for those fields (see `smartstack-frontend.md` section 6). The corresponding backend GetAll endpoints (Layer 1) MUST support `?search=` parameter.
69
73
 
70
74
  ### Layer 3 — Tests (sequential, if -t)
71
75
 
@@ -13,6 +13,8 @@ All code goes through skills (/controller, /application, /ui-components, /efcore
13
13
 
14
14
  ## LOAD CONDITIONALLY
15
15
 
16
+ - **ALWAYS** read `references/smartstack-api.md` — BaseEntity API, entity/config/controller patterns
17
+ - **ALWAYS** read `references/smartstack-frontend.md` — lazy loading, i18n, page structure, CSS variables
16
18
  - Read `references/smartstack-layers.md` for execution rules per layer
17
19
  - If NOT `{economy_mode}` AND Layer 1 has parallel work: read `references/agent-teams-protocol.md`
18
20
 
@@ -25,7 +27,8 @@ All code goes through skills (/controller, /application, /ui-components, /efcore
25
27
  ```
26
28
  For each entity to create/modify:
27
29
  → MCP scaffold_extension (type: "entity", target: entity_name)
28
- → Verify: inherits AuditableEntity, has IHasData if multi-tenant
30
+ → Verify: inherits BaseEntity, implements ITenantEntity + IAuditableEntity
31
+ → Verify entity matches patterns in references/smartstack-api.md
29
32
  ```
30
33
 
31
34
  ### EF Core Configurations
@@ -43,7 +46,7 @@ For each entity:
43
46
  1. MCP suggest_migration → get standardized name
44
47
  2. dotnet ef migrations add {Name} --project src/{Infra}.csproj --startup-project src/{Api}.csproj -o Persistence/Migrations
45
48
  3. dotnet ef database update (if local DB)
46
- 4. dotnet build --no-restore → MUST PASS
49
+ 4. dotnet build → MUST PASS
47
50
  ```
48
51
 
49
52
  **BLOCKING:** If build fails after migration, fix EF configs before proceeding.
@@ -51,10 +54,10 @@ For each entity:
51
54
  ### Post-Layer 0 Build Gate
52
55
 
53
56
  ```bash
54
- dotnet build --no-restore
57
+ dotnet build
55
58
  ```
56
59
 
57
- **MUST PASS before Layer 1. If failure, fix and retry.**
60
+ **MUST PASS before Layer 1. If NuGet error, run `dotnet restore` first. If file lock (MSB3021), use `--output /tmp/{project}_build`.**
58
61
 
59
62
  ---
60
63
 
@@ -64,6 +67,18 @@ dotnet build --no-restore
64
67
 
65
68
  Execute each item from the plan sequentially using skills and MCP.
66
69
 
70
+ **For frontend tasks (economy_mode):** Follow the same rules as exec-frontend above:
71
+ - `MCP scaffold_api_client` → API client + types + React Query hook
72
+ - `MCP scaffold_routes` with `outputFormat: 'clientRoutes'` for lazy imports
73
+ - Pages: use `/ui-components` skill — MANDATORY for entity lists, grids, tables, dashboards
74
+ - **Form pages: Create `EntityCreatePage.tsx` (route: `/create`) and `EntityEditPage.tsx` (route: `/:id/edit`)**
75
+ - **FK FIELDS (CRITICAL):** Any Guid FK property (e.g., EmployeeId, DepartmentId) MUST use `EntityLookup` component — NEVER a plain text input. See `smartstack-frontend.md` section 6.
76
+ - **ZERO modals/popups/drawers for forms — ALL forms are full pages with their own URL**
77
+ - **Form tests: Generate `EntityCreatePage.test.tsx` and `EntityEditPage.test.tsx` (co-located)**
78
+ - Read `references/smartstack-frontend.md` for mandatory patterns (sections 3b + 8)
79
+ - Generate i18n JSON files for all 4 languages (fr, en, it, de) — `src/i18n/locales/{lang}/{module}.json`
80
+ - All pages must follow loading → error → content pattern with CSS variables
81
+
67
82
  ### If NOT economy_mode: Agent Teams (parallel)
68
83
 
69
84
  > **Protocol:** See `references/agent-teams-protocol.md`
@@ -80,6 +95,7 @@ Spawn 2 teammates (Opus, full tools):
80
95
  For each task:
81
96
  - Application services/DTOs: MCP scaffold_extension
82
97
  - Controllers: use /controller skill for complex, MCP scaffold_extension for simple
98
+ - IMPORTANT: ALL GetAll endpoints MUST support ?search= query parameter (enables EntityLookup on frontend)
83
99
  - Seed data: MCP generate_permissions, then follow smartstack-layers.md templates
84
100
 
85
101
  After ALL tasks done:
@@ -89,11 +105,37 @@ Spawn 2 teammates (Opus, full tools):
89
105
  "Execute these Layer 1 frontend tasks for module {module_code}:
90
106
  {list of frontend + i18n tasks from plan}
91
107
 
108
+ **MANDATORY: Read references/smartstack-frontend.md FIRST** — contains all required patterns.
109
+
92
110
  For each task:
93
111
  - API client: MCP scaffold_api_client
94
- - Routes: MCP scaffold_routes
95
- - Pages: use /ui-components skill
96
- - I18n: 4 languages (fr, en, it, de)
112
+ - Routes: MCP scaffold_routes (outputFormat: 'clientRoutes') → generates lazy imports + Suspense
113
+ - Pages: use /ui-components skill — MUST follow smartstack-frontend.md patterns:
114
+ React.lazy() for all page imports (named export wrapping)
115
+ → <Suspense fallback={<PageLoader />}> around all lazy components
116
+ → Page structure: hooks → useEffect(load) → loading → error → content
117
+ → CSS variables only: bg-[var(--bg-card)], text-[var(--text-primary)]
118
+ → SmartTable/SmartFilter/EntityCard (NEVER raw HTML)
119
+ - **FORM PAGES (CRITICAL):** Create/Edit forms are FULL PAGES with own routes:
120
+ → EntityCreatePage.tsx with route /{module}/create
121
+ → EntityEditPage.tsx with route /{module}/:id/edit
122
+ → ZERO modals/popups/drawers/dialogs for forms
123
+ → Back button with navigate(-1) on every form page
124
+ → See smartstack-frontend.md section 3b for templates
125
+ - **FK FIELDS (CRITICAL):** Foreign key Guid fields (e.g., EmployeeId) MUST use EntityLookup:
126
+ → NEVER render FK fields as plain text inputs — users cannot type GUIDs
127
+ → Use EntityLookup from @/components/ui/EntityLookup for searchable selection
128
+ → Each FK field needs: apiEndpoint, mapOption (display name), search support on backend
129
+ → See smartstack-frontend.md section 6 for the full EntityLookup pattern
130
+ - **FORM TESTS (MANDATORY):**
131
+ → EntityCreatePage.test.tsx (co-located next to page)
132
+ → EntityEditPage.test.tsx (co-located next to page)
133
+ → Cover: rendering, validation, submit, pre-fill, navigation, errors
134
+ → See smartstack-frontend.md section 8 for test templates
135
+ - I18n: Generate 4 JSON files per module namespace (fr, en, it, de)
136
+ → Follow JSON template from smartstack-frontend.md
137
+ → Keys: actions, labels, errors, validation, columns, form, messages, empty
138
+ → ALL t() calls MUST use namespace prefix + fallback: t('ns:key', 'Default text')
97
139
  - MUST use src/pages/{Context}/{App}/{Module}/ hierarchy (NOT flat)
98
140
 
99
141
  After ALL tasks done:
@@ -102,7 +144,7 @@ Spawn 2 teammates (Opus, full tools):
102
144
  Wait for both teammates to report completion.
103
145
 
104
146
  Build verification:
105
- dotnet build --no-restore (backend)
147
+ dotnet build (backend)
106
148
  npm run typecheck (frontend, if applicable)
107
149
 
108
150
  shutdown_request → shutdown_response → TeamDelete("apex-exec")
@@ -136,7 +178,7 @@ After Layer 1 completes:
136
178
  - DI registration added
137
179
 
138
180
  2. Build gate:
139
- dotnet build --no-restore → MUST PASS
181
+ dotnet build → MUST PASS
140
182
  npm run typecheck → MUST PASS (if frontend)
141
183
  ```
142
184