@atlashub/smartstack-cli 3.21.0 → 3.22.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 (28) hide show
  1. package/dist/index.js +17 -5
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +68 -3
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/templates/skills/application/references/application-roles-template.md +2 -2
  7. package/templates/skills/application/steps/step-05-frontend.md +40 -35
  8. package/templates/skills/application/templates-frontend.md +64 -36
  9. package/templates/skills/business-analyse/html/ba-interactive.html +80 -6
  10. package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +38 -6
  11. package/templates/skills/business-analyse/html/src/styles/06-wireframes.css +42 -0
  12. package/templates/skills/business-analyse/references/acceptance-criteria.md +169 -0
  13. package/templates/skills/business-analyse/references/deploy-data-build.md +5 -3
  14. package/templates/skills/business-analyse/references/handoff-file-templates.md +2 -1
  15. package/templates/skills/business-analyse/references/naming-conventions.md +245 -0
  16. package/templates/skills/business-analyse/references/validate-incremental-html.md +26 -4
  17. package/templates/skills/business-analyse/references/validation-checklist.md +31 -11
  18. package/templates/skills/business-analyse/references/wireframe-svg-style-guide.md +335 -0
  19. package/templates/skills/business-analyse/steps/step-03b-ui.md +59 -0
  20. package/templates/skills/business-analyse/steps/step-03c-compile.md +114 -0
  21. package/templates/skills/business-analyse/steps/step-03d-validate.md +144 -22
  22. package/templates/skills/business-analyse/steps/step-05a-handoff.md +114 -2
  23. package/templates/skills/business-analyse/steps/step-05b-deploy.md +28 -0
  24. package/templates/skills/ralph-loop/references/category-rules.md +5 -2
  25. package/templates/skills/ralph-loop/references/compact-loop.md +52 -1
  26. package/templates/skills/ralph-loop/references/core-seed-data.md +232 -21
  27. package/templates/skills/ralph-loop/steps/step-01-task.md +36 -4
  28. package/templates/skills/ralph-loop/steps/step-02-execute.md +81 -0
@@ -57047,13 +57047,40 @@ async function scaffoldRoutes(input, config2) {
57047
57047
  result.instructions.push("");
57048
57048
  result.instructions.push("## App.tsx Wiring Instructions");
57049
57049
  result.instructions.push("");
57050
- result.instructions.push("Import page components and add routes INSIDE the appropriate Layout wrapper in App.tsx.");
57051
- result.instructions.push("Routes must be added in BOTH the standard block and the tenant-prefixed block (/t/:slug/...).");
57050
+ result.instructions.push("**Detect App.tsx pattern first**, then follow the matching instructions:");
57052
57051
  result.instructions.push("");
57053
57052
  const routeTree = buildRouteTree(navRoutes);
57053
+ result.instructions.push("### Pattern A: mergeRoutes (if App.tsx uses `contextRoutes: ContextRouteExtensions`)");
57054
+ result.instructions.push("");
57055
+ result.instructions.push("Add routes to `contextRoutes.{context}[]` with **RELATIVE** paths (no leading `/`):");
57056
+ result.instructions.push("");
57057
+ result.instructions.push("```tsx");
57058
+ result.instructions.push("const contextRoutes: ContextRouteExtensions = {");
57059
+ for (const [context, applications] of Object.entries(routeTree)) {
57060
+ result.instructions.push(` ${context}: [`);
57061
+ for (const [, modules] of Object.entries(applications)) {
57062
+ for (const route of modules) {
57063
+ const modulePath = route.navRoute.split(".").slice(1).join("/");
57064
+ const pageEntry = pageFiles.get(route.navRoute);
57065
+ const component = pageEntry?.[0]?.componentName || `${route.navRoute.split(".").map(capitalize).join("")}Page`;
57066
+ result.instructions.push(` { path: '${modulePath}', element: <${component} /> },`);
57067
+ }
57068
+ }
57069
+ result.instructions.push(" ],");
57070
+ }
57071
+ result.instructions.push("};");
57072
+ result.instructions.push("```");
57073
+ result.instructions.push("");
57074
+ result.instructions.push("Routes are automatically injected into BOTH standard and tenant-prefixed trees by `mergeRoutes()`.");
57075
+ result.instructions.push("**DO NOT** add business/platform/personal routes to `clientRoutes[]` \u2014 that array is only for routes outside SmartStack contexts.");
57076
+ result.instructions.push("");
57077
+ result.instructions.push('### Pattern B: JSX Routes (if App.tsx uses `<Route path="/{context}" element={<{Layout} />}>`)');
57078
+ result.instructions.push("");
57079
+ result.instructions.push("Insert `<Route>` children INSIDE the appropriate Layout wrapper:");
57080
+ result.instructions.push("");
57054
57081
  for (const [context, applications] of Object.entries(routeTree)) {
57055
57082
  const layoutName = getLayoutName(context);
57056
- result.instructions.push(`### ${capitalize(context)} context (inside <Route path="/${context}" element={<${layoutName} />}>):`);
57083
+ result.instructions.push(`#### ${capitalize(context)} context (inside \`<Route path="/${context}" element={<${layoutName} />}>\`):`);
57057
57084
  result.instructions.push("");
57058
57085
  result.instructions.push("```tsx");
57059
57086
  for (const [, modules] of Object.entries(applications)) {
@@ -57547,6 +57574,7 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
57547
57574
  " */",
57548
57575
  "",
57549
57576
  "import type { RouteObject } from 'react-router-dom';",
57577
+ "import type { ContextRouteExtensions } from '@atlashub/smartstack';",
57550
57578
  "import { Navigate } from 'react-router-dom';"
57551
57579
  ];
57552
57580
  if (includeGuards) {
@@ -57648,6 +57676,24 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
57648
57676
  }
57649
57677
  lines.push("};");
57650
57678
  lines.push("");
57679
+ lines.push("/**");
57680
+ lines.push(" * Context route extensions for mergeRoutes() pattern.");
57681
+ lines.push(" * Import and spread into your App.tsx contextRoutes:");
57682
+ lines.push(" *");
57683
+ lines.push(" * ```tsx");
57684
+ lines.push(" * import { contextRouteExtensions } from './routes/clientRoutes.generated';");
57685
+ lines.push(" * const contextRoutes: ContextRouteExtensions = {");
57686
+ lines.push(" * ...contextRouteExtensions,");
57687
+ lines.push(" * // your additional routes...");
57688
+ lines.push(" * };");
57689
+ lines.push(" * ```");
57690
+ lines.push(" */");
57691
+ lines.push("export const contextRouteExtensions: ContextRouteExtensions = {");
57692
+ for (const context of contexts) {
57693
+ lines.push(` ${context}: ${context}Routes,`);
57694
+ }
57695
+ lines.push("};");
57696
+ lines.push("");
57651
57697
  return lines.join("\n");
57652
57698
  }
57653
57699
  function getLayoutName(context) {
@@ -58028,6 +58074,25 @@ async function validateAppWiring(webPath, backendRoutes, result) {
58028
58074
  result.appWiring.issues.push("App.tsx does not import any route configuration");
58029
58075
  return;
58030
58076
  }
58077
+ const caseMismatches = [];
58078
+ for (const route of backendRoutes) {
58079
+ const modulePath = route.webPath.replace(/^\//, "");
58080
+ if (modulePath !== modulePath.toLowerCase()) {
58081
+ const kebabPath = modulePath.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
58082
+ caseMismatches.push(
58083
+ `Route "${route.navRoute}" uses PascalCase in URL. Found: ${modulePath} \u2192 Expected: ${kebabPath}`
58084
+ );
58085
+ }
58086
+ }
58087
+ if (caseMismatches.length > 0) {
58088
+ result.appWiring.issues.push(
58089
+ `Case mismatch detected (${caseMismatches.length} routes with uppercase):`
58090
+ );
58091
+ result.appWiring.issues.push(...caseMismatches);
58092
+ result.appWiring.issues.push(
58093
+ "Fix: Use ToKebabCase() in NavigationSeedData route generation (see core-seed-data.md)"
58094
+ );
58095
+ }
58031
58096
  for (const route of backendRoutes) {
58032
58097
  const modulePath = route.navRoute.split(".").slice(1).join("/");
58033
58098
  const lastSegment = route.navRoute.split(".").pop() || "";