@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.
- package/dist/mcp-entry.mjs +62 -37
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/efcore/scan.md +3 -1
- package/templates/agents/gitflow/commit.md +74 -0
- package/templates/agents/gitflow/finish.md +5 -2
- package/templates/agents/gitflow/init-clone.md +3 -3
- package/templates/agents/gitflow/init-validate.md +3 -2
- package/templates/agents/gitflow/merge.md +5 -0
- package/templates/agents/gitflow/pr.md +5 -0
- package/templates/agents/gitflow/start.md +8 -1
- package/templates/hooks/hooks.json +11 -0
- package/templates/hooks/wsl-dotnet-cleanup.sh +24 -0
- package/templates/skills/apex/references/core-seed-data.md +0 -1
- package/templates/skills/apex/references/examine-build-validation.md +1 -6
- package/templates/skills/apex/references/smartstack-frontend.md +1 -1
- package/templates/skills/apex/steps/step-03-execute.md +4 -9
- package/templates/skills/apex/steps/step-08-run-tests.md +1 -2
- package/templates/skills/application/SKILL.md +241 -241
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +5 -5
- package/templates/skills/application/references/frontend-verification.md +1 -1
- package/templates/skills/application/references/init-parameter-detection.md +121 -120
- package/templates/skills/application/references/migration-checklist-troubleshooting.md +100 -100
- package/templates/skills/application/references/nav-fallback-procedure.md +199 -199
- package/templates/skills/application/steps/step-00-init.md +130 -130
- package/templates/skills/application/steps/step-01-navigation.md +170 -170
- package/templates/skills/application/steps/step-02-permissions.md +196 -196
- package/templates/skills/application/steps/step-03-roles.md +182 -182
- package/templates/skills/application/steps/step-03b-provider.md +133 -133
- package/templates/skills/application/steps/step-04-backend.md +174 -174
- package/templates/skills/application/steps/step-05-frontend.md +1 -1
- package/templates/skills/application/templates-frontend.md +7 -7
- package/templates/skills/business-analyse/react/schema.md +836 -836
- package/templates/skills/business-analyse/templates/tpl-progress.md +1 -1
- package/templates/skills/business-analyse/templates-frd.md +1 -1
- package/templates/skills/efcore/SKILL.md +1 -1
- package/templates/skills/efcore/steps/migration/step-02-create.md +1 -14
- package/templates/skills/gitflow/SKILL.md +27 -4
- package/templates/skills/gitflow/_shared.md +86 -12
- package/templates/skills/gitflow/phases/abort.md +4 -0
- package/templates/skills/gitflow/phases/cleanup.md +4 -0
- package/templates/skills/gitflow/references/finish-cleanup.md +4 -0
- package/templates/skills/gitflow/references/init-structure-creation.md +4 -0
- package/templates/skills/gitflow/references/start-worktree-creation.md +1 -1
- package/templates/skills/ralph-loop/steps/step-04-check.md +1 -2
- package/templates/skills/review-code/references/smartstack-conventions.md +568 -568
- package/templates/skills/validate-feature/steps/step-01-compile.md +1 -6
package/dist/mcp-entry.mjs
CHANGED
|
@@ -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 <
|
|
27189
|
-
result.
|
|
27190
|
-
type: "
|
|
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
|
|
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 >=
|
|
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").
|
|
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 <
|
|
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
|
|
53132
|
-
const
|
|
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
|
|
53190
|
-
const
|
|
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
|
|
53221
|
+
code += `// 1. Add ${fkProperty} variable (get from ${seedDataSource})
|
|
53193
53222
|
`;
|
|
53194
|
-
code += `var ${
|
|
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 =
|
|
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 =
|
|
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(
|
|
58124
|
-
|
|
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 (
|
|
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
|
|
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:**
|