@atlashub/smartstack-cli 3.38.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 (47) hide show
  1. package/dist/mcp-entry.mjs +62 -37
  2. package/dist/mcp-entry.mjs.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/agents/efcore/scan.md +3 -1
  5. package/templates/agents/gitflow/commit.md +74 -0
  6. package/templates/agents/gitflow/finish.md +5 -2
  7. package/templates/agents/gitflow/init-clone.md +3 -3
  8. package/templates/agents/gitflow/init-validate.md +3 -2
  9. package/templates/agents/gitflow/merge.md +5 -0
  10. package/templates/agents/gitflow/pr.md +5 -0
  11. package/templates/agents/gitflow/start.md +8 -1
  12. package/templates/hooks/hooks.json +11 -0
  13. package/templates/hooks/wsl-dotnet-cleanup.sh +24 -0
  14. package/templates/skills/apex/references/core-seed-data.md +0 -1
  15. package/templates/skills/apex/references/examine-build-validation.md +1 -6
  16. package/templates/skills/apex/references/smartstack-frontend.md +1 -1
  17. package/templates/skills/apex/steps/step-03-execute.md +4 -9
  18. package/templates/skills/apex/steps/step-08-run-tests.md +1 -2
  19. package/templates/skills/application/SKILL.md +241 -241
  20. package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +5 -5
  21. package/templates/skills/application/references/frontend-verification.md +1 -1
  22. package/templates/skills/application/references/init-parameter-detection.md +121 -120
  23. package/templates/skills/application/references/migration-checklist-troubleshooting.md +100 -100
  24. package/templates/skills/application/references/nav-fallback-procedure.md +199 -199
  25. package/templates/skills/application/steps/step-00-init.md +130 -130
  26. package/templates/skills/application/steps/step-01-navigation.md +170 -170
  27. package/templates/skills/application/steps/step-02-permissions.md +196 -196
  28. package/templates/skills/application/steps/step-03-roles.md +182 -182
  29. package/templates/skills/application/steps/step-03b-provider.md +133 -133
  30. package/templates/skills/application/steps/step-04-backend.md +174 -174
  31. package/templates/skills/application/steps/step-05-frontend.md +1 -1
  32. package/templates/skills/application/templates-frontend.md +7 -7
  33. package/templates/skills/business-analyse/react/schema.md +836 -836
  34. package/templates/skills/business-analyse/templates/tpl-progress.md +1 -1
  35. package/templates/skills/business-analyse/templates-frd.md +1 -1
  36. package/templates/skills/efcore/SKILL.md +1 -1
  37. package/templates/skills/efcore/steps/migration/step-02-create.md +1 -14
  38. package/templates/skills/gitflow/SKILL.md +27 -4
  39. package/templates/skills/gitflow/_shared.md +86 -12
  40. package/templates/skills/gitflow/phases/abort.md +4 -0
  41. package/templates/skills/gitflow/phases/cleanup.md +4 -0
  42. package/templates/skills/gitflow/references/finish-cleanup.md +4 -0
  43. package/templates/skills/gitflow/references/init-structure-creation.md +4 -0
  44. package/templates/skills/gitflow/references/start-worktree-creation.md +1 -1
  45. package/templates/skills/ralph-loop/steps/step-04-check.md +1 -2
  46. package/templates/skills/review-code/references/smartstack-conventions.md +568 -568
  47. package/templates/skills/validate-feature/steps/step-01-compile.md +1 -6
@@ -27185,13 +27185,13 @@ async function validateControllerRoutes(structure, _config, result) {
27185
27185
  if (navRouteMatch) {
27186
27186
  const routePath = navRouteMatch[1];
27187
27187
  const parts = routePath.split(".");
27188
- if (parts.length < 2) {
27189
- result.warnings.push({
27190
- type: "warning",
27188
+ if (parts.length < 3) {
27189
+ result.errors.push({
27190
+ type: "error",
27191
27191
  category: "controllers",
27192
27192
  message: `Controller "${fileName}" has NavRoute with insufficient depth: "${routePath}"`,
27193
27193
  file: path8.relative(structure.root, file),
27194
- suggestion: 'NavRoute should have at least 2 levels: "application.module" (e.g., "administration.users")'
27194
+ suggestion: 'NavRoute must have at least 3 levels: "application.module.section" (e.g., "administration.users.management")'
27195
27195
  });
27196
27196
  }
27197
27197
  const hasUppercase = parts.some((part) => part !== part.toLowerCase());
@@ -27222,7 +27222,7 @@ async function validateControllerRoutes(structure, _config, result) {
27222
27222
  category: "controllers",
27223
27223
  message: `Controller "${fileName}" uses hardcoded Route instead of NavRoute`,
27224
27224
  file: path8.relative(structure.root, file),
27225
- suggestion: 'Use [NavRoute("application.module")] for navigation-based routing'
27225
+ suggestion: 'Use [NavRoute("application.module.section")] for navigation-based routing'
27226
27226
  });
27227
27227
  }
27228
27228
  }
@@ -34423,21 +34423,24 @@ var require_lib = __commonJS({
34423
34423
  import path10 from "path";
34424
34424
  function resolveHierarchy(navRoute) {
34425
34425
  if (!navRoute) {
34426
- return { application: "", module: "", domainPath: "", infraPath: "", controllerArea: "" };
34426
+ return { application: "", module: "", section: "", domainPath: "", infraPath: "", controllerArea: "" };
34427
34427
  }
34428
34428
  const segments = navRoute.split(".");
34429
34429
  const toPascal = (s) => s.split("-").map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
34430
34430
  const application = segments[0] ? toPascal(segments[0]) : "";
34431
34431
  const module = segments[1] ? toPascal(segments[1]) : "";
34432
+ const section = segments[2] ? toPascal(segments[2]) : "";
34432
34433
  let domainPath = "";
34433
- if (segments.length >= 2) {
34434
+ if (segments.length >= 3) {
34435
+ domainPath = path10.join(application, module, section);
34436
+ } else if (segments.length >= 2) {
34434
34437
  domainPath = path10.join(application, module);
34435
34438
  } else if (segments.length === 1) {
34436
34439
  domainPath = application;
34437
34440
  }
34438
34441
  const infraPath = domainPath;
34439
34442
  const controllerArea = application;
34440
- return { application, module, domainPath, infraPath, controllerArea };
34443
+ return { application, module, section, domainPath, infraPath, controllerArea };
34441
34444
  }
34442
34445
  async function handleScaffoldExtension(args, config2) {
34443
34446
  const input = ScaffoldExtensionInputSchema.parse(args);
@@ -35401,12 +35404,12 @@ public class {{name}}Controller : ControllerBase
35401
35404
  result.instructions.push("");
35402
35405
  result.instructions.push("NavRoute resolves API routes from Navigation entities in the database.");
35403
35406
  result.instructions.push("Ensure the navigation path exists (seed data required):");
35404
- result.instructions.push(` Application > Module matching "${navRoute}"`);
35407
+ result.instructions.push(` Application > Module > Section matching "${navRoute}"`);
35405
35408
  } else {
35406
35409
  result.instructions.push("Controller created with traditional routing.");
35407
35410
  result.instructions.push("");
35408
35411
  result.instructions.push("\u26A0\uFE0F Consider using NavRoute for navigation-based routing:");
35409
- result.instructions.push(` [NavRoute("application.module")]`);
35412
+ result.instructions.push(` [NavRoute("application.module.section")]`);
35410
35413
  result.instructions.push("");
35411
35414
  result.instructions.push("API endpoints (with traditional routing):");
35412
35415
  result.instructions.push(` GET /api/${name.toLowerCase()}`);
@@ -36470,7 +36473,7 @@ var init_scaffold_extension = __esm({
36470
36473
  },
36471
36474
  navRoute: {
36472
36475
  type: "string",
36473
- description: 'Navigation route path for controller (e.g., "administration.users"). Required for controllers.'
36476
+ description: 'Navigation route path for controller (e.g., "administration.users.management"). Minimum 3 levels: application.module.section. Optional 4th: resource.'
36474
36477
  },
36475
36478
  navRouteSuffix: {
36476
36479
  type: "string",
@@ -53017,8 +53020,8 @@ function generatePermissionsForNavRoute(navRoute, customActions, includeStandard
53017
53020
  const permissions = [];
53018
53021
  const parts = navRoute.split(".");
53019
53022
  const application = parts[0];
53020
- if (parts.length < 2) {
53021
- throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: application.module`);
53023
+ if (parts.length < 3) {
53024
+ throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: application.module.section (minimum 3 levels, optional 4th: resource)`);
53022
53025
  }
53023
53026
  if (includeWildcard) {
53024
53027
  permissions.push({
@@ -53128,9 +53131,20 @@ function formatPermissionDescription(navRoute, action) {
53128
53131
  const parts = navRoute.split(".");
53129
53132
  const application = parts[0];
53130
53133
  const module = parts[1];
53131
- const applicationName = application.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53132
- const moduleName = module.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53134
+ const section = parts[2];
53135
+ const toTitleCase = (s) => s.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53136
+ const applicationName = toTitleCase(application);
53137
+ const moduleName = toTitleCase(module);
53133
53138
  const actionVerb = getActionVerb(action);
53139
+ if (parts.length >= 4) {
53140
+ const sectionName = toTitleCase(section);
53141
+ const resourceName = toTitleCase(parts[parts.length - 1]);
53142
+ return `${actionVerb} ${resourceName} in ${applicationName} > ${moduleName} > ${sectionName}`;
53143
+ }
53144
+ if (section) {
53145
+ const sectionName = toTitleCase(section);
53146
+ return `${actionVerb} ${sectionName} in ${applicationName} > ${moduleName}`;
53147
+ }
53134
53148
  return `${actionVerb} ${moduleName} in ${applicationName}`;
53135
53149
  }
53136
53150
  function getActionVerb(action) {
@@ -53186,12 +53200,27 @@ function getUniqueNavRouteCount(permissions) {
53186
53200
  }
53187
53201
  function generateHasDataCode(permissions, navRoute) {
53188
53202
  const parts = navRoute.split(".");
53189
- const moduleName = parts.length >= 2 ? parts[parts.length - 1] : "custom";
53190
- const moduleVarName = `${moduleName}ModuleId`;
53203
+ const lastSegment = parts[parts.length - 1];
53204
+ const depth = parts.length;
53205
+ let permissionLevel;
53206
+ let fkProperty;
53207
+ let fkVarName;
53208
+ let seedDataSource;
53209
+ if (depth >= 4) {
53210
+ permissionLevel = "PermissionLevel.Resource";
53211
+ fkProperty = "ResourceId";
53212
+ fkVarName = `${lastSegment}ResourceId`;
53213
+ seedDataSource = "NavigationResourceSeedData.cs";
53214
+ } else {
53215
+ permissionLevel = "PermissionLevel.Section";
53216
+ fkProperty = "SectionId";
53217
+ fkVarName = `${lastSegment}SectionId`;
53218
+ seedDataSource = "NavigationSectionSeedData.cs";
53219
+ }
53191
53220
  let code = "```csharp\n";
53192
- code += `// 1. Add module ID variable (get from NavigationModuleSeedData.cs)
53221
+ code += `// 1. Add ${fkProperty} variable (get from ${seedDataSource})
53193
53222
  `;
53194
- code += `var ${moduleVarName} = Guid.Parse("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); // TODO: Replace with actual ID
53223
+ code += `var ${fkVarName} = Guid.Parse("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); // TODO: Replace with actual ID
53195
53224
 
53196
53225
  `;
53197
53226
  code += `// 2. Add these entries to the HasData() return array:
@@ -53201,11 +53230,11 @@ function generateHasDataCode(permissions, navRoute) {
53201
53230
  const action = perm.code.split(".").pop();
53202
53231
  const guidPlaceholder = generatePlaceholderGuid();
53203
53232
  if (isWildcard) {
53204
- code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = PermissionLevel.Module, IsWildcard = true, ModuleId = ${moduleVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53233
+ code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = ${permissionLevel}, IsWildcard = true, ${fkProperty} = ${fkVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53205
53234
  `;
53206
53235
  } else {
53207
53236
  const actionEnum = getActionEnum(action || "read");
53208
- code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = PermissionLevel.Module, Action = PermissionAction.${actionEnum}, IsWildcard = false, ModuleId = ${moduleVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53237
+ code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = ${permissionLevel}, Action = PermissionAction.${actionEnum}, IsWildcard = false, ${fkProperty} = ${fkVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53209
53238
  `;
53210
53239
  }
53211
53240
  }
@@ -58120,13 +58149,8 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
58120
58149
  lines.push("");
58121
58150
  return lines.join("\n");
58122
58151
  }
58123
- function getLayoutName(application) {
58124
- const layoutMap = {
58125
- administration: "AdminLayout",
58126
- support: "SupportLayout",
58127
- myspace: "UserLayout"
58128
- };
58129
- return layoutMap[application] || `${capitalize(application)}Layout`;
58152
+ function getLayoutName(_application) {
58153
+ return "AppLayout";
58130
58154
  }
58131
58155
  function toKebabCase(segment) {
58132
58156
  return segment.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
@@ -58190,7 +58214,7 @@ Creates:
58190
58214
  Example:
58191
58215
  scaffold_routes source="controllers" scope="all"
58192
58216
 
58193
- Scans backend controllers for [NavRoute("application.module")] attributes
58217
+ Scans backend controllers for [NavRoute("application.module.section")] attributes
58194
58218
  and generates corresponding frontend routing infrastructure.`,
58195
58219
  inputSchema: {
58196
58220
  type: "object",
@@ -60803,7 +60827,7 @@ async function checkAuthorization(structure, result) {
60803
60827
  message: `Controller ${controllerName} missing authorization attribute`,
60804
60828
  file: path23.relative(structure.root, file),
60805
60829
  line: lineNumber,
60806
- suggestion: 'Add [NavRoute("application.module")] or [Authorize] attribute to the controller class',
60830
+ suggestion: 'Add [NavRoute("application.module.section")] or [Authorize] attribute to the controller class',
60807
60831
  cweId: "CWE-862"
60808
60832
  });
60809
60833
  }
@@ -64710,7 +64734,7 @@ Tables are organized by domain using prefixes:
64710
64734
  | Prefix | Domain | Example Tables |
64711
64735
  |--------|--------|----------------|
64712
64736
  | \`auth_\` | Authorization | auth_Users, auth_Roles, auth_Permissions |
64713
- | \`nav_\` | Navigation | nav_Applications, nav_Modules, nav_Sections |
64737
+ | \`nav_\` | Navigation | nav_Applications, nav_Modules, nav_Sections, nav_Resources |
64714
64738
  | \`usr_\` | User profiles | usr_Profiles, usr_Preferences |
64715
64739
  | \`ai_\` | AI features | ai_Providers, ai_Models, ai_Prompts |
64716
64740
  | \`cfg_\` | Configuration | cfg_Settings |
@@ -64744,7 +64768,7 @@ In addition to the platform prefixes above, client applications define their own
64744
64768
 
64745
64769
  ### Navigation Scope System
64746
64770
 
64747
- All navigation data (Application, Module, Section) uses a **Scope** field to distinguish system data from client extensions:
64771
+ All navigation data (Application, Module, Section, Resource) uses a **Scope** field to distinguish system data from client extensions:
64748
64772
 
64749
64773
  | Scope | Usage | Description | Example Code |
64750
64774
  |-------|-------|-------------|--------------|
@@ -64753,10 +64777,10 @@ All navigation data (Application, Module, Section) uses a **Scope** field to dis
64753
64777
  | \`${scopeTypes[2]}\` | Partner modules | Provided by certified partners | \`partner_integration\` |
64754
64778
  | \`${scopeTypes[3]}\` | Community modules | Open-source community contributions | \`community_tool\` |
64755
64779
 
64756
- **Navigation Hierarchy (3 levels):**
64780
+ **Navigation Hierarchy (4 levels):**
64757
64781
 
64758
64782
  \`\`\`
64759
- Application \u2192 Module \u2192 Section
64783
+ Application \u2192 Module \u2192 Section \u2192 Resource (optional)
64760
64784
  \`\`\`
64761
64785
 
64762
64786
  **Examples for each level:**
@@ -64764,8 +64788,9 @@ Application \u2192 Module \u2192 Section
64764
64788
  | Level | Core Example | Extension Example |
64765
64789
  |-------|--------------|-------------------|
64766
64790
  | Application | Code: \`administration\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`custom_app\`<br/>Scope: \`${scopeTypes[1]}\` |
64767
- | Module | Code: \`users\`<br/>Route: \`administration.users\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`inventory\`<br/>Route: \`operations.inventory\`<br/>Scope: \`${scopeTypes[1]}\` |
64791
+ | Module | Code: \`users\`<br/>Route: \`administration.users.management\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`inventory\`<br/>Route: \`operations.inventory.list\`<br/>Scope: \`${scopeTypes[1]}\` |
64768
64792
  | Section | Code: \`management\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`reports\`<br/>Scope: \`${scopeTypes[1]}\` |
64793
+ | Resource (optional) | Code: \`dashboard\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`analytics\`<br/>Scope: \`${scopeTypes[1]}\` |
64769
64794
 
64770
64795
  **Rules:**
64771
64796
  1. \`${scopeTypes[0]}\` modules are **protected** - clients cannot create or modify them
@@ -65583,7 +65608,7 @@ All tenant-related tables use the \`tenant_\` prefix:
65583
65608
 
65584
65609
  ### Layout Standards
65585
65610
 
65586
- All application layouts MUST follow the AdminLayout pattern for consistent user experience.
65611
+ All applications use the unified AppLayout for consistent user experience.
65587
65612
 
65588
65613
  #### Standard Structure
65589
65614
 
@@ -65725,7 +65750,7 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65725
65750
  #### Hierarchy Pattern
65726
65751
 
65727
65752
  \`\`\`
65728
- Application > Module > [Section] > [Entity Name]
65753
+ Application > Module > [Section] > [Resource] > [Entity Name]
65729
65754
  \`\`\`
65730
65755
 
65731
65756
  **Examples:**