@atlashub/smartstack-cli 4.14.0 → 4.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlashub/smartstack-cli",
3
- "version": "4.14.0",
3
+ "version": "4.16.1",
4
4
  "description": "SmartStack Claude Code automation toolkit - GitFlow, EF Core migrations, prompts and more",
5
5
  "author": {
6
6
  "name": "SmartStack",
@@ -1,3 +1,4 @@
1
+ {{!-- DEPRECATED: Ce template n'est plus utilisé. scaffold_api_client génère le code inline. --}}
1
2
  {{!-- SmartStack API Client Template --}}
2
3
  {{!-- Generates type-safe API client with NavRoute integration --}}
3
4
 
@@ -43,13 +43,36 @@ Task:
43
43
 
44
44
  ## Task List Coordination (T10)
45
45
 
46
- Team lead manages the task list:
46
+ ### Task Creation (by team lead, BEFORE spawning teammates)
47
+
48
+ Tasks MUST be created upfront for the full layer scope:
49
+
50
+ ```
51
+ FOR EACH entity in layer:
52
+ TaskCreate(
53
+ subject: "Layer {N}: {Entity} {layer_type}",
54
+ description: "{detailed scope: files, skills, MCP tools}",
55
+ activeForm: "{Building/Creating} {Entity} {layer_type}"
56
+ )
57
+ ```
58
+
59
+ ### Task Assignment (by team lead, WHEN spawning)
60
+
61
+ Include task ID and metadata context in teammate prompt:
62
+
63
+ ```
64
+ "Your assigned task ID is {task_id}.
65
+ Your metadata context: entities={entities}, layer={layer}, tools={tools}.
66
+ Call TaskUpdate(taskId: '{task_id}', status: 'in_progress') before starting.
67
+ Call TaskUpdate(taskId: '{task_id}', status: 'completed', metadata: { files_created: [...] }) after ENTITY_COMPLETE message."
68
+ ```
69
+
70
+ ### Task Monitoring (by team lead)
47
71
 
48
72
  ```
49
- 1. TaskCreate: create task for each work item, assign owner
50
- 2. Teammate: TaskUpdate(status: "in_progress") before starting
51
- 3. Teammate: TaskUpdate(status: "completed") after finishing
52
- 4. Lead: TaskList to monitor progress
73
+ 1. TaskList() check progress after each teammate message
74
+ 2. All tasks completed proceed to build gate
75
+ 3. Any task stuck investigate, reassign if needed
53
76
  ```
54
77
 
55
78
  ---
@@ -155,6 +155,138 @@ Write to `{output_dir}/02-plan.md` with the complete plan.
155
155
 
156
156
  ---
157
157
 
158
+ ## 8. Create Task List (MANDATORY)
159
+
160
+ > **Visibility:** TaskCreate generates the grouped progress UI with checkboxes.
161
+ > This makes APEX execution trackable and predictable for the user.
162
+
163
+ After plan is finalized (auto_mode or user approved):
164
+
165
+ ### Task Creation Rules
166
+
167
+ 1. Create ONE task per layer (Layer 0-4)
168
+ 2. For multi-entity layers (2, 3): create ONE sub-task per entity within the layer
169
+ 3. Add build/test gate tasks after each layer
170
+ 4. Set dependencies via `addBlockedBy` to enforce layer ordering
171
+
172
+ ### Metadata Schema
173
+
174
+ > **All APEX tasks use this metadata schema for context recovery after compression:**
175
+
176
+ ```typescript
177
+ // Schema for ALL APEX tasks
178
+ {
179
+ layer?: number, // 0-4, absent for meta/examine/finding tasks
180
+ apex_step?: string, // "02-plan", "03-execute", etc (meta task only)
181
+ entities?: string[], // entities concerned
182
+ tools?: string[], // MCP tools/skills used
183
+ build_gate?: "pending" | "pass" | "fail",
184
+ files_created?: string[], // updated via TaskUpdate after creation
185
+ module?: string, // module code (meta task only)
186
+ app?: string, // app name (meta task only)
187
+ flags?: object // APEX flags (meta task only)
188
+ }
189
+ ```
190
+
191
+ ### Task Template
192
+
193
+ ```
194
+ # APEX Progress Tracker (recovery anchor)
195
+ TaskCreate(subject: "APEX Progress",
196
+ description: "Module: {module_code}, App: {app_name}, Entities: {entities list}. Current: step-02 (Plan)",
197
+ activeForm: "Planning execution",
198
+ metadata: {
199
+ apex_step: "02-plan",
200
+ module: "{module_code}",
201
+ app: "{app_name}",
202
+ entities: ["{entity1}", "{entity2}"],
203
+ flags: { auto: {auto_mode}, economy: {economy_mode}, examine: {examine_mode} }
204
+ })
205
+
206
+ # Layer 0 — Domain + Infrastructure
207
+ TaskCreate(subject: "Layer 0: Domain + Infrastructure",
208
+ description: "Entities: {entity1} ({tenantMode}), {entity2} ({tenantMode}).
209
+ Files: Domain/Entities/*.cs, Infrastructure/Persistence/Configs/*.cs, Migration.
210
+ Tools: MCP scaffold_extension (type: entity, configuration). MCP suggest_migration.
211
+ Gate: dotnet build --no-restore. ACs: {relevant ACs}.",
212
+ activeForm: "Creating domain entities",
213
+ metadata: { layer: 0, entities: [...], tools: ["scaffold_extension", "suggest_migration"], build_gate: "pending", files_created: [] })
214
+
215
+ # Layer 1 — Seed Data
216
+ TaskCreate(subject: "Layer 1: Seed Data",
217
+ description: "Navigation, permissions, roles, provider for {module_code}.
218
+ Files: Seeding/Data/{Module}/*.cs, {App}SeedDataProvider.cs.
219
+ Tools: MCP generate_permissions. Ref: core-seed-data.md.
220
+ Gate: dotnet build. ACs: {relevant ACs}.",
221
+ activeForm: "Generating seed data",
222
+ metadata: { layer: 1, entities: [...], tools: ["generate_permissions"], build_gate: "pending", files_created: [] })
223
+ TaskUpdate(taskId: layer1_id, addBlockedBy: [layer0_id])
224
+
225
+ # Layer 2 — Backend (1 task per entity if multi-entity, 1 task if single)
226
+ IF multi-entity:
227
+ FOR EACH entity:
228
+ TaskCreate(subject: "Layer 2: {Entity} backend",
229
+ description: "Service + DTO + Controller + Validator for {Entity}.
230
+ Files: Application/Services/{Entity}Service.cs, Application/DTOs/{Entity}*.cs, Api/Controllers/{Entity}Controller.cs.
231
+ Tools: MCP scaffold_extension, /controller skill. Gate: dotnet build.
232
+ ACs: {relevant ACs for this entity}.",
233
+ activeForm: "Building {Entity} backend",
234
+ metadata: { layer: 2, entities: ["{Entity}"], tools: ["scaffold_extension", "controller"], build_gate: "pending", files_created: [] })
235
+ TaskUpdate(taskId: entity_task_id, addBlockedBy: [layer1_id])
236
+
237
+ # Layer 2 Tests
238
+ TaskCreate(subject: "Layer 2: Backend tests",
239
+ description: "Unit + integration tests for all entities.
240
+ Tools: MCP scaffold_tests (unit + integration). Gate: dotnet test.",
241
+ activeForm: "Running backend tests",
242
+ metadata: { layer: 2, tools: ["scaffold_tests"], build_gate: "pending" })
243
+
244
+ # Layer 3 — Frontend (1 task per entity if multi-entity)
245
+ IF multi-entity:
246
+ FOR EACH entity:
247
+ TaskCreate(subject: "Layer 3: {Entity} frontend",
248
+ description: "API client, pages (List/Detail/Create/Edit), i18n (4 langs), routes for {Entity}.
249
+ Files: src/pages/{App}/{Module}/{Entity}*.tsx, src/i18n/locales/*/{module}.json.
250
+ Tools: MCP scaffold_api_client, MCP scaffold_routes, /ui-components skill.
251
+ Gate: npm run typecheck + 5 compliance gates. ACs: {relevant ACs}.",
252
+ activeForm: "Building {Entity} frontend",
253
+ metadata: { layer: 3, entities: ["{Entity}"], tools: ["scaffold_api_client", "scaffold_routes", "ui-components"], build_gate: "pending", files_created: [] })
254
+ TaskUpdate(taskId: entity_task_id, addBlockedBy: [layer2_tests_id])
255
+
256
+ # Layer 3 Tests + Compliance
257
+ TaskCreate(subject: "Layer 3: Frontend tests + compliance",
258
+ description: "Form tests (Create/Edit .test.tsx), typecheck, 5 compliance gates.
259
+ Tools: Vitest + React Testing Library. Gate: npm run test + typecheck.",
260
+ activeForm: "Running frontend tests",
261
+ metadata: { layer: 3, tools: ["vitest"], build_gate: "pending" })
262
+
263
+ # Layer 4 (if applicable)
264
+ IF NOT foundation_mode AND devdata needed:
265
+ TaskCreate(subject: "Layer 4: DevData",
266
+ description: "Development test data seeder.
267
+ Files: Infrastructure/Persistence/Seeding/DevData/{Module}DevDataSeeder.cs.
268
+ Gate: dotnet build.",
269
+ activeForm: "Creating dev data",
270
+ metadata: { layer: 4, tools: [], build_gate: "pending", files_created: [] })
271
+
272
+ # Post-execution
273
+ TaskCreate(subject: "eXamine: Validation + POST-CHECKs",
274
+ description: "MCP validate_conventions, build, 50 POST-CHECKs, acceptance criteria.
275
+ Tools: MCP validate_conventions, validate_security, validate_frontend_routes.",
276
+ activeForm: "Validating conventions",
277
+ metadata: { tools: ["validate_conventions", "validate_security", "validate_frontend_routes"] })
278
+ ```
279
+
280
+ ### Economy Mode
281
+
282
+ IF economy_mode: Create the SAME tasks (for visibility), but no Agent Teams — agent principal executes sequentially.
283
+
284
+ ### Delegate Mode
285
+
286
+ IF delegate_mode: Create tasks from PRD task list, mapped to layers.
287
+
288
+ ---
289
+
158
290
  ## NEXT STEP
159
291
 
160
292
  Load `steps/step-03-execute.md`
@@ -47,6 +47,12 @@ Execute ALL layers normally (Layer 0 → Layer 1 → Layer 2 → Layer 3 → Lay
47
47
 
48
48
  ## Layer 0 — Domain + Infrastructure (sequential, agent principal)
49
49
 
50
+ ### Task Progress
51
+ TaskUpdate(taskId: layer0_task_id, status: "in_progress")
52
+ TaskUpdate(taskId: progress_tracker_id,
53
+ description: "Module: {module_code}. Current: step-03 (Execute), Layer 0",
54
+ activeForm: "Executing Layer 0")
55
+
50
56
  ### Domain Entities
51
57
 
52
58
  ```
@@ -108,6 +114,9 @@ dotnet build
108
114
 
109
115
  **MUST PASS before Layer 1. If NuGet error, run `dotnet restore` first. If file lock (MSB3021), use `--output /tmp/{project}_build`.**
110
116
 
117
+ TaskUpdate(taskId: layer0_task_id, status: "completed",
118
+ metadata: { build_gate: "pass" })
119
+
111
120
  ### Layer 0 Commit
112
121
 
113
122
  ```
@@ -118,6 +127,12 @@ feat({module}): [domain+infra] {short description}
118
127
 
119
128
  ## Layer 1 — Seed Data (DEDICATED LAYER — sequential, agent principal)
120
129
 
130
+ ### Task Progress
131
+ TaskUpdate(taskId: layer1_task_id, status: "in_progress")
132
+ TaskUpdate(taskId: progress_tracker_id,
133
+ description: "Module: {module_code}. Current: step-03 (Execute), Layer 1",
134
+ activeForm: "Executing Layer 1")
135
+
121
136
  > **This layer is DEDICATED and MANDATORY.** Seed data makes modules visible in the UI.
122
137
  > Without seed data, the module exists in code but is invisible to users.
123
138
  > Reference: `references/core-seed-data.md` (loaded above) for complete C# templates.
@@ -181,6 +196,9 @@ dotnet build
181
196
 
182
197
  **MUST PASS before Layer 2.**
183
198
 
199
+ TaskUpdate(taskId: layer1_task_id, status: "completed",
200
+ metadata: { build_gate: "pass" })
201
+
184
202
  ### Layer 1 Commit
185
203
 
186
204
  ```
@@ -191,6 +209,12 @@ feat({module}): [seed] navigation, permissions, roles
191
209
 
192
210
  ## Layer 2 — Backend (Services + Controllers)
193
211
 
212
+ ### Task Progress
213
+ TaskUpdate(taskId: layer2_task_id, status: "in_progress")
214
+ TaskUpdate(taskId: progress_tracker_id,
215
+ description: "Module: {module_code}. Current: step-03 (Execute), Layer 2",
216
+ activeForm: "Executing Layer 2")
217
+
194
218
  > **Layer 2 rules** are in `references/smartstack-layers.md` (already in context from step-02):
195
219
  > - NavRoute and permission kebab-case (Layer 2 - API section)
196
220
  > - Controller route attributes (FORBIDDEN: [Route] alongside [NavRoute])
@@ -238,6 +262,18 @@ Wait for all teammates to report completion.
238
262
  shutdown_request → shutdown_response → TeamDelete("apex-layer2")
239
263
  ```
240
264
 
265
+ ### Agent Teams + TaskCreate Integration
266
+
267
+ When spawning teammates for multi-entity layers:
268
+ - Each teammate receives its task ID and metadata context in the prompt
269
+ - Teammate MUST call TaskUpdate(status: "in_progress") before starting
270
+ - Teammate MUST call TaskUpdate(status: "completed", metadata: { files_created: [...] }) after SendMessage("ENTITY_COMPLETE")
271
+ - Lead monitors via TaskList() between teammate completions
272
+ - Lead updates activeForm after each entity completion:
273
+ `TaskUpdate(taskId: layer2_task_id, activeForm: "Building {EntityName} backend (2/5 entities)")`
274
+ - Lead updates metadata after each MCP scaffold:
275
+ `TaskUpdate(taskId: layer_task_id, metadata: { files_created: [...previous, "new_file.cs"] })`
276
+
241
277
  ### Post-Layer 2 Build Gate
242
278
 
243
279
  ```bash
@@ -246,6 +282,11 @@ dotnet build
246
282
 
247
283
  **MUST PASS before backend tests.**
248
284
 
285
+ TaskUpdate(taskId: layer2_task_id, status: "completed",
286
+ metadata: { build_gate: "pass" })
287
+ TaskUpdate(taskId: progress_tracker_id,
288
+ activeForm: "Running build gate (Layer 2)")
289
+
249
290
  ### Backend Tests Inline
250
291
 
251
292
  > **Tests are scaffolded and run WITHIN Layer 2, not deferred to step-07.**
@@ -282,6 +323,12 @@ test({module}): backend unit and integration tests
282
323
 
283
324
  ## Layer 3 — Frontend (Pages + I18n + Documentation)
284
325
 
326
+ ### Task Progress
327
+ TaskUpdate(taskId: layer3_task_id, status: "in_progress")
328
+ TaskUpdate(taskId: progress_tracker_id,
329
+ description: "Module: {module_code}. Current: step-03 (Execute), Layer 3",
330
+ activeForm: "Executing Layer 3")
331
+
285
332
  > **Frontend patterns** are in `references/smartstack-frontend.md` (already loaded above):
286
333
  > - API client generation (MCP scaffold_api_client)
287
334
  > - Route scaffolding (MCP scaffold_routes) — section 1 + 3b
@@ -399,6 +446,18 @@ Wait for all teammates to report completion.
399
446
  shutdown_request → shutdown_response → TeamDelete("apex-layer3")
400
447
  ```
401
448
 
449
+ ### Agent Teams + TaskCreate Integration
450
+
451
+ When spawning teammates for multi-entity layers:
452
+ - Each teammate receives its task ID and metadata context in the prompt
453
+ - Teammate MUST call TaskUpdate(status: "in_progress") before starting
454
+ - Teammate MUST call TaskUpdate(status: "completed", metadata: { files_created: [...] }) after SendMessage("ENTITY_COMPLETE")
455
+ - Lead monitors via TaskList() between teammate completions
456
+ - Lead updates activeForm after each entity completion:
457
+ `TaskUpdate(taskId: layer3_task_id, activeForm: "Building {EntityName} frontend (2/5 entities)")`
458
+ - Lead updates metadata after each MCP scaffold:
459
+ `TaskUpdate(taskId: layer_task_id, metadata: { files_created: [...previous, "NewPage.tsx"] })`
460
+
402
461
  ### FRONTEND COMPLIANCE GATE (MANDATORY before commit)
403
462
 
404
463
  > **Reference:** See `references/smartstack-frontend.md` section 9 "Compliance Gates" for all 5 mandatory checks:
@@ -453,6 +512,9 @@ npm run typecheck
453
512
 
454
513
  **MUST PASS before commit.**
455
514
 
515
+ TaskUpdate(taskId: layer3_task_id, status: "completed",
516
+ metadata: { build_gate: "pass" })
517
+
456
518
  ### Layer 3 Commits
457
519
 
458
520
  ```
@@ -464,6 +526,12 @@ test({module}): frontend form tests
464
526
 
465
527
  ## Layer 4 — DevData (optional)
466
528
 
529
+ ### Task Progress
530
+ IF layer4 task exists: TaskUpdate(taskId: layer4_task_id, status: "in_progress")
531
+ IF layer4 task exists: TaskUpdate(taskId: progress_tracker_id,
532
+ description: "Module: {module_code}. Current: step-03 (Execute), Layer 4",
533
+ activeForm: "Executing Layer 4")
534
+
467
535
  > **Business test data for development/demo environments.**
468
536
  > Skip this layer if no meaningful test data is needed.
469
537
 
@@ -477,6 +545,9 @@ test({module}): frontend form tests
477
545
  dotnet build → MUST PASS
478
546
  ```
479
547
 
548
+ IF layer4 task exists: TaskUpdate(taskId: layer4_task_id, status: "completed",
549
+ metadata: { build_gate: "pass" })
550
+
480
551
  ### Layer 4 Commit (if applicable)
481
552
 
482
553
  ```
@@ -14,6 +14,22 @@ next_step: steps/step-05-deep-review.md
14
14
 
15
15
  ---
16
16
 
17
+ ## 0. Task Progress
18
+
19
+ ### Progress Tracker Update
20
+ ```
21
+ TaskUpdate(taskId: progress_tracker_id,
22
+ description: "Module: {module_code}. Current: step-04 (eXamine)",
23
+ activeForm: "Validating conventions")
24
+ ```
25
+
26
+ ### eXamine Task Lifecycle
27
+ ```
28
+ TaskUpdate(taskId: examine_task_id, status: "in_progress")
29
+ ```
30
+
31
+ ---
32
+
17
33
  ## 1. MCP Convention Validation
18
34
 
19
35
  ```
@@ -284,6 +300,11 @@ ELSE:
284
300
  **BLOCKING RULE:** The APEX workflow is NOT complete until steps 07-08 execute.
285
301
  The success criteria require: "Tests: 100% pass, >= 80% coverage" — step-07 verifies coverage and adds security tests.
286
302
 
303
+ ### eXamine Task Lifecycle — Completion
304
+ ```
305
+ TaskUpdate(taskId: examine_task_id, status: "completed")
306
+ ```
307
+
287
308
  **NEXT ACTION:** Load `steps/step-07-tests.md` now.
288
309
 
289
310
  ---
@@ -12,6 +12,17 @@ next_step: steps/step-06-resolve.md
12
12
 
13
13
  ---
14
14
 
15
+ ## 0. Task Progress
16
+
17
+ ### Progress Tracker Update
18
+ ```
19
+ TaskUpdate(taskId: progress_tracker_id,
20
+ description: "Module: {module_code}. Current: step-05 (Deep Review)",
21
+ activeForm: "Reviewing code")
22
+ ```
23
+
24
+ ---
25
+
15
26
  ## 1. Gather Changed Files
16
27
 
17
28
  ```bash
@@ -12,15 +12,34 @@ next_step: steps/step-07-tests.md
12
12
 
13
13
  ---
14
14
 
15
- ## 1. Process BLOCKING Findings
15
+ ## 0. Task Progress
16
+
17
+ ### Progress Tracker Update
18
+ ```
19
+ TaskUpdate(taskId: progress_tracker_id,
20
+ description: "Module: {module_code}. Current: step-06 (Resolve)",
21
+ activeForm: "Fixing findings")
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 1. Create Finding Tasks
16
27
 
17
28
  For each BLOCKING finding from step-05:
18
29
 
19
30
  ```
20
- Finding: {F01, F02, ...}
21
- File: {path}
22
- Issue: {description}
23
- Fix approach: {use appropriate skill/MCP tool}
31
+ TaskCreate(subject: "Fix: {F01} {short description}",
32
+ description: "File: {path}:{line}\nIssue: {description}\nFix: {approach}",
33
+ activeForm: "Fixing {F01}",
34
+ metadata: { finding_id: "F01", severity: "BLOCKING", source_file: "{path}" })
35
+ ```
36
+
37
+ Then process each finding by updating task status:
38
+
39
+ ```
40
+ TaskUpdate(taskId: finding_task_id, status: "in_progress")
41
+ ... apply fix ...
42
+ TaskUpdate(taskId: finding_task_id, status: "completed")
24
43
  ```
25
44
 
26
45
  **Fixing rules:**
@@ -16,6 +16,17 @@ next_step: steps/step-08-run-tests.md
16
16
 
17
17
  ---
18
18
 
19
+ ## Task Progress
20
+
21
+ ### Progress Tracker Update
22
+ ```
23
+ TaskUpdate(taskId: progress_tracker_id,
24
+ description: "Module: {module_code}. Current: step-07 (Final Test Sweep)",
25
+ activeForm: "Running test sweep")
26
+ ```
27
+
28
+ ---
29
+
19
30
  ## 0. Ensure Test Infrastructure Exists
20
31
 
21
32
  ### 0a. Frontend Test Tooling (if frontend was generated)
@@ -55,10 +55,14 @@ Read App.tsx and detect which pattern is used:
55
55
  const applicationRoutes: ApplicationRouteExtensions = {
56
56
  'human-resources': [
57
57
  // existing routes...
58
- { path: '{module_kebab}', element: <{EntityName}ListPage /> },
59
- { path: '{module_kebab}/new', element: <Create{EntityName}Page /> },
60
- { path: '{module_kebab}/:id', element: <{EntityName}DetailPage /> },
61
- { path: '{module_kebab}/:id/edit', element: <Create{EntityName}Page /> },
58
+ { path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
59
+ { path: '{module_kebab}/{section_kebab}/new', element: <Create{EntityName}Page /> },
60
+ { path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
61
+ { path: '{module_kebab}/{section_kebab}/:id/edit', element: <Create{EntityName}Page /> },
62
+
63
+ // Parent redirect routes (MANDATORY — prevents /login redirect on parent navigation)
64
+ { path: '{module_kebab}', element: <Navigate to="{module_kebab}/{first_section_kebab}" replace /> },
65
+ { path: '', element: <Navigate to="{first_module_kebab}/{first_section_kebab}" replace /> },
62
66
  ],
63
67
  };
64
68
  ```
@@ -137,6 +141,34 @@ If `appWiring.issues` is not empty, fix the wiring before proceeding.
137
141
 
138
142
  ---
139
143
 
144
+ ## Step 4e: Parent Redirect Routes (MANDATORY)
145
+
146
+ **CRITICAL:** Without parent redirects, navigating to an application or module URL (e.g., `/human-resources` or `/human-resources/employees`) will cause a redirect to `/login` because no route matches.
147
+
148
+ For each application, you MUST add:
149
+
150
+ 1. **Application root redirect** — redirects `/{application}` to the first module/section:
151
+ ```tsx
152
+ { path: '', element: <Navigate to="{first_module}/{first_section}" replace /> }
153
+ ```
154
+
155
+ 2. **Module redirect** (if modules have sections) — redirects `/{application}/{module}` to first section:
156
+ ```tsx
157
+ { path: '{module}', element: <Navigate to="{module}/{first_section}" replace /> }
158
+ ```
159
+
160
+ **Example:** For NavRoutes `human-resources.employees.management` and `human-resources.employees.departments`:
161
+ ```tsx
162
+ { path: 'employees', element: <Navigate to="employees/management" replace /> },
163
+ { path: '', element: <Navigate to="employees/management" replace /> },
164
+ ```
165
+
166
+ The `to` prop is resolved relative to the **parent route** (`/{application}`), so always use the full path from the application root.
167
+
168
+ > Note: `scaffold_routes` with `outputFormat: "applicationRoutes"` generates these redirects automatically.
169
+
170
+ ---
171
+
140
172
  ## Forbidden Patterns (BOTH patterns)
141
173
 
142
174
  - Adding application routes to `clientRoutes[]` with absolute paths — `clientRoutes` is ONLY for routes outside SmartStack applications (e.g., `/about`, `/pricing`)
@@ -53,13 +53,15 @@ Read the parent SeedData class and find the GUID matching `{parent_path}`.
53
53
  Generate a random GUID for the new navigation entity:
54
54
 
55
55
  ```csharp
56
- // ALWAYS use Guid.NewGuid() avoids conflicts between projects/tenants/environments
57
- var guid = Guid.NewGuid();
56
+ // IMPORTANT: Use a stable GUID. Never change after the first seed.
57
+ // Generate once with Guid.NewGuid(), then hardcode the result as a static field.
58
+ public static readonly Guid MyEntityId = Guid.Parse("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
58
59
  ```
59
60
 
60
61
  **Rules:**
61
- - ALWAYS use `Guid.NewGuid()` no deterministic, no sequential, no fixed values
62
- - Idempotence is handled by Code-based lookups, not by fixed IDs
62
+ - Generate a GUID once with `Guid.NewGuid()`, then **hardcode it as a static readonly field**
63
+ - NEVER call `Guid.NewGuid()` at runtime in seed data each migration run would generate different IDs, breaking foreign keys
64
+ - Idempotence is handled by EF Core HasData matching on the `Id` primary key
63
65
  - Store result as `{navigation_guid}`
64
66
 
65
67
  ## F4. Write Navigation Entity Seed
@@ -20,9 +20,15 @@ Gather all context needed to generate the controller. Find the Entity, check DbC
20
20
 
21
21
  **Search for entity file:**
22
22
 
23
+ 1. Read `.smartstack/config.json` → use `paths.domain` if available
24
+ 2. Otherwise, use wildcard on project name:
23
25
  ```
24
- Glob: "src/SmartStack.Domain/**/{entity}.cs"
25
- Glob: "src/SmartStack.Domain/**/{entity}s.cs"
26
+ Glob: "src/*Domain*/**/{entity}.cs"
27
+ Glob: "src/*Domain*/**/{entity}s.cs"
28
+ ```
29
+ 3. Fallback (if no match):
30
+ ```
31
+ Glob: "src/**/{entity}.cs" with ignore "**/obj/**,**/bin/**,**/Tests/**"
26
32
  ```
27
33
 
28
34
  **Extract from Entity:**
@@ -25,7 +25,9 @@ Validate that generated documentation is complete and accurate, then integrate i
25
25
  - [ ] Mock UI faithfully reproduces the real page interface (not generic KPI/table)
26
26
  - [ ] Every Mock UI section has `Annotation` components explaining each visual element
27
27
  - [ ] i18n JSON is FLAT (no root key) — `t('title')` resolves directly
28
- - [ ] Route registered in App.tsx
28
+ - [ ] Route added as **child** of `/docs/business` group (not standalone) in App.tsx
29
+ - [ ] Route added in `smartstackRoutes.tsx` (locked routes)
30
+ - [ ] DocsLayout sidebar updated (if applicable)
29
31
  - [ ] Module appears in UserIndexPage.tsx (if applicable)
30
32
  - [ ] DocPanelContext.tsx mapping updated for all module routes
31
33
  - [ ] i18n/config.ts updated with new namespace
@@ -36,7 +38,9 @@ Validate that generated documentation is complete and accurate, then integrate i
36
38
  - [ ] i18n JSON uses root key matching namespace
37
39
  - [ ] DocRenderer wrapper (index.tsx) passes correct `i18nNamespace` prop
38
40
  - [ ] doc-data.ts contains structured data (~50 lines)
39
- - [ ] Route registered in App.tsx and parent indexes
41
+ - [ ] Route added as **child** of `/system/docs` group (not standalone) in App.tsx
42
+ - [ ] Route added in `smartstackRoutes.tsx` (locked routes)
43
+ - [ ] DocsLayout sidebar updated (if applicable)
40
44
 
41
45
  #### For `update` Type
42
46
 
@@ -111,34 +115,59 @@ detects tenant-prefixed routes (`/t/:slug/...`), and builds lookup keys as `{app
111
115
 
112
116
  #### App.tsx Routing
113
117
 
114
- **For `user` type:** Add dynamic import and route:
118
+ Documentation pages use a **separate routing system** from business pages. They render inside `DocsLayout` (sidebar navigation), NOT `AppLayout`. There are two route groups:
119
+
120
+ - **`/docs/business`** → Business module docs (user type) — uses `<DocsLayout />`
121
+ - **`/system/docs`** → Developer/database/testing docs — uses `<DocsLayout />`
122
+
123
+ > **Note:** The `<Suspense fallback={<PageLoader />}>` is already in place at the global level (wrapping the entire Routes tree). Do NOT add per-route `<Suspense>` wrappers.
124
+
125
+ **For `user` type:** Add lazy import and **child route** inside the existing `/docs/business` group:
115
126
 
116
127
  ```tsx
128
+ // 1. Add lazy import at top of App.tsx
117
129
  const {Module}DocPage = lazy(() =>
118
130
  import('@/pages/docs/business/{application}/{module}')
119
131
  );
120
132
 
121
- // In routes array:
122
- {
123
- path: '/docs/business/{application}/{module}',
124
- element: <Suspense><{Module}DocPage /></Suspense>
125
- }
133
+ // 2. Find the existing <Route path="/docs/business" element={<DocsLayout />}> group
134
+ // Add as CHILD route (not standalone):
135
+ <Route path="/docs/business" element={<DocsLayout />}>
136
+ {/* ... existing doc routes ... */}
137
+ <Route path="{application}/{module}" element={<{Module}DocPage />} />
138
+ </Route>
126
139
  ```
127
140
 
128
- **For `developer|database|testing` types:** Add to appropriate category:
141
+ **For `developer|database|testing` types:** Add **child route** inside the existing `/system/docs` group:
129
142
 
130
143
  ```tsx
144
+ // 1. Add lazy import at top of App.tsx
131
145
  const {Tool}DocPage = lazy(() =>
132
- import('@/pages/docs/developer/{category}/{tool}')
146
+ import('@/pages/docs/{category}/{tool}')
133
147
  );
134
148
 
135
- // In routes array:
136
- {
137
- path: '/docs/developer/{category}/{tool}',
138
- element: <Suspense><{Tool}DocPage /></Suspense>
139
- }
149
+ // 2. Find the existing <Route path="/system/docs" element={<DocsLayout />}> group
150
+ // Add as CHILD route:
151
+ <Route path="/system/docs" element={<DocsLayout />}>
152
+ {/* ... existing doc routes ... */}
153
+ <Route path="{category}/{tool}" element={<{Tool}DocPage />} />
154
+ </Route>
140
155
  ```
141
156
 
157
+ #### smartstackRoutes.tsx Registration
158
+
159
+ **MANDATORY** for all doc types: Add the route in `smartstackRoutes.tsx` under the corresponding group (`/docs/business` or `/system/docs`). Documentation routes are part of `LOCKED_PREFIXES` and cannot be overridden by client extensions.
160
+
161
+ #### DocsLayout Sidebar Update
162
+
163
+ If the new documentation page should appear in the sidebar navigation, update the `navigation` array in `DocsLayout.tsx` with the new entry (label, path, icon).
164
+
165
+ #### Important Notes
166
+
167
+ - Documentation routes do **NOT** use `AppLayout`, `RouteGuard`, or `LicenseGuard`
168
+ - Documentation routes have **no tenant prefix** (`/t/:slug/...`) — they are globally accessible
169
+ - Documentation routes require **no specific permission** to access
170
+
142
171
  #### i18n Config Update
143
172
 
144
173
  **File:** `web/smartstack-web/src/i18n/config.ts`
@@ -230,7 +259,9 @@ Add or update entry with metadata:
230
259
  - [x] Mock UI faithfully reproduces the real page interface (user type)
231
260
  - [x] Every Mock UI section has `Annotation` components (user type)
232
261
  - [x] i18n files created in ALL 4 languages (FR, EN, DE, IT) with correct format
233
- - [x] Route registered in App.tsx
262
+ - [x] Route added as child of correct DocsLayout group in App.tsx
263
+ - [x] Route registered in smartstackRoutes.tsx (locked routes)
264
+ - [x] DocsLayout sidebar updated (if applicable)
234
265
  - [x] docs-manifest.json updated
235
266
  - [x] i18n/config.ts updated with new namespace
236
267
  - [x] Module appears in UserIndexPage (if type = user)