@atlashub/smartstack-cli 3.37.0 → 3.39.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 (228) hide show
  1. package/dist/index.js +16 -24
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +235 -265
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/scripts/extract-api-endpoints.ts +5 -5
  7. package/scripts/generate-doc-with-mock-ui.ts +10 -17
  8. package/templates/agents/ba-reader.md +9 -9
  9. package/templates/agents/ba-writer.md +12 -15
  10. package/templates/agents/code-reviewer.md +1 -1
  11. package/templates/agents/docs-context-reader.md +1 -1
  12. package/templates/agents/efcore/scan.md +3 -1
  13. package/templates/agents/gitflow/commit.md +74 -0
  14. package/templates/agents/gitflow/finish.md +5 -2
  15. package/templates/agents/gitflow/init-clone.md +3 -3
  16. package/templates/agents/gitflow/init-validate.md +3 -2
  17. package/templates/agents/gitflow/merge.md +5 -4
  18. package/templates/agents/gitflow/pr.md +5 -4
  19. package/templates/agents/gitflow/start.md +37 -5
  20. package/templates/hooks/hooks.json +11 -0
  21. package/templates/hooks/wsl-dotnet-cleanup.sh +24 -0
  22. package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +20 -20
  23. package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +16 -24
  24. package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +2 -2
  25. package/templates/skills/_resources/mcp-validate-documentation-spec.md +3 -3
  26. package/templates/skills/_shared.md +15 -17
  27. package/templates/skills/ai-prompt/SKILL.md +1 -1
  28. package/templates/skills/ai-prompt/steps/step-00-init.md +47 -0
  29. package/templates/skills/apex/SKILL.md +3 -4
  30. package/templates/skills/apex/_shared.md +10 -20
  31. package/templates/skills/apex/references/analysis-methods.md +141 -0
  32. package/templates/skills/apex/references/challenge-questions.md +1 -21
  33. package/templates/skills/apex/references/core-seed-data.md +35 -58
  34. package/templates/skills/apex/references/examine-build-validation.md +82 -0
  35. package/templates/skills/apex/references/execution-frontend-gates.md +177 -0
  36. package/templates/skills/apex/references/execution-frontend-patterns.md +105 -0
  37. package/templates/skills/apex/references/execution-layer1-rules.md +96 -0
  38. package/templates/skills/apex/references/initialization-challenge-flow.md +110 -0
  39. package/templates/skills/apex/references/planning-layer-mapping.md +151 -0
  40. package/templates/skills/apex/references/post-checks.md +145 -40
  41. package/templates/skills/apex/references/smartstack-api.md +35 -51
  42. package/templates/skills/apex/references/smartstack-frontend.md +18 -18
  43. package/templates/skills/apex/references/smartstack-layers.md +38 -62
  44. package/templates/skills/apex/steps/step-00-init.md +14 -26
  45. package/templates/skills/apex/steps/step-01-analyze.md +10 -143
  46. package/templates/skills/apex/steps/step-02-plan.md +10 -92
  47. package/templates/skills/apex/steps/step-03-execute.md +45 -252
  48. package/templates/skills/apex/steps/step-04-examine.md +14 -78
  49. package/templates/skills/apex/steps/step-05-deep-review.md +2 -2
  50. package/templates/skills/apex/steps/step-08-run-tests.md +1 -0
  51. package/templates/skills/application/SKILL.md +241 -242
  52. package/templates/skills/application/references/backend-controller-hierarchy.md +16 -16
  53. package/templates/skills/application/references/backend-seeding-and-dto-output.md +83 -0
  54. package/templates/skills/application/references/backend-table-prefix-mapping.md +79 -0
  55. package/templates/skills/application/references/backend-verification.md +1 -1
  56. package/templates/skills/application/references/frontend-i18n-and-output.md +67 -0
  57. package/templates/skills/application/references/frontend-route-naming.md +117 -0
  58. package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +107 -0
  59. package/templates/skills/application/references/frontend-verification.md +12 -12
  60. package/templates/skills/application/references/init-parameter-detection.md +121 -0
  61. package/templates/skills/application/references/migration-checklist-troubleshooting.md +100 -0
  62. package/templates/skills/application/references/nav-fallback-procedure.md +199 -200
  63. package/templates/skills/application/references/provider-template.md +2 -6
  64. package/templates/skills/application/references/roles-client-project-handling.md +55 -0
  65. package/templates/skills/application/references/roles-fallback-procedure.md +149 -0
  66. package/templates/skills/application/references/test-coverage-requirements.md +213 -0
  67. package/templates/skills/application/references/test-frontend.md +3 -3
  68. package/templates/skills/application/steps/step-00-init.md +130 -260
  69. package/templates/skills/application/steps/step-01-navigation.md +170 -170
  70. package/templates/skills/application/steps/step-02-permissions.md +196 -196
  71. package/templates/skills/application/steps/step-03-roles.md +182 -339
  72. package/templates/skills/application/steps/step-03b-provider.md +133 -134
  73. package/templates/skills/application/steps/step-04-backend.md +174 -265
  74. package/templates/skills/application/steps/step-05-frontend.md +18 -144
  75. package/templates/skills/application/steps/step-06-migration.md +12 -60
  76. package/templates/skills/application/steps/step-07-tests.md +9 -76
  77. package/templates/skills/application/templates-backend.md +29 -27
  78. package/templates/skills/application/templates-frontend.md +49 -49
  79. package/templates/skills/application/templates-seed.md +57 -131
  80. package/templates/skills/business-analyse/SKILL.md +27 -30
  81. package/templates/skills/business-analyse/_architecture.md +6 -6
  82. package/templates/skills/business-analyse/_shared.md +60 -88
  83. package/templates/skills/business-analyse/questionnaire/04-data.md +3 -3
  84. package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
  85. package/templates/skills/business-analyse/questionnaire/13-cross-module.md +1 -1
  86. package/templates/skills/business-analyse/react/application-viewer.md +12 -12
  87. package/templates/skills/business-analyse/react/components.md +8 -12
  88. package/templates/skills/business-analyse/react/schema.md +836 -836
  89. package/templates/skills/business-analyse/references/agent-module-prompt.md +2 -3
  90. package/templates/skills/business-analyse/references/analysis-semantic-checks.md +190 -0
  91. package/templates/skills/business-analyse/references/cache-warming-strategy.md +2 -2
  92. package/templates/skills/business-analyse/references/cadrage-challenge-patterns.md +41 -0
  93. package/templates/skills/business-analyse/references/cadrage-coverage-matrix.md +74 -0
  94. package/templates/skills/business-analyse/references/cadrage-shared-modules.md +69 -0
  95. package/templates/skills/business-analyse/references/cadrage-structure-cards.md +1 -1
  96. package/templates/skills/business-analyse/references/compilation-structure-cards.md +297 -0
  97. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +2 -2
  98. package/templates/skills/business-analyse/references/deploy-modes.md +5 -5
  99. package/templates/skills/business-analyse/references/detection-strategies.md +7 -7
  100. package/templates/skills/business-analyse/references/handoff-file-templates.md +14 -22
  101. package/templates/skills/business-analyse/references/handoff-mappings.md +4 -4
  102. package/templates/skills/business-analyse/references/handoff-seeddata-generation.md +312 -0
  103. package/templates/skills/business-analyse/references/init-schema-deployment.md +3 -3
  104. package/templates/skills/business-analyse/references/naming-conventions.md +22 -24
  105. package/templates/skills/business-analyse/references/prd-generation.md +2 -2
  106. package/templates/skills/business-analyse/references/review-data-mapping.md +2 -2
  107. package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
  108. package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
  109. package/templates/skills/business-analyse/references/team-orchestration.md +49 -6
  110. package/templates/skills/business-analyse/references/ui-dashboard-spec.md +1 -1
  111. package/templates/skills/business-analyse/references/ui-resource-cards.md +18 -18
  112. package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -2
  113. package/templates/skills/business-analyse/references/validation-checklist.md +2 -2
  114. package/templates/skills/business-analyse/schemas/application-schema.json +4 -5
  115. package/templates/skills/business-analyse/schemas/project-schema.json +1 -6
  116. package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -3
  117. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +4 -4
  118. package/templates/skills/business-analyse/steps/step-00-init.md +8 -17
  119. package/templates/skills/business-analyse/steps/step-01-cadrage.md +35 -198
  120. package/templates/skills/business-analyse/steps/step-01b-applications.md +16 -20
  121. package/templates/skills/business-analyse/steps/step-02-decomposition.md +1 -1
  122. package/templates/skills/business-analyse/steps/step-03a1-setup.md +4 -4
  123. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +1 -1
  124. package/templates/skills/business-analyse/steps/step-03b-ui.md +4 -4
  125. package/templates/skills/business-analyse/steps/step-03c-compile.md +66 -140
  126. package/templates/skills/business-analyse/steps/step-03d-validate.md +2 -2
  127. package/templates/skills/business-analyse/steps/step-04a-collect.md +2 -2
  128. package/templates/skills/business-analyse/steps/step-04b-analyze.md +42 -160
  129. package/templates/skills/business-analyse/steps/step-04c-decide.md +1 -1
  130. package/templates/skills/business-analyse/steps/step-05a-handoff.md +74 -104
  131. package/templates/skills/business-analyse/steps/step-05b-deploy.md +13 -11
  132. package/templates/skills/business-analyse/steps/step-06-review.md +3 -3
  133. package/templates/skills/business-analyse/templates/tpl-frd.md +13 -13
  134. package/templates/skills/business-analyse/templates/tpl-handoff.md +12 -12
  135. package/templates/skills/business-analyse/templates/tpl-progress.md +1 -1
  136. package/templates/skills/business-analyse/templates-frd.md +25 -25
  137. package/templates/skills/business-analyse/templates-react.md +15 -21
  138. package/templates/skills/controller/SKILL.md +1 -1
  139. package/templates/skills/controller/postman-templates.md +1 -1
  140. package/templates/skills/controller/references/controller-code-templates.md +2 -2
  141. package/templates/skills/controller/references/mcp-scaffold-workflow.md +209 -0
  142. package/templates/skills/controller/references/permission-sync-templates.md +13 -16
  143. package/templates/skills/controller/steps/step-00-init.md +11 -11
  144. package/templates/skills/controller/steps/step-03-generate.md +64 -103
  145. package/templates/skills/controller/templates.md +67 -71
  146. package/templates/skills/debug/SKILL.md +13 -218
  147. package/templates/skills/debug/steps/step-00-init.md +57 -0
  148. package/templates/skills/debug/steps/step-01-analyze.md +219 -0
  149. package/templates/skills/debug/steps/step-02-resolve.md +85 -0
  150. package/templates/skills/documentation/SKILL.md +49 -345
  151. package/templates/skills/documentation/data-schema.md +11 -8
  152. package/templates/skills/documentation/steps/step-00-init.md +70 -0
  153. package/templates/skills/documentation/steps/step-01-scan.md +113 -0
  154. package/templates/skills/documentation/steps/step-02-generate.md +231 -0
  155. package/templates/skills/documentation/steps/step-03-validate.md +238 -0
  156. package/templates/skills/documentation/templates.md +480 -322
  157. package/templates/skills/efcore/SKILL.md +1 -1
  158. package/templates/skills/efcore/references/both-contexts.md +32 -0
  159. package/templates/skills/efcore/references/database-operations.md +67 -0
  160. package/templates/skills/efcore/references/destructive-operations.md +38 -0
  161. package/templates/skills/efcore/references/reset-operations.md +81 -0
  162. package/templates/skills/efcore/references/seed-methods.md +86 -0
  163. package/templates/skills/efcore/references/shared-init-functions.md +250 -0
  164. package/templates/skills/efcore/references/sql-objects-injection.md +61 -0
  165. package/templates/skills/efcore/references/troubleshooting.md +81 -0
  166. package/templates/skills/efcore/steps/db/step-deploy.md +1 -32
  167. package/templates/skills/efcore/steps/db/step-reset.md +7 -103
  168. package/templates/skills/efcore/steps/db/step-seed.md +10 -132
  169. package/templates/skills/efcore/steps/db/step-status.md +5 -44
  170. package/templates/skills/efcore/steps/migration/step-02-create.md +1 -14
  171. package/templates/skills/efcore/steps/migration/step-03-validate.md +8 -62
  172. package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +1 -57
  173. package/templates/skills/efcore/steps/shared/step-00-init.md +11 -254
  174. package/templates/skills/efcore/steps/squash/step-03-create.md +1 -58
  175. package/templates/skills/feature-full/SKILL.md +1 -1
  176. package/templates/skills/feature-full/steps/step-00-init.md +57 -0
  177. package/templates/skills/feature-full/steps/step-01-implementation.md +1 -1
  178. package/templates/skills/gitflow/SKILL.md +28 -5
  179. package/templates/skills/gitflow/_shared.md +109 -12
  180. package/templates/skills/gitflow/phases/abort.md +4 -0
  181. package/templates/skills/gitflow/phases/cleanup.md +4 -0
  182. package/templates/skills/gitflow/references/commit-message-generation.md +58 -0
  183. package/templates/skills/gitflow/references/commit-migration-validation.md +49 -0
  184. package/templates/skills/gitflow/references/finish-cleanup.md +55 -0
  185. package/templates/skills/gitflow/references/finish-version-bumping.md +45 -0
  186. package/templates/skills/gitflow/references/init-environment-detection.md +41 -0
  187. package/templates/skills/gitflow/references/init-questions.md +185 -0
  188. package/templates/skills/gitflow/references/init-structure-creation.md +75 -0
  189. package/templates/skills/gitflow/references/init-version-detection.md +21 -0
  190. package/templates/skills/gitflow/references/init-workspace-detection.md +43 -0
  191. package/templates/skills/gitflow/references/merge-ci-status.md +36 -0
  192. package/templates/skills/gitflow/references/merge-execution.md +62 -0
  193. package/templates/skills/gitflow/references/merge-pr-context.md +76 -0
  194. package/templates/skills/gitflow/references/pr-build-checks.md +60 -0
  195. package/templates/skills/gitflow/references/pr-generation.md +58 -0
  196. package/templates/skills/gitflow/references/start-branch-normalization.md +28 -0
  197. package/templates/skills/gitflow/references/start-worktree-creation.md +50 -0
  198. package/templates/skills/gitflow/references/sync-push-verify.md +44 -0
  199. package/templates/skills/gitflow/references/sync-rebase-conflicts.md +38 -0
  200. package/templates/skills/gitflow/steps/step-commit.md +12 -91
  201. package/templates/skills/gitflow/steps/step-finish.md +15 -159
  202. package/templates/skills/gitflow/steps/step-init.md +24 -326
  203. package/templates/skills/gitflow/steps/step-merge.md +17 -176
  204. package/templates/skills/gitflow/steps/step-pr.md +10 -116
  205. package/templates/skills/gitflow/steps/step-start.md +16 -109
  206. package/templates/skills/gitflow/steps/step-sync.md +6 -69
  207. package/templates/skills/ralph-loop/SKILL.md +6 -0
  208. package/templates/skills/ralph-loop/references/category-completeness.md +185 -0
  209. package/templates/skills/ralph-loop/references/compact-loop.md +1 -1
  210. package/templates/skills/ralph-loop/references/init-resume-recovery.md +127 -0
  211. package/templates/skills/ralph-loop/references/module-transition.md +151 -0
  212. package/templates/skills/ralph-loop/references/multi-module-queue.md +171 -0
  213. package/templates/skills/ralph-loop/references/parallel-execution.md +246 -0
  214. package/templates/skills/ralph-loop/references/task-transform-legacy.md +6 -9
  215. package/templates/skills/ralph-loop/references/team-orchestration.md +45 -3
  216. package/templates/skills/ralph-loop/steps/step-00-init.md +36 -109
  217. package/templates/skills/ralph-loop/steps/step-01-task.md +15 -163
  218. package/templates/skills/ralph-loop/steps/step-02-execute.md +8 -154
  219. package/templates/skills/ralph-loop/steps/step-04-check.md +20 -73
  220. package/templates/skills/review-code/references/owasp-api-top10.md +5 -5
  221. package/templates/skills/review-code/references/smartstack-conventions.md +568 -568
  222. package/templates/skills/validate-feature/references/api-smoke-tests.md +140 -0
  223. package/templates/skills/validate-feature/references/db-validation-checks.md +180 -0
  224. package/templates/skills/validate-feature/steps/step-01-compile.md +1 -3
  225. package/templates/skills/validate-feature/steps/step-04-api-smoke.md +34 -145
  226. package/templates/skills/validate-feature/steps/step-05-db-validation.md +74 -260
  227. package/templates/skills/workflow/SKILL.md +1 -1
  228. package/templates/skills/workflow/steps/step-00-init.md +57 -0
@@ -26,15 +26,14 @@ const permissions = coreSeedData.permissions || [];
26
26
  const rolePerms = coreSeedData.rolePermissions || [];
27
27
 
28
28
  // Derived context (from guardrail or PRD)
29
- const navRoute = meta.navRoute; // e.g. "business.human-resources.projects"
30
- const contextCode = meta.contextCode; // e.g. "business"
29
+ const navRoute = meta.navRoute; // e.g. "human-resources.projects"
31
30
  const appCode = meta.appCode; // e.g. "human-resources"
32
31
  const moduleCode = task.module; // e.g. "projects"
33
32
 
34
33
  // If _seedDataMeta is absent, fallback to PRD source
35
34
  if (!navRoute) {
36
35
  const prd = readJSON('.ralph/prd.json');
37
- const navRoute = `${prd.source?.context || 'business'}.${prd.source?.application || prd.metadata?.module}.${task.module}`;
36
+ const navRoute = `${prd.source?.application || prd.metadata?.module}.${task.module}`;
38
37
  }
39
38
  ```
40
39
 
@@ -42,8 +41,7 @@ if (!navRoute) {
42
41
 
43
42
  | Variable | Example | Source |
44
43
  |----------|---------|--------|
45
- | `navRoute` | `business.human-resources.projects` | `_seedDataMeta.navRoute` |
46
- | `contextCode` | `business` | `_seedDataMeta.contextCode` |
44
+ | `navRoute` | `human-resources.projects` | `_seedDataMeta.navRoute` |
47
45
  | `appCode` | `human-resources` | `_seedDataMeta.appCode` |
48
46
  | `moduleCode` | `projects` | `task.module` |
49
47
  | `navModules[]` | `[{code, label, icon, route, translations}]` | `coreSeedData.navigationModules` |
@@ -72,24 +70,15 @@ From `seedDataCore.navigationApplications[0]` in feature.json (generated by BA s
72
70
  | `{appLabel_xx}` | `navigationApplications[0].labels.xx` (fr, en, it, de) |
73
71
  | `{appDesc_xx}` | `navigationApplications[0].description.xx` |
74
72
  | `{appIcon}` | `navigationApplications[0].icon` |
75
- | `{contextCode}` | `navigationApplications[0].context` or `_seedDataMeta.contextCode` |
76
73
 
77
74
  ### GUID Generation Rule
78
75
 
79
- > **CRITICAL — NavigationContext IDs are NEVER generated as deterministic GUIDs.**
80
- > Contexts (`business`, `platform`, `personal`) are pre-seeded by SmartStack core with hardcoded GUIDs.
81
- > The `contextId` parameter in `GetApplicationEntry(Guid contextId)` is resolved at runtime
82
- > by querying `db.NavigationContexts.FirstOrDefaultAsync(c => c.Code == "business", ct)`.
83
- > **FORBIDDEN:** `GenerateDeterministicGuid("nav:business")` or any ContextId constant in SeedConstants.
84
76
 
85
77
  ```csharp
86
- // Deterministic GUID for APPLICATION (not context — contexts are pre-seeded by SmartStack core)
78
+ // Deterministic GUID for APPLICATION
87
79
  public static readonly Guid ApplicationId =
88
- GenerateDeterministicGuid("navigation-application-{contextCode}.{appCode}");
89
- // Example: GenerateDeterministicGuid("navigation-application-business.human-resources")
90
- //
91
- // FORBIDDEN — Context IDs must NOT be generated:
92
- // public static readonly Guid BusinessContextId = GenerateDeterministicGuid("nav:business"); // WRONG!
80
+ GenerateDeterministicGuid("navigation-application-{appCode}");
81
+ // Example: GenerateDeterministicGuid("navigation-application-human-resources")
93
82
  ```
94
83
 
95
84
  ### Template
@@ -108,23 +97,22 @@ public static class NavigationApplicationSeedData
108
97
  {
109
98
  // Deterministic GUID for this application
110
99
  public static readonly Guid ApplicationId =
111
- GenerateDeterministicGuid("navigation-application-{contextCode}.{appCode}");
100
+ GenerateDeterministicGuid("navigation-application-{appCode}");
112
101
 
113
102
  /// <summary>
114
103
  /// Returns navigation application entry for seeding into core.nav_Applications.
115
104
  /// </summary>
116
- public static NavigationApplicationSeedEntry GetApplicationEntry(Guid contextId)
105
+ public static NavigationApplicationSeedEntry GetApplicationEntry()
117
106
  {
118
107
  return new NavigationApplicationSeedEntry
119
108
  {
120
109
  Id = ApplicationId,
121
- ContextId = contextId,
122
110
  Code = "{appCode}",
123
111
  Label = "{appLabel_en}",
124
112
  Description = "{appDesc_en}",
125
113
  Icon = "{appIcon}", // Lucide React icon name
126
114
  IconType = IconType.Lucide,
127
- Route = ToKebabCase("/{contextCode}/{appCode}"),
115
+ Route = ToKebabCase("/{appCode}"),
128
116
  DisplayOrder = 1,
129
117
  IsActive = true
130
118
  };
@@ -212,7 +200,6 @@ public static class NavigationApplicationSeedData
212
200
  public class NavigationApplicationSeedEntry
213
201
  {
214
202
  public Guid Id { get; init; }
215
- public Guid ContextId { get; init; }
216
203
  public string Code { get; init; } = null!;
217
204
  public string Label { get; init; } = null!;
218
205
  public string? Description { get; init; }
@@ -245,7 +232,7 @@ private static Guid GenerateDeterministicGuid(string seed)
245
232
 
246
233
  // Usage: GUIDs are derived from the navigation path
247
234
  public static readonly Guid ModuleId = GenerateDeterministicGuid("navigation-module-{navRoute}");
248
- // Example: GenerateDeterministicGuid("navigation-module-business.human-resources.projects")
235
+ // Example: GenerateDeterministicGuid("navigation-module-human-resources.projects")
249
236
  ```
250
237
 
251
238
  ### Template
@@ -279,7 +266,7 @@ public static class {ModulePascal}NavigationSeedData
279
266
  Description = "{desc_en}",
280
267
  Icon = "{icon}", // Lucide React icon name
281
268
  IconType = IconType.Lucide,
282
- Route = ToKebabCase($"/{contextCode}/{appCode}/{moduleCode}"),
269
+ Route = ToKebabCase($"/{appCode}/{moduleCode}"),
283
270
  DisplayOrder = {displayOrder},
284
271
  IsActive = true
285
272
  };
@@ -337,7 +324,7 @@ public static class {ModulePascal}NavigationSeedData
337
324
 
338
325
  /// <summary>
339
326
  /// Converts PascalCase route segments to kebab-case for web URLs.
340
- /// Example: /business/HumanResources/TimeManagement → /business/human-resources/time-management
327
+ /// Example: /HumanResources/TimeManagement → /human-resources/time-management
341
328
  /// </summary>
342
329
  private static string ToKebabCase(string route)
343
330
  {
@@ -406,20 +393,20 @@ public class NavigationTranslationSeedEntry
406
393
  // Section GUID: deterministic from navRoute + section code
407
394
  public static readonly Guid {SectionPascal}SectionId =
408
395
  GenerateDeterministicGuid("navigation-section-{navRoute}.{sectionCode}");
409
- // Example: GenerateDeterministicGuid("navigation-section-business.human-resources.employees.list")
396
+ // Example: GenerateDeterministicGuid("navigation-section-human-resources.employees.list")
410
397
 
411
398
  // Resource GUID: deterministic from navRoute + section code + resource code
412
399
  public static readonly Guid {ResourcePascal}ResourceId =
413
400
  GenerateDeterministicGuid("navigation-resource-{navRoute}.{sectionCode}.{resourceCode}");
414
- // Example: GenerateDeterministicGuid("navigation-resource-business.human-resources.employees.list.employees-grid")
401
+ // Example: GenerateDeterministicGuid("navigation-resource-human-resources.employees.list.employees-grid")
415
402
  ```
416
403
 
417
404
  ### Section Methods (add to {ModulePascal}NavigationSeedData.cs)
418
405
 
419
406
  > **ROUTE SPECIAL CASES (list and detail):**
420
407
  > The `list` and `detail` sections are view modes of the module, NOT functional sub-areas.
421
- > - `list` section route = module route (e.g., `/business/human-resources/employees`) — NO `/list` suffix
422
- > - `detail` section route = module route + `/:id` (e.g., `/business/human-resources/employees/:id`) — NOT `/detail/:id`
408
+ > - `list` section route = module route (e.g., `/human-resources/employees`) — NO `/list` suffix
409
+ > - `detail` section route = module route + `/:id` (e.g., `/human-resources/employees/:id`) — NOT `/detail/:id`
423
410
  > - FORBIDDEN: `/{module}/list`, `/{module}/detail/:id`
424
411
  > - Other sections (dashboard, approve, import) = module route + `/{section-kebab}` (normal)
425
412
 
@@ -542,9 +529,9 @@ public static IEnumerable<NavigationResourceSeedEntry> GetResourceEntries(Guid s
542
529
  // Then append: /{resource-kebab}
543
530
  //
544
531
  // Example: resource "export" under section "dashboard":
545
- // Route = /business/human-resources/employees/dashboard/export
532
+ // Route = /human-resources/employees/dashboard/export
546
533
  // Example: resource "employees-grid" under section "list":
547
- // Route = /business/human-resources/employees/employees-grid (NOT /employees/list/employees-grid)
534
+ // Route = /human-resources/employees/employees-grid (NOT /employees/list/employees-grid)
548
535
  new NavigationResourceSeedEntry
549
536
  {
550
537
  Id = {Resource1Pascal}ResourceId,
@@ -678,22 +665,20 @@ MCP returns:
678
665
  ### Step B: Write Permissions.cs (Application layer)
679
666
 
680
667
  > **CRITICAL — Permission paths use the SAME kebab-case as NavRoute codes.**
681
- > `{navRoute}` is already kebab-case (e.g., `business.human-resources.employees`).
668
+ > `{navRoute}` is already kebab-case (e.g., `human-resources.employees`).
682
669
  > NEVER strip hyphens or derive codes from C# class names.
683
- > FORBIDDEN: `business.humanresources.employees.read` → CORRECT: `business.human-resources.employees.read`
684
- > SmartStack.app reference: `business.support-client.my-tickets.read`
670
+ > FORBIDDEN: `humanresources.employees.read` → CORRECT: `human-resources.employees.read`
671
+ > SmartStack.app reference: `support-client.my-tickets.read`
685
672
 
686
673
  ```csharp
687
674
  // Add to Application/Common/Authorization/Permissions.cs
688
- // IMPORTANT: {navRoute} uses kebab-case segments (e.g., "business.human-resources.employees")
675
+ // IMPORTANT: {navRoute} uses kebab-case segments (e.g., "human-resources.employees")
689
676
  // Do NOT derive permission codes from C# identifiers — use navRoute directly
690
- public static class {ContextPascal}
677
+ public static class {AppPascal}
691
678
  {
692
- public const string Access = "{contextCode}.{appCode}";
693
-
694
679
  public static class {ModulePascal}
695
680
  {
696
- public const string View = "{navRoute}.read"; // e.g., "business.human-resources.employees.read"
681
+ public const string View = "{navRoute}.read"; // e.g., "human-resources.employees.read"
697
682
  public const string Create = "{navRoute}.create";
698
683
  public const string Update = "{navRoute}.update";
699
684
  public const string Delete = "{navRoute}.delete";
@@ -949,11 +934,9 @@ public class ApplicationRoleSeedEntry
949
934
 
950
935
  ### Context-Based Role Mapping
951
936
 
952
- | Context | Admin | Manager | Contributor | Viewer |
953
- |---------|-------|---------|-------------|--------|
954
- | `platform.*` | CRUD | CRU | CR | R |
955
- | `business.*` | CRUD | CRU | CR | R |
956
- | `personal.*` | CRUD | CRU | CR | R |
937
+ | Application | Admin | Manager | Contributor | Viewer |
938
+ |-------------|-------|---------|-------------|--------|
939
+ | Any | CRUD | CRU | CR | R |
957
940
 
958
941
  ### Template
959
942
 
@@ -1059,7 +1042,7 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1059
1042
  // NOTE: Idempotence is at MODULE level (not application level).
1060
1043
  // If the application already exists, we load it and continue to seed any missing modules.
1061
1044
  // This allows adding Module 2+ to an existing application without re-running the full seed.
1062
- var appEntry = NavigationApplicationSeedData.GetApplicationEntry(Guid.Empty); // contextId resolved below
1045
+ var appEntry = NavigationApplicationSeedData.GetApplicationEntry();
1063
1046
  var existingApp = await context.NavigationApplications
1064
1047
  .FirstOrDefaultAsync(a => a.Code == appEntry.Code, ct);
1065
1048
 
@@ -1070,13 +1053,8 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1070
1053
  }
1071
1054
  else
1072
1055
  {
1073
- var parentContext = await context.NavigationContexts
1074
- .FirstAsync(c => c.Code == "{contextCode}", ct);
1075
-
1076
- // Re-get entry with resolved contextId
1077
- appEntry = NavigationApplicationSeedData.GetApplicationEntry(parentContext.Id);
1078
1056
  app = NavigationApplication.Create(
1079
- appEntry.ContextId, appEntry.Code, appEntry.Label,
1057
+ appEntry.Code, appEntry.Label,
1080
1058
  appEntry.Description, appEntry.Icon, appEntry.IconType,
1081
1059
  appEntry.Route, appEntry.DisplayOrder);
1082
1060
  context.NavigationApplications.Add(app);
@@ -1218,12 +1196,12 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1218
1196
  public async Task SeedPermissionsAsync(ICoreDbContext context, CancellationToken ct)
1219
1197
  {
1220
1198
  var exists = await context.Permissions
1221
- .AnyAsync(p => p.Path == "{contextCode}.{appCode}.*", ct);
1199
+ .AnyAsync(p => p.Path == "{appCode}.*", ct);
1222
1200
  if (exists) return;
1223
1201
 
1224
1202
  // Application-level wildcard
1225
1203
  var appWildcard = Permission.CreateWildcard(
1226
- "{contextCode}.{appCode}.*", PermissionLevel.Application,
1204
+ "{appCode}.*", PermissionLevel.Application,
1227
1205
  "Full {appLabel_en} access");
1228
1206
  context.Permissions.Add(appWildcard);
1229
1207
 
@@ -1245,7 +1223,7 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1245
1223
  public async Task SeedRolePermissionsAsync(ICoreDbContext context, CancellationToken ct)
1246
1224
  {
1247
1225
  var exists = await context.RolePermissions
1248
- .AnyAsync(rp => rp.Permission!.Path.StartsWith("{contextCode}.{appCode}."), ct);
1226
+ .AnyAsync(rp => rp.Permission!.Path.StartsWith("{appCode}."), ct);
1249
1227
  if (exists) return;
1250
1228
 
1251
1229
  // CRITICAL: Resolve roles by Code from DB — NEVER use deterministic GUIDs.
@@ -1258,7 +1236,7 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1258
1236
 
1259
1237
  // Resolve permissions
1260
1238
  var permissions = await context.Permissions
1261
- .Where(p => p.Path.StartsWith("{contextCode}.{appCode}."))
1239
+ .Where(p => p.Path.StartsWith("{appCode}."))
1262
1240
  .ToListAsync(ct);
1263
1241
 
1264
1242
  // Apply role-permission mappings from all modules
@@ -1349,9 +1327,8 @@ Before marking the task as completed, verify ALL:
1349
1327
 
1350
1328
  **Application-Level (FIRST — before modules):**
1351
1329
  - [ ] `NavigationApplicationSeedData.cs` created (once per application, at `Infrastructure/Persistence/Seeding/Data/`)
1352
- - [ ] Application GUID is deterministic (SHA256 of `"navigation-application-{contextCode}.{appCode}"`)
1353
- - [ ] **NO ContextId constant in SeedConstants** — Context IDs are pre-seeded by SmartStack core (hardcoded GUIDs, NOT deterministic)
1354
- - [ ] **SeedDataProvider queries context by code at runtime:** `db.NavigationContexts.FirstOrDefaultAsync(c => c.Code == "{contextCode}", ct)`
1330
+ - [ ] Application GUID is deterministic (SHA256 of `"navigation-application-{appCode}"`)
1331
+ - [ ] GetApplicationEntry() takes no parameters (no contextId)
1355
1332
  - [ ] Application translations created (4 languages: fr, en, it, de, EntityType = Application)
1356
1333
  - [ ] `IClientSeedDataProvider.SeedNavigationAsync()` uses `NavigationApplicationSeedData` (NO hardcoded `{appLabel_en}` / `{appIcon}` placeholders)
1357
1334
  - [ ] `ApplicationRolesSeedData.ApplicationId` references `NavigationApplicationSeedData.ApplicationId` (NO `{ApplicationGuid}` placeholder)
@@ -0,0 +1,82 @@
1
+ # Examine Build & Migration Validation
2
+
3
+ > **Loaded by:** step-04-examine.md (sections 4-5)
4
+ > **Purpose:** Build verification, migration validation, database testing procedures.
5
+
6
+ ---
7
+
8
+ ## Build Verification
9
+
10
+ ```bash
11
+ # Backend
12
+ dotnet clean && dotnet restore && dotnet build
13
+ # Note: WSL bin\Debug cleanup handled by PostToolUse hook (wsl-dotnet-cleanup.sh)
14
+
15
+ # Frontend (if applicable)
16
+ npm run typecheck
17
+ ```
18
+
19
+ **BLOCKING:** Both must pass. If failure, classify error per `references/error-classification.md`:
20
+ - Category A (missing package) → `dotnet add package` → rebuild
21
+ - Category B (assembly conflict) → resolve version → rebuild
22
+ - Category C (DI missing) → fix DI registration → rebuild
23
+ - Category D (migration broken) → fix migration → rebuild
24
+ - Category E (config) → fix config → rebuild
25
+ - Category F (source code) → fix code → rebuild
26
+
27
+ ---
28
+
29
+ ## Migration Validation (if needs_migration)
30
+
31
+ ### Pending Model Changes Check
32
+
33
+ ```bash
34
+ INFRA_PROJECT=$(ls src/*Infrastructure*/*.csproj 2>/dev/null | head -1)
35
+ API_PROJECT=$(ls src/*Api*/*.csproj 2>/dev/null | head -1)
36
+
37
+ dotnet ef migrations has-pending-model-changes \
38
+ --project "$INFRA_PROJECT" \
39
+ --startup-project "$API_PROJECT"
40
+ ```
41
+
42
+ **BLOCKING** if pending changes detected → migration is missing.
43
+
44
+ ### Migration Application Test (SQL Server LocalDB)
45
+
46
+ ```bash
47
+ DB_NAME="SmartStack_Apex_Examine_$(date +%s)"
48
+ CONN_STRING="Server=(localdb)\\MSSQLLocalDB;Database=$DB_NAME;Integrated Security=true;TrustServerCertificate=true;Connect Timeout=120;"
49
+
50
+ dotnet ef database update \
51
+ --connection "$CONN_STRING" \
52
+ --project "$INFRA_PROJECT" \
53
+ --startup-project "$API_PROJECT"
54
+ ```
55
+
56
+ **BLOCKING** if migration fails on SQL Server. Common issues:
57
+ - SQLite-only syntax in migrations (fix: regenerate migration)
58
+ - Column type mismatches (fix: update EF configuration)
59
+ - Missing foreign key targets (fix: reorder migrations)
60
+
61
+ ### Integration Tests on Real SQL Server
62
+
63
+ ```bash
64
+ # Integration tests use DatabaseFixture → real SQL Server LocalDB
65
+ # This validates: LINQ→SQL, multi-tenant isolation, soft delete, EF configs
66
+ INT_TEST_PROJECT=$(ls tests/*Tests.Integration*/*.csproj 2>/dev/null | head -1)
67
+ if [ -n "$INT_TEST_PROJECT" ]; then
68
+ dotnet test "$INT_TEST_PROJECT" --no-build --verbosity normal
69
+ fi
70
+ ```
71
+
72
+ Tests running against SQL Server catch issues that SQLite misses:
73
+ - Case sensitivity in string comparisons
74
+ - Date/time function differences
75
+ - IDENTITY vs AUTOINCREMENT behavior
76
+ - Global query filter translation to T-SQL
77
+
78
+ ### Cleanup
79
+
80
+ ```bash
81
+ sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "IF DB_ID('$DB_NAME') IS NOT NULL BEGIN ALTER DATABASE [$DB_NAME] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [$DB_NAME]; END" 2>/dev/null
82
+ ```
@@ -0,0 +1,177 @@
1
+ # Frontend Compliance Gate — 5 Mandatory Checks
2
+
3
+ > **Loaded by:** step-03-execute.md (FRONTEND COMPLIANCE GATE section)
4
+ > **Condition:** MANDATORY before any frontend commit
5
+ > **Purpose:** Automated checks that catch the most common failures in generated code.
6
+
7
+ ---
8
+
9
+ ## Gate 1: CSS Variables (Theme System)
10
+
11
+ Check for hardcoded Tailwind colors — MUST use CSS variables.
12
+
13
+ ```bash
14
+ ALL_PAGES=$(find src/pages/ src/components/ -name "*.tsx" 2>/dev/null | grep -v node_modules | grep -v "\.test\.")
15
+ if [ -n "$ALL_PAGES" ]; then
16
+ HARDCODED=$(grep -Pn '(bg|text|border)-(?!\[)(red|blue|green|gray|white|black|slate|zinc|neutral|stone)-' $ALL_PAGES 2>/dev/null)
17
+ if [ -n "$HARDCODED" ]; then
18
+ echo "FAIL: Hardcoded Tailwind colors found — must use CSS variables"
19
+ echo "$HARDCODED"
20
+ else
21
+ echo "PASS: CSS variables"
22
+ fi
23
+ fi
24
+ ```
25
+
26
+ **If hardcoded colors found, replace BEFORE committing:**
27
+
28
+ | Old | New |
29
+ |-----|-----|
30
+ | `bg-white` | `bg-[var(--bg-card)]` |
31
+ | `bg-gray-50` | `bg-[var(--bg-primary)]` |
32
+ | `text-gray-900` | `text-[var(--text-primary)]` |
33
+ | `text-gray-500/600` | `text-[var(--text-secondary)]` |
34
+ | `border-gray-200` | `border-[var(--border-color)]` |
35
+ | `bg-blue-600` / `text-blue-600` | `bg-[var(--color-accent-500)]` / `text-[var(--color-accent-500)]` |
36
+ | `hover:bg-blue-700` | `hover:bg-[var(--color-accent-600)]` |
37
+ | `text-red-500` | `text-[var(--error-text)]` |
38
+ | `bg-green-500` | `bg-[var(--success-bg)]` |
39
+
40
+ ---
41
+
42
+ ## Gate 2: Forms as Pages (ZERO Modals/Drawers/Slide-overs)
43
+
44
+ Check for modal/dialog/drawer/slide-over imports and inline form patterns — FORBIDDEN.
45
+
46
+ ```bash
47
+ PAGE_FILES=$(find src/pages/ -name "*.tsx" 2>/dev/null)
48
+ if [ -n "$PAGE_FILES" ]; then
49
+ FAIL=false
50
+
51
+ # 2a. Component imports
52
+ MODAL_IMPORTS=$(grep -Pn "import.*(?:Modal|Dialog|Drawer|Popup|Sheet|SlideOver|Overlay)" $PAGE_FILES 2>/dev/null)
53
+ if [ -n "$MODAL_IMPORTS" ]; then
54
+ echo "FAIL: Modal/Dialog/Drawer component imports — forms MUST be full pages"
55
+ echo "$MODAL_IMPORTS"
56
+ FAIL=true
57
+ fi
58
+
59
+ # 2b. State variables for inline forms (catches drawers/slide-overs without imports)
60
+ MODAL_STATE=$(grep -Pn "useState.*(?:isOpen|showModal|showDialog|showCreate|showEdit|showForm|isCreating|isEditing|showDrawer|showPanel|showSlideOver|selectedEntity|editingEntity)" $PAGE_FILES 2>/dev/null)
61
+ if [ -n "$MODAL_STATE" ]; then
62
+ echo "FAIL: Inline form state detected — forms MUST be separate page components with own routes"
63
+ echo "$MODAL_STATE"
64
+ FAIL=true
65
+ fi
66
+
67
+ if [ "$FAIL" = true ]; then
68
+ echo "Fix: Create EntityCreatePage.tsx (route: /create) and EntityEditPage.tsx (route: /:id/edit)"
69
+ echo "See smartstack-frontend.md section 3b"
70
+ else
71
+ echo "PASS: No modals/drawers"
72
+ fi
73
+ fi
74
+ ```
75
+
76
+ **If modals/drawers found:** Replace with separate `EntityCreatePage.tsx` (route: `/{module}/create`) and `EntityEditPage.tsx` (route: `/{module}/:id/edit`). See `smartstack-frontend.md` section 3b.
77
+
78
+ ---
79
+
80
+ ## Gate 3: I18n File Structure
81
+
82
+ Verify translation files exist as separate JSON per language.
83
+
84
+ ```bash
85
+ if [ ! -d "src/i18n/locales" ]; then
86
+ echo "FAIL: Missing src/i18n/locales/ directory — create it with 4 languages"
87
+ else
88
+ for LANG in fr en it de; do
89
+ JSON_FILES=$(find "src/i18n/locales/$LANG" -name "*.json" 2>/dev/null | wc -l)
90
+ if [ "$JSON_FILES" -eq 0 ]; then
91
+ echo "FAIL: No JSON files in src/i18n/locales/$LANG/"
92
+ else
93
+ echo "PASS: $LANG ($JSON_FILES files)"
94
+ fi
95
+ done
96
+ fi
97
+ ```
98
+
99
+ **If i18n structure wrong:** Create `src/i18n/locales/{fr,en,it,de}/{module}.json` following the template in `smartstack-frontend.md` section 2. NEVER embed translations in a single `.ts` file.
100
+
101
+ **Correct structure:**
102
+ ```
103
+ src/i18n/locales/
104
+ ├── fr/{module}.json ← French (primary)
105
+ ├── en/{module}.json ← English
106
+ ├── it/{module}.json ← Italian
107
+ └── de/{module}.json ← German
108
+ ```
109
+
110
+ Each file MUST contain: `title`, `description`, `actions`, `labels`, `columns`, `form`, `errors`, `validation`, `messages`, `empty`.
111
+
112
+ ---
113
+
114
+ ## Gate 4: Lazy Loading
115
+
116
+ Check for static page imports in route/App files.
117
+
118
+ ```bash
119
+ APP_TSX=$(find src/ -name "App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
120
+ ROUTE_FILES=$(find src/routes/ -name "*.tsx" -o -name "*.ts" 2>/dev/null)
121
+ if [ -n "$APP_TSX" ]; then
122
+ STATIC_IMPORTS=$(grep -Pn "^import .+ from '@/pages/" "$APP_TSX" $ROUTE_FILES 2>/dev/null)
123
+ if [ -n "$STATIC_IMPORTS" ]; then
124
+ echo "FAIL: Static page imports in App.tsx/routes — MUST use React.lazy()"
125
+ echo "$STATIC_IMPORTS"
126
+ else
127
+ echo "PASS: Lazy loading"
128
+ fi
129
+ fi
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Gate 5: useTranslation in Pages
135
+
136
+ Verify pages use i18n.
137
+
138
+ ```bash
139
+ PAGE_FILES=$(find src/pages/ -name "*.tsx" 2>/dev/null | grep -v "\.test\." | grep -v node_modules)
140
+ if [ -n "$PAGE_FILES" ]; then
141
+ TOTAL=$(echo "$PAGE_FILES" | wc -l)
142
+ WITH_I18N=$(grep -l "useTranslation" $PAGE_FILES 2>/dev/null | wc -l)
143
+ if [ "$WITH_I18N" -eq 0 ]; then
144
+ echo "FAIL: No pages use useTranslation — all text must be translated"
145
+ else
146
+ echo "PASS: $WITH_I18N/$TOTAL pages use useTranslation"
147
+ fi
148
+ fi
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Explicit I18n File Creation
154
+
155
+ When creating i18n files, generate EXACTLY this structure:
156
+
157
+ ```
158
+ src/i18n/locales/
159
+ ├── fr/{module}.json ← French (primary)
160
+ ├── en/{module}.json ← English
161
+ ├── it/{module}.json ← Italian
162
+ └── de/{module}.json ← German
163
+ ```
164
+
165
+ Each file MUST contain these keys: `title`, `description`, `actions`, `labels`, `columns`, `form`, `errors`, `validation`, `messages`, `empty`. See `smartstack-frontend.md` section 2 for the complete JSON template.
166
+
167
+ ---
168
+
169
+ ## ALL 5 Gates MUST PASS
170
+
171
+ **Before creating the frontend commit:**
172
+ 1. Do NOT commit frontend changes until ALL checks pass
173
+ 2. If ANY gate fails, fix the issues first
174
+ 3. When delegating to `/ui-components` skill, include explicit instructions:
175
+ - "CSS: Use CSS variables ONLY — `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`. NEVER use hardcoded Tailwind colors."
176
+ - "Forms: Create/Edit forms are FULL PAGES with own routes (e.g., `/create`, `/:id/edit`). NEVER use modals/dialogs."
177
+ - "I18n: ALL text must use `t('namespace:key', 'Fallback')`. Generate JSON files in `src/i18n/locales/`."
@@ -0,0 +1,105 @@
1
+ # Frontend Patterns — Economy Mode Guidelines
2
+
3
+ > **Loaded by:** step-03-execute.md (Layer 1 section: economy_mode frontend tasks)
4
+ > **Purpose:** Quick reference for frontend creation in sequential (economy) mode.
5
+ > **Detailed patterns:** See `smartstack-frontend.md` (referenced from smartstack-layers.md)
6
+
7
+ ---
8
+
9
+ ## Frontend Tasks — Sequential Execution (economy_mode)
10
+
11
+ For each frontend task in the plan (Layer 1):
12
+
13
+ 1. **API Client:** `MCP scaffold_api_client` → API client + types + React Query hook
14
+ 2. **Routes:** `MCP scaffold_routes` with `outputFormat: 'clientRoutes'` for lazy imports
15
+ 3. **Pages:** **INVOKE `/ui-components` skill** (read SKILL.md + ALL patterns) — MANDATORY for ALL page types
16
+
17
+ ---
18
+
19
+ ## Required Page Types Per Module
20
+
21
+ Create ALL 4 page types per module:
22
+ - `ListPage.tsx` — entity list with SmartTable/EntityCard
23
+ - `DetailPage.tsx` — entity detail view
24
+ - `EntityCreatePage.tsx` (route: `/create`) — FULL PAGE form, NEVER modal
25
+ - `EntityEditPage.tsx` (route: `/:id/edit`) — FULL PAGE form, NEVER modal
26
+
27
+ **Wire ALL routes in App.tsx:** `index` (ListPage), `:id` (DetailPage), `create` (CreatePage), `:id/edit` (EditPage)
28
+
29
+ ---
30
+
31
+ ## Foreign Key (FK) Fields — CRITICAL
32
+
33
+ Any Guid FK property (e.g., EmployeeId, DepartmentId) MUST use `EntityLookup` component:
34
+ - **NEVER** a `<select>` dropdown
35
+ - **NEVER** a `<input type="text">`
36
+ - **A `<select>` loaded from API state is NOT a substitute for EntityLookup**
37
+
38
+ See `smartstack-frontend.md` section 6 for the full EntityLookup pattern. Backend GetAll endpoints MUST support `?search=` parameter (enables EntityLookup on frontend).
39
+
40
+ ---
41
+
42
+ ## Forms: ZERO Modals/Popups/Drawers/Slide-overs
43
+
44
+ **ALL forms are full pages with their own URL:**
45
+ - Create forms: route `/{module}/create`
46
+ - Edit forms: route `/{module}/:id/edit`
47
+ - NEVER embed forms as drawers, panels, or slide-overs
48
+ - Back button with `navigate(-1)` on every form page
49
+
50
+ ---
51
+
52
+ ## Detail Pages: Tab Behavior (CRITICAL)
53
+
54
+ **Tabs MUST switch content LOCALLY via `setActiveTab()` — NEVER `navigate()` to another page.**
55
+
56
+ Sub-resource data (e.g., employee's leaves) loads inline via API call filtered by parent entity ID. See `smartstack-frontend.md` section 3 "Tab Behavior Rules".
57
+
58
+ ---
59
+
60
+ ## Tests (MANDATORY)
61
+
62
+ Generate form tests as co-located files:
63
+ - `EntityCreatePage.test.tsx` (next to CreatePage.tsx)
64
+ - `EntityEditPage.test.tsx` (next to EditPage.tsx)
65
+
66
+ Cover: rendering, validation, submit, pre-fill, navigation, errors. See `smartstack-frontend.md` section 8 for test templates.
67
+
68
+ ---
69
+
70
+ ## Section-Level Routes (if sections exist)
71
+
72
+ **SECTION PERMISSIONS:** After calling `MCP generate_permissions` for the module navRoute (2 segments: `{app}.{module}`), also call it for EACH section navRoute (3 segments: `{app}.{module}.{section}`)
73
+
74
+ **SECTION ROUTES:** After generating module routes, add section child routes to the module's `children` array. Wire `PermissionGuard` for section routes with section-level permissions.
75
+
76
+ ---
77
+
78
+ ## Sub-Resource Handling
79
+
80
+ If a section controller has sub-resource endpoints (e.g., `[HttpGet("types")]` for LeaveTypes inside LeavesController), you MUST EITHER:
81
+ 1. Create dedicated frontend pages for the sub-resource (ListPage, CreatePage, EditPage) with routes wired in App.tsx, OR
82
+ 2. NOT include any `navigate()` button that links to those sub-resource pages
83
+
84
+ **Prefer separate controllers** with `[NavRoute(..., Suffix = "types")]` — see `smartstack-api.md` Sub-Resource Pattern. A dead link (navigate to a route with no page) is a BLOCKING issue (POST-CHECK 42).
85
+
86
+ ---
87
+
88
+ ## I18n (Translations)
89
+
90
+ Generate i18n JSON files for all 4 languages (fr, en, it, de):
91
+ - Location: `src/i18n/locales/{lang}/{module}.json`
92
+ - Keys: `actions`, `labels`, `errors`, `validation`, `columns`, `form`, `messages`, `empty`
93
+ - ALL `t()` calls MUST use namespace prefix + fallback: `t('ns:key', 'Default text')`
94
+
95
+ **CRITICAL:** After creating i18n JSON files, register EACH new namespace in the i18n config file (config.ts/index.ts/i18n.ts). Unregistered namespaces → `useTranslation(['module'])` returns empty strings at runtime. POST-CHECK 45 validates this.
96
+
97
+ ---
98
+
99
+ ## Folder Structure
100
+
101
+ MUST use: `src/pages/{App}/{Module}/` hierarchy (NOT flat).
102
+
103
+ All pages must follow: **hooks → useEffect(load) → loading state → error state → content**
104
+
105
+ Use **CSS variables ONLY** for styling — hardcoded Tailwind colors are BLOCKING (POST-CHECK 13).