@atlashub/smartstack-cli 3.53.0 → 4.0.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.
@@ -16,8 +16,8 @@ All code goes through skills (/controller, /application, /ui-components, /efcore
16
16
  > **CONTEXT REUSE:** `smartstack-api.md` (loaded in step-01) and `smartstack-layers.md` (loaded in step-02) are already in context. Do NOT re-read them.
17
17
 
18
18
  - **ALWAYS** read `references/smartstack-frontend.md` — lazy loading, i18n, page structure, CSS variables, EntityLookup, compliance gates (sections 1-9)
19
- - If NOT `{economy_mode}` AND Layer 1 has parallel work: read `references/agent-teams-protocol.md`
20
- - If `{delegate_mode}` AND seedData tasks exist: read `references/core-seed-data.md` — comprehensive seed data templates
19
+ - **ALWAYS** read `references/core-seed-data.md` comprehensive seed data templates (Layer 1)
20
+ - If NOT `{economy_mode}` AND a layer has multi-entity work: read `references/agent-teams-protocol.md`
21
21
  - If build failure during execution: read `references/error-classification.md` — error diagnosis categories A-F
22
22
 
23
23
  ---
@@ -30,9 +30,10 @@ This is a foundation-only execution (called by ralph-loop Phase 0). Execute ONLY
30
30
  - Layer 0: Domain entities + EF configs + Migration
31
31
 
32
32
  **SKIP ALL OTHER LAYERS:**
33
- - Layer 1: Application + API + Seed Data → SKIP
34
- - Layer 2: Frontend → SKIP
35
- - Layer 3: Tests → SKIP
33
+ - Layer 1: Seed Data → SKIP
34
+ - Layer 2: Backend → SKIP
35
+ - Layer 3: Frontend → SKIP
36
+ - Layer 4: DevData → SKIP
36
37
 
37
38
  After Layer 0 completes and builds successfully:
38
39
  - Commit with message: `chore(foundation): entities for {module_code}`
@@ -40,7 +41,7 @@ After Layer 0 completes and builds successfully:
40
41
  - End execution
41
42
 
42
43
  **IF `{foundation_mode}` == false:**
43
- Execute ALL layers normally (Layer 0 → Layer 1 → Layer 2 → Layer 3).
44
+ Execute ALL layers normally (Layer 0 → Layer 1 → Layer 2 → Layer 3 → Layer 4).
44
45
 
45
46
  ---
46
47
 
@@ -107,137 +108,233 @@ dotnet build
107
108
 
108
109
  **MUST PASS before Layer 1. If NuGet error, run `dotnet restore` first. If file lock (MSB3021), use `--output /tmp/{project}_build`.**
109
110
 
111
+ ### Layer 0 Commit
112
+
113
+ ```
114
+ feat({module}): [domain+infra] {short description}
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Layer 1 — Seed Data (DEDICATED LAYER — sequential, agent principal)
120
+
121
+ > **This layer is DEDICATED and MANDATORY.** Seed data makes modules visible in the UI.
122
+ > Without seed data, the module exists in code but is invisible to users.
123
+ > Reference: `references/core-seed-data.md` (loaded above) for complete C# templates.
124
+
125
+ ### Application-Level Seed Data (ONCE per application)
126
+
127
+ ```
128
+ 1. NavigationApplicationSeedData.cs
129
+ → Application-level navigation entry (MUST be first)
130
+ → Random GUID via Guid.NewGuid()
131
+ → 4 language translations (fr, en, it, de)
132
+
133
+ 2. ApplicationRolesSeedData.cs
134
+ → 4 roles: admin, manager, contributor, viewer
135
+ → Random GUIDs (Guid.NewGuid())
136
+ → References NavigationApplicationSeedData.ApplicationId
137
+ ```
138
+
139
+ ### Per-Module Seed Data
140
+
141
+ ```
142
+ 3. NavigationModuleSeedData.cs
143
+ → Random GUIDs (Guid.NewGuid()), 4 languages (fr, en, it, de)
144
+ → GetModuleEntry() + GetTranslationEntries()
145
+ → If sections defined: GetSectionEntries() + GetSectionTranslationEntries()
146
+ → If resources defined: GetResourceEntries() + resource translations
147
+ → Query actual parent from DB for FK (NOT deterministic GUID)
148
+
149
+ 4. Permissions.cs
150
+ → MCP generate_permissions (PRIMARY tool)
151
+ → Static constants: public static class {Module} { public const string Read = "..."; }
152
+ → Permission paths MUST use kebab-case matching NavRoute codes
153
+
154
+ 5. PermissionsSeedData.cs
155
+ → MCP generate_permissions first, fallback template
156
+ → Paths match Permissions.cs, wildcard + CRUD
157
+
158
+ 6. RolesSeedData.cs
159
+ → Admin=wildcard(*), Manager=CRU, Contributor=CR, Viewer=R
160
+ → Code-based role mapping (NEVER deterministic GUIDs for roles)
161
+ → Look up roles by Code at runtime
162
+ ```
163
+
164
+ ### Infrastructure Provider (ONCE per application)
165
+
166
+ ```
167
+ 7. {App}SeedDataProvider.cs
168
+ → Implements IClientSeedDataProvider
169
+ → SeedNavigationAsync(): Application → Module → Section → Resource + translations
170
+ → SeedRolesAsync(): application-scoped roles from ApplicationRolesSeedData
171
+ → SeedPermissionsAsync(): permission entries from PermissionsSeedData
172
+ → SeedRolePermissionsAsync(): maps roles to permissions (by Code, NOT by GUID)
173
+ → DI: services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()
174
+ ```
175
+
176
+ ### Post-Layer 1 Build Gate
177
+
178
+ ```bash
179
+ dotnet build
180
+ ```
181
+
182
+ **MUST PASS before Layer 2.**
183
+
184
+ ### Layer 1 Commit
185
+
186
+ ```
187
+ feat({module}): [seed] navigation, permissions, roles
188
+ ```
189
+
110
190
  ---
111
191
 
112
- ## Layer 1Application + API + Seed Data
192
+ ## Layer 2Backend (Services + Controllers)
113
193
 
114
- > **Layer 1 rules** are in `references/smartstack-layers.md` (already in context from step-02):
115
- > - NavRoute and permission kebab-case (Layer 1 - API section)
194
+ > **Layer 2 rules** are in `references/smartstack-layers.md` (already in context from step-02):
195
+ > - NavRoute and permission kebab-case (Layer 2 - API section)
116
196
  > - Controller route attributes (FORBIDDEN: [Route] alongside [NavRoute])
117
197
  > - Validators DI registration
118
198
  > - DateOnly vs string for DTO date fields
119
199
  > - Code generation patterns (ICodeGenerator<T> registration, see references/code-generation.md)
120
200
 
121
- ### Backend Tasks (sequential or parallel)
201
+ ### Backend Tasks (sequential or parallel within layer)
122
202
 
123
203
  - **Services/DTOs:** MCP scaffold_extension
124
204
  - **Controllers:** use /controller skill for complex, MCP scaffold_extension for simple
125
205
  - **IMPORTANT:** ALL GetAll endpoints MUST support `?search=` query parameter (enables EntityLookup on frontend)
126
- - **Seed data:** MCP generate_permissions, then follow smartstack-layers.md templates
127
206
 
128
- ### Frontend Tasks (sequential or parallel)
207
+ ### Skill Delegation
129
208
 
130
- > **Frontend patterns** are in `references/smartstack-frontend.md` (already loaded above):
131
- > - API client generation (MCP scaffold_api_client)
132
- > - Route scaffolding (MCP scaffold_routes) section 1 + 3b
133
- > - Page types (ListPage, DetailPage, CreatePage, EditPage) section 3
134
- > - FK field handling (EntityLookup component) section 6
135
- > - Form structure (ZERO modals all full pages) — section 3b
136
- > - Detail page tabs (local state only) section 3 "Tab Behavior Rules"
137
- > - Testing patterns (co-located form tests) section 8
138
- > - Section-level routes and permissions — section 3b
139
- > - I18n JSON structure and registration — section 2
140
- > - Compliance gates (5 mandatory checks) — section 9
209
+ | Skill | When | Context to provide |
210
+ |-------|------|--------------------|
211
+ | /controller | Custom routes, complex auth, file upload | entity, CRUD actions, permissions, routes |
212
+ | /application | Full app/module from scratch | app, module names |
213
+ | /ui-components | Complex pages (tables, grids, dashboards) | entity, fields, page type |
214
+ | /efcore | Complex EF configs, inheritance | relationships, indexes |
215
+ | /notification | In-app or email notifications | trigger, recipients, template |
216
+ | /workflow | Automated workflows | trigger, steps, conditions |
141
217
 
142
- ### If NOT economy_mode: Agent Teams (parallel)
218
+ ### If NOT economy_mode AND multiple entities: Agent Teams (parallel within layer)
143
219
 
144
220
  > **Protocol:** See `references/agent-teams-protocol.md`
145
221
 
146
222
  ```
147
- TeamCreate("apex-exec", description: "Execute Layer 1 in parallel")
148
-
149
- Spawn 2 teammates (Opus, full tools):
223
+ TeamCreate("apex-layer2", description: "Execute Layer 2 backend in parallel")
150
224
 
151
- 1. exec-backend (team_name: "apex-exec", name: "exec-backend"):
152
- "Execute these Layer 1 backend tasks for module {module_code}:
153
- {list of application + api + seed data tasks from plan}
225
+ Spawn 1 teammate per entity (Opus, full tools):
154
226
 
155
- For each task:
156
- - Application services/DTOs: MCP scaffold_extension
157
- - Controllers: use /controller skill for complex, MCP scaffold_extension for simple
158
- - IMPORTANT: ALL GetAll endpoints MUST support ?search= query parameter (enables EntityLookup on frontend)
159
- - Seed data: MCP generate_permissions, then follow smartstack-layers.md templates
227
+ For each entity:
228
+ Task: "Execute Layer 2 backend for entity {EntityName}:
229
+ - Application service/DTO: MCP scaffold_extension
230
+ - Controller: /controller skill or MCP scaffold_extension
231
+ - IMPORTANT: GetAll endpoint MUST support ?search= parameter
232
+ - Validators: FluentValidation + DI registration
160
233
 
161
234
  After ALL tasks done:
162
- SendMessage(type:'message', recipient:'team-lead', content:'BACKEND_COMPLETE', summary:'Backend layer done')"
235
+ SendMessage(type:'message', recipient:'team-lead', content:'ENTITY_COMPLETE: {EntityName}', summary:'{EntityName} backend done')"
163
236
 
164
- 2. exec-frontend (team_name: "apex-exec", name: "exec-frontend"):
165
- "Execute these Layer 1 frontend tasks for module {module_code}:
166
- {list of frontend + i18n tasks from plan}
237
+ Wait for all teammates to report completion.
238
+ shutdown_request shutdown_response TeamDelete("apex-layer2")
239
+ ```
167
240
 
168
- **MANDATORY: Read references/smartstack-frontend.md FIRST** contains all required patterns.
241
+ ### Post-Layer 2 Build Gate
169
242
 
170
- For each task:
171
- - API client: MCP scaffold_api_client
172
- - Routes: MCP scaffold_routes (outputFormat: 'clientRoutes') → generates lazy imports + Suspense
173
- - Pages: use /ui-components skill — MUST follow smartstack-frontend.md patterns:
174
- → React.lazy() for all page imports (named export wrapping)
175
- → <Suspense fallback={<PageLoader />}> around all lazy components
176
- → Page structure: hooks → useEffect(load) → loading → error → content
177
- → CSS variables only: bg-[var(--bg-card)], text-[var(--text-primary)]
178
- → SmartTable/SmartFilter/EntityCard (NEVER raw HTML)
179
- - **FORM PAGES (CRITICAL):** Create/Edit forms are FULL PAGES with own routes:
180
- → EntityCreatePage.tsx with route /{module}/create
181
- → EntityEditPage.tsx with route /{module}/:id/edit
182
- → ZERO modals/popups/drawers/dialogs for forms
183
- → Back button with navigate(-1) on every form page
184
- → See smartstack-frontend.md section 3b for templates
185
- - **TABS ON DETAIL PAGES (CRITICAL):** Tabs MUST switch content LOCALLY:
186
- → Tab click handler: setActiveTab(tabKey) ONLY — NEVER navigate() to another page
187
- → Tab content: render inline with {activeTab === 'tabKey' && <TabContent />}
188
- → Sub-resource data: fetch via API filtered by parent ID, display in tab panel
189
- → FORBIDDEN: navigate('../leaves?employee=${id}') in tab handler
190
- → See smartstack-frontend.md section 3 'Tab Behavior Rules'
191
- - **FK FIELDS (CRITICAL):** Foreign key Guid fields (e.g., EmployeeId) MUST use EntityLookup:
192
- → NEVER render FK fields as `<input>` — users cannot type GUIDs
193
- → NEVER render FK fields as `<select>` — even with API-loaded options, `<select>` is NOT acceptable
194
- → ONLY use `<EntityLookup />` from @/components/ui/EntityLookup for searchable selection
195
- → Each FK field needs: apiEndpoint, mapOption (display name), search support on backend
196
- → FORBIDDEN: `<select value={formData.departmentId}>`, `<option value={dept.id}>`, `e.target.value` for FK fields
197
- → See smartstack-frontend.md section 6 for the full EntityLookup pattern
198
- - **FORM TESTS (MANDATORY):**
199
- → EntityCreatePage.test.tsx (co-located next to page)
200
- → EntityEditPage.test.tsx (co-located next to page)
201
- → Cover: rendering, validation, submit, pre-fill, navigation, errors
202
- → See smartstack-frontend.md section 8 for test templates
203
- - **PERMISSIONS:** Call MCP generate_permissions for the module permission root (2 segments: {app}.{module}),
204
- then also call MCP generate_permissions for EACH section (3 segments: {app}.{module}.{section}).
205
- - **SECTION ROUTES:** Add section child routes to the module's children array.
206
- Wire PermissionGuard for section routes with section-level permissions.
207
- - I18n: Generate 4 JSON files per module namespace (fr, en, it, de)
208
- → Follow JSON template from smartstack-frontend.md
209
- → Keys: actions, labels, errors, validation, columns, form, messages, empty
210
- → ALL t() calls MUST use namespace prefix + fallback: t('ns:key', 'Default text')
211
- - MUST use src/pages/{App}/{Module}/ hierarchy (NOT flat)
243
+ ```bash
244
+ dotnet build
245
+ ```
212
246
 
213
- After ALL tasks done:
214
- SendMessage(type:'message', recipient:'team-lead', content:'FRONTEND_COMPLETE', summary:'Frontend layer done')"
247
+ **MUST PASS before backend tests.**
215
248
 
216
- Wait for both teammates to report completion.
249
+ ### Backend Tests Inline
217
250
 
218
- Build verification:
219
- dotnet build (backend)
220
- npm run typecheck (frontend, if applicable)
251
+ > **Tests are scaffolded and run WITHIN Layer 2, not deferred to step-07.**
221
252
 
222
- shutdown_request → shutdown_response → TeamDelete("apex-exec")
253
+ ```
254
+ 1. Scaffold backend tests:
255
+ → MCP scaffold_tests (target_layer: "domain", module: "{module_code}", test_type: "unit")
256
+ → MCP scaffold_tests (target_layer: "application", module: "{module_code}", test_type: "unit")
257
+ → MCP scaffold_tests (target_layer: "api", module: "{module_code}", test_type: "integration")
258
+
259
+ 2. Run tests:
260
+ dotnet test --no-build --verbosity normal
261
+
262
+ 3. Fix loop (max 3 iterations):
263
+ IF tests fail:
264
+ → Identify root cause (ALWAYS code bug, not test bug)
265
+ → Fix production CODE via appropriate skill/MCP
266
+ → dotnet build --no-restore
267
+ → dotnet test --no-build
268
+ → Repeat until pass or max 3
269
+
270
+ 4. If still failing after 3 iterations: note failures, continue to Layer 3.
271
+ Step-07 "Final Test Sweep" will handle remaining failures.
223
272
  ```
224
273
 
225
- ---
226
-
227
- ## Layer 1 — Skill Delegation
274
+ ### Layer 2 Commits
228
275
 
229
- | Skill | When | Context to provide |
230
- |-------|------|--------------------|
231
- | /controller | Custom routes, complex auth, file upload | entity, CRUD actions, permissions, routes |
232
- | /application | Full app/module from scratch | app, module names |
233
- | /ui-components | Complex pages (tables, grids, dashboards) | entity, fields, page type |
234
- | /efcore | Complex EF configs, inheritance | relationships, indexes |
235
- | /notification | In-app or email notifications | trigger, recipients, template |
236
- | /workflow | Automated workflows | trigger, steps, conditions |
276
+ ```
277
+ feat({module}): [app+api] {short description}
278
+ test({module}): backend unit and integration tests
279
+ ```
237
280
 
238
281
  ---
239
282
 
240
- ## Layer 2bDocumentation (after frontend pages exist)
283
+ ## Layer 3Frontend (Pages + I18n + Documentation)
284
+
285
+ > **Frontend patterns** are in `references/smartstack-frontend.md` (already loaded above):
286
+ > - API client generation (MCP scaffold_api_client)
287
+ > - Route scaffolding (MCP scaffold_routes) — section 1 + 3b
288
+ > - Page types (ListPage, DetailPage, CreatePage, EditPage) — section 3
289
+ > - FK field handling (EntityLookup component) — section 6
290
+ > - Form structure (ZERO modals — all full pages) — section 3b
291
+ > - Detail page tabs (local state only) — section 3 "Tab Behavior Rules"
292
+ > - Testing patterns (co-located form tests) — section 8
293
+ > - Section-level routes and permissions — section 3b
294
+ > - I18n JSON structure and registration — section 2
295
+ > - Compliance gates (5 mandatory checks) — section 9
296
+
297
+ ### Frontend Tasks (sequential or parallel within layer)
298
+
299
+ For each module:
300
+ - **API client:** MCP scaffold_api_client
301
+ - **Routes:** MCP scaffold_routes (outputFormat: 'clientRoutes') → generates lazy imports + Suspense
302
+ - **Pages:** use /ui-components skill — MUST follow smartstack-frontend.md patterns:
303
+ → React.lazy() for all page imports (named export wrapping)
304
+ → `<Suspense fallback={<PageLoader />}>` around all lazy components
305
+ → Page structure: hooks → useEffect(load) → loading → error → content
306
+ → CSS variables only: bg-[var(--bg-card)], text-[var(--text-primary)]
307
+ → SmartTable/SmartFilter/EntityCard (NEVER raw HTML)
308
+ - **FORM PAGES (CRITICAL):** Create/Edit forms are FULL PAGES with own routes:
309
+ → EntityCreatePage.tsx with route /{module}/create
310
+ → EntityEditPage.tsx with route /{module}/:id/edit
311
+ → ZERO modals/popups/drawers/dialogs for forms
312
+ → Back button with navigate(-1) on every form page
313
+ → See smartstack-frontend.md section 3b for templates
314
+ - **TABS ON DETAIL PAGES (CRITICAL):** Tabs MUST switch content LOCALLY:
315
+ → Tab click handler: setActiveTab(tabKey) ONLY — NEVER navigate() to another page
316
+ → Tab content: render inline with {activeTab === 'tabKey' && <TabContent />}
317
+ → Sub-resource data: fetch via API filtered by parent ID, display in tab panel
318
+ → FORBIDDEN: navigate('../leaves?employee=${id}') in tab handler
319
+ → See smartstack-frontend.md section 3 'Tab Behavior Rules'
320
+ - **FK FIELDS (CRITICAL):** Foreign key Guid fields (e.g., EmployeeId) MUST use EntityLookup:
321
+ → NEVER render FK fields as `<input>` — users cannot type GUIDs
322
+ → NEVER render FK fields as `<select>` — even with API-loaded options, `<select>` is NOT acceptable
323
+ → ONLY use `<EntityLookup />` from @/components/ui/EntityLookup for searchable selection
324
+ → Each FK field needs: apiEndpoint, mapOption (display name), search support on backend
325
+ → FORBIDDEN: `<select value={formData.departmentId}>`, `<option value={dept.id}>`, `e.target.value` for FK fields
326
+ → See smartstack-frontend.md section 6 for the full EntityLookup pattern
327
+ - **I18n:** Generate 4 JSON files per module namespace (fr, en, it, de)
328
+ → Follow JSON template from smartstack-frontend.md
329
+ → Keys: actions, labels, errors, validation, columns, form, messages, empty
330
+ → ALL t() calls MUST use namespace prefix + fallback: t('ns:key', 'Default text')
331
+ - **PERMISSIONS:** Call MCP generate_permissions for the module permission root (2 segments: {app}.{module}),
332
+ then also call MCP generate_permissions for EACH section (3 segments: {app}.{module}.{section}).
333
+ - **SECTION ROUTES:** Add section child routes to the module's children array.
334
+ Wire PermissionGuard for section routes with section-level permissions.
335
+ - MUST use src/pages/{App}/{Module}/ hierarchy (NOT flat)
336
+
337
+ ### Documentation (after frontend pages exist)
241
338
 
242
339
  > **After frontend pages are created, generate module documentation via `/documentation` skill.**
243
340
 
@@ -257,28 +354,35 @@ This generates:
257
354
  - Import: `import { DocToggleButton } from '@/components/docs/DocToggleButton';`
258
355
  - Placement: inside the header actions area (see `smartstack-frontend.md` section 7)
259
356
 
260
- ---
261
-
262
- ## Layer 2 — Final Seed Data + Validation (sequential)
357
+ ### If NOT economy_mode AND multiple entities: Agent Teams (parallel within layer)
263
358
 
264
- After Layer 1 completes:
359
+ > **Protocol:** See `references/agent-teams-protocol.md`
265
360
 
266
361
  ```
267
- 1. Verify seed data completeness:
268
- - NavigationModuleSeedData.cs with 4 languages
269
- - PermissionsSeedData.cs with Guid.NewGuid()
270
- - RolesSeedData.cs with context-based role mapping
271
- - IClientSeedDataProvider updated
272
- - DI registration added
362
+ TeamCreate("apex-layer3", description: "Execute Layer 3 frontend in parallel")
273
363
 
274
- 2. Build gate:
275
- dotnet build → MUST PASS
276
- npm run typecheck → MUST PASS (if frontend)
277
- ```
364
+ Spawn 1 teammate per entity (Opus, full tools):
278
365
 
279
- ---
366
+ For each entity:
367
+ Task: "Execute Layer 3 frontend for entity {EntityName}:
368
+ **MANDATORY: Read references/smartstack-frontend.md FIRST**
369
+ - API client: MCP scaffold_api_client
370
+ - Routes: MCP scaffold_routes (outputFormat: 'clientRoutes')
371
+ - Pages: /ui-components skill (ALL 4 types: List, Detail, Create, Edit)
372
+ - I18n: 4 JSON files (fr, en, it, de)
373
+ - FORM PAGES: Full pages with own routes (ZERO modals)
374
+ - FK FIELDS: EntityLookup for all FK Guid fields
375
+ - TABS: Local state only (NEVER navigate())
376
+ - FORM TESTS: Co-located .test.tsx for Create and Edit pages
377
+
378
+ After ALL tasks done:
379
+ SendMessage(type:'message', recipient:'team-lead', content:'ENTITY_COMPLETE: {EntityName}', summary:'{EntityName} frontend done')"
280
380
 
281
- ## FRONTEND COMPLIANCE GATE (MANDATORY before commit)
381
+ Wait for all teammates to report completion.
382
+ shutdown_request → shutdown_response → TeamDelete("apex-layer3")
383
+ ```
384
+
385
+ ### FRONTEND COMPLIANCE GATE (MANDATORY before commit)
282
386
 
283
387
  > **Reference:** See `references/smartstack-frontend.md` section 9 "Compliance Gates" for all 5 mandatory checks:
284
388
  > 1. CSS Variables (theme system)
@@ -294,6 +398,74 @@ When delegating to `/ui-components` skill, include explicit instructions:
294
398
  - "Forms: Create/Edit forms are FULL PAGES with own routes (e.g., `/create`, `/:id/edit`)."
295
399
  - "I18n: ALL text must use `t('namespace:key', 'Fallback')`. Generate JSON files in `src/i18n/locales/`."
296
400
 
401
+ ### Frontend Tests Inline
402
+
403
+ > **Tests are scaffolded and run WITHIN Layer 3, not deferred to step-07.**
404
+
405
+ ```
406
+ 1. Scaffold frontend tests:
407
+ → For each module with create/edit pages:
408
+ → Generate EntityCreatePage.test.tsx and EntityEditPage.test.tsx
409
+ → Co-located next to the page component (NOT in __tests__/ folder)
410
+ → Cover: rendering, validation, submit, pre-fill, navigation, errors
411
+ → Tools: Vitest + React Testing Library + @testing-library/user-event
412
+ → Mock API: vi.mock() or MSW — NEVER real API calls
413
+
414
+ 2. Run tests:
415
+ WEB_DIR=$(find . -name "vitest.config.ts" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
416
+ if [ -n "$WEB_DIR" ]; then
417
+ (cd "$WEB_DIR" && npm run test)
418
+ fi
419
+
420
+ 3. Fix loop (max 3 iterations):
421
+ IF tests fail:
422
+ → Identify root cause (ALWAYS code bug, not test bug)
423
+ → Fix production CODE
424
+ → Re-run tests
425
+ → Repeat until pass or max 3
426
+
427
+ 4. If still failing after 3 iterations: note failures, continue.
428
+ Step-07 "Final Test Sweep" will handle remaining failures.
429
+ ```
430
+
431
+ ### Typecheck Gate
432
+
433
+ ```bash
434
+ npm run typecheck
435
+ ```
436
+
437
+ **MUST PASS before commit.**
438
+
439
+ ### Layer 3 Commits
440
+
441
+ ```
442
+ feat({module}): [frontend] pages, routes, i18n, documentation
443
+ test({module}): frontend form tests
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Layer 4 — DevData (optional)
449
+
450
+ > **Business test data for development/demo environments.**
451
+ > Skip this layer if no meaningful test data is needed.
452
+
453
+ ```
454
+ 1. Create DevDataSeeder:
455
+ → Infrastructure/Persistence/Seeding/DevData/{Module}DevDataSeeder.cs
456
+ → ALL entities MUST include TenantId
457
+ → Realistic business data for demo purposes
458
+
459
+ 2. Build gate:
460
+ dotnet build → MUST PASS
461
+ ```
462
+
463
+ ### Layer 4 Commit (if applicable)
464
+
465
+ ```
466
+ feat({module}): [devdata] test data for development
467
+ ```
468
+
297
469
  ---
298
470
 
299
471
  ## PRD State Update (delegate mode only)
@@ -323,11 +495,16 @@ After each layer completes, gates pass, and builds pass:
323
495
 
324
496
  ```
325
497
  Layer 0: feat({module}): [domain+infra] {short description}
326
- Layer 1: feat({module}): [app+api] {short description}
327
- Layer 1: feat({module}): [frontend] {short description} # if applicable — AFTER all 5 gates pass
328
- Layer 2: feat({module}): [seed] {short description} # if applicable
498
+ Layer 1: feat({module}): [seed] navigation, permissions, roles
499
+ Layer 2: feat({module}): [app+api] {short description}
500
+ Layer 2: test({module}): backend unit and integration tests
501
+ Layer 3: feat({module}): [frontend] pages, routes, i18n, documentation
502
+ Layer 3: test({module}): frontend form tests
503
+ Layer 4: feat({module}): [devdata] test data for development # if applicable
329
504
  ```
330
505
 
506
+ **Maximum 7 commits per module.**
507
+
331
508
  ---
332
509
 
333
510
  ## Save Output (if save_mode)
@@ -225,6 +225,14 @@ AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
225
225
  ```
226
226
  **APEX SmartStack - eXamine Complete**
227
227
 
228
+ | Layer | Status | Details |
229
+ |-------|--------|---------|
230
+ | Layer 0 — Domain + Infrastructure | PASS / N/A | Entities, EF configs, migration, build gate |
231
+ | Layer 1 — Seed Data | PASS / N/A | Navigation, permissions, roles, provider, build gate |
232
+ | Layer 2 — Backend | PASS / N/A | Services, controllers, build gate, inline tests |
233
+ | Layer 3 — Frontend | PASS / N/A | Pages, i18n, docs, compliance gate, inline tests |
234
+ | Layer 4 — DevData | PASS / N/A / SKIPPED | Optional test data |
235
+
228
236
  | Category | Checks | Status |
229
237
  |----------|--------|--------|
230
238
  | MCP conventions | validate_conventions | PASS (0 errors) |
@@ -244,6 +252,8 @@ AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
244
252
  | Role-permission matrix | Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R (POST-CHECK 42) | PASS / N/A |
245
253
  | PermissionAction enum | No Enum.Parse, only typed enum values 0-10 (POST-CHECK 43) | PASS / N/A |
246
254
  | Navigation translations | 4 langs per level, section/resource translations present (POST-CHECK 44) | PASS / N/A |
255
+ | Inline tests (Layer 2) | Backend unit + integration tests | PASS / N/A |
256
+ | Inline tests (Layer 3) | Frontend form tests | PASS / N/A |
247
257
  | POST-CHECKs | 3 MCP tools + 50 bash checks (6 security + 44 convention) | PASS / N/A |
248
258
  | Acceptance criteria | AC1..ACn | {X}/{Y} PASS |
249
259
  ```
@@ -256,24 +266,23 @@ Write to `{output_dir}/04-examine.md` with validation results.
256
266
 
257
267
  ---
258
268
 
259
- ## 10. Route to Next Step — TESTS ARE MANDATORY
269
+ ## 10. Route to Next Step — FINAL TEST SWEEP
260
270
 
261
- > **CRITICAL DO NOT STOP HERE.**
262
- > Step-04 (eXamine) is NOT the final step. Tests MUST be scaffolded and run.
263
- > Completing APEX without tests violates the methodology — skip is FORBIDDEN.
271
+ > **Note:** Backend tests (Layer 2) and frontend tests (Layer 3) have already been scaffolded and run inline.
272
+ > Step-07 "Final Test Sweep" handles: security tests, coverage analysis, cross-layer scenarios, and remaining failures.
264
273
 
265
274
  ```
266
275
  IF examine_mode (-x flag):
267
276
  → Load steps/step-05-deep-review.md (adversarial review)
268
277
  → Then step-06 (resolve) if BLOCKING findings
269
- → Then step-07 (tests) — ALWAYS
278
+ → Then step-07 (Final Test Sweep) — ALWAYS
270
279
 
271
280
  ELSE:
272
281
  → Load steps/step-07-tests.md — IMMEDIATELY after eXamine completes
273
282
  ```
274
283
 
275
284
  **BLOCKING RULE:** The APEX workflow is NOT complete until steps 07-08 execute.
276
- The success criteria require: "Tests: 100% pass, >= 80% coverage" — this is impossible without step-07.
285
+ The success criteria require: "Tests: 100% pass, >= 80% coverage" — step-07 verifies coverage and adds security tests.
277
286
 
278
287
  **NEXT ACTION:** Load `steps/step-07-tests.md` now.
279
288