@atlashub/smartstack-cli 3.20.0 → 3.21.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 (26) hide show
  1. package/dist/index.js +53 -1
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +1 -0
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/templates/project/api.ts.template +8 -29
  7. package/templates/project/appsettings.json.template +1 -0
  8. package/templates/skills/business-analyse/html/ba-interactive.html +562 -150
  9. package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +11 -6
  10. package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +209 -4
  11. package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +2 -8
  12. package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +57 -2
  13. package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +3 -1
  14. package/templates/skills/business-analyse/html/src/scripts/08-editing.js +112 -22
  15. package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +7 -0
  16. package/templates/skills/business-analyse/html/src/styles/02-layout.css +1 -1
  17. package/templates/skills/business-analyse/html/src/styles/03-navigation.css +89 -31
  18. package/templates/skills/business-analyse/html/src/styles/05-modules.css +64 -0
  19. package/templates/skills/business-analyse/html/src/template.html +8 -76
  20. package/templates/skills/business-analyse/references/deploy-data-build.md +9 -7
  21. package/templates/skills/business-analyse/references/html-data-mapping.md +20 -28
  22. package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -1
  23. package/templates/skills/business-analyse/steps/step-03c-compile.md +55 -2
  24. package/templates/skills/business-analyse/steps/step-03d-validate.md +82 -15
  25. package/templates/skills/business-analyse/steps/step-05a-handoff.md +77 -3
  26. package/templates/skills/business-analyse/steps/step-05b-deploy.md +27 -0
@@ -194,7 +194,7 @@ See [references/handoff-file-templates.md](../references/handoff-file-templates.
194
194
  |----------|--------|-----------|
195
195
  | **4.1 Domain** | `analysis.entities[]` | Entities, ValueObjects, Enums, Exceptions |
196
196
  | **4.2 Application** | `analysis.useCases[]` | Services, DTOs, Validators |
197
- | **4.3 Infrastructure** | `analysis.entities[]` | EF Configurations, DbSet, DI |
197
+ | **4.3 Infrastructure** | `analysis.entities[]` | EF Configurations, DbSet, DI. **DEPENDENCY:** Each EF config task MUST `dependsOn` its corresponding domain entity task. |
198
198
  | **4.4 API** | `specification.apiEndpoints[]` | Controllers with `{ContextShort}` mapping |
199
199
  | **4.5 Frontend** | `specification.uiWireframes[]` | Pages, Components, Hooks + wireframe traceability |
200
200
  | **4.6 SeedData** | `specification.seedDataCore` | 5 CORE + business + IClientSeedDataProvider |
@@ -204,6 +204,7 @@ See [references/handoff-file-templates.md](../references/handoff-file-templates.
204
204
  - All backend paths include `{ContextPascal}/{ApplicationName}/` hierarchy
205
205
  - Frontend pages MUST have `linkedWireframes[]` + `wireframeAcceptanceCriteria`
206
206
  - SeedData: 5 CORE entries ALWAYS + IClientSeedDataProvider for client projects
207
+ - **Acceptance Criteria Mapping:** Each task's `acceptanceCriteria` MUST be derived from its own `linkedFRs[]` entries (lookup FR → `acceptanceCriteria`). NEVER map by sequential FR index — use the task's explicit linkedFRs to resolve the correct criteria.
207
208
  - Path convention: `Persistence/Seeding/Data/` (NEVER `Data/SeedData/`)
208
209
 
209
210
  ---
@@ -228,6 +229,52 @@ For each endpoint: operation, method, route, linkedUC, linkedFR, permissions, re
228
229
 
229
230
  Total endpoints = count of specification.apiEndpoints[] across all modules.
230
231
 
232
+ ### 6b. Frontend Task Splitting (MANDATORY)
233
+
234
+ > **CRITICAL:** Frontend MUST be split into discrete tasks, NOT bundled as a single mega-task.
235
+ > A single mega-task covering 5-8 files prevents granular error recovery in ralph-loop.
236
+
237
+ For each module, generate these SEPARATE frontend file entries (not one monolithic entry):
238
+
239
+ ```json
240
+ "frontend": [
241
+ { "path": "src/pages/{Mod}/{ListPage}Page.tsx", "type": "Page", "linkedWireframes": ["{module}-list"], "module": "{moduleCode}" },
242
+ { "path": "src/pages/{Mod}/{DetailPage}Page.tsx", "type": "Page", "linkedWireframes": ["{module}-detail"], "module": "{moduleCode}" },
243
+ { "path": "src/hooks/use{Module}.ts", "type": "Hook", "module": "{moduleCode}" },
244
+ { "path": "src/i18n/{module}.json", "type": "I18n", "module": "{moduleCode}" }
245
+ ]
246
+ ```
247
+
248
+ Additional per-section pages (dashboard, import, etc.) are separate entries.
249
+
250
+ **Route wiring task (MANDATORY — separate entry):**
251
+ ```json
252
+ { "path": "src/App.tsx", "type": "RouteWiring", "module": "{moduleCode}", "description": "Wire {module} routes into App.tsx Layout wrappers (standard + tenant-prefixed blocks). BLOCKING: pages without route wiring = blank pages." }
253
+ ```
254
+
255
+ ### 6c. Cross-Module PRD (MANDATORY for multi-module features)
256
+
257
+ > **CRITICAL:** Cross-module integration tasks MUST exist in a dedicated PRD file.
258
+ > Without this, ralph-loop will NOT execute E2E tests or FK validation.
259
+
260
+ Generate `.ralph/prd-CrossModule.json` with:
261
+ ```json
262
+ {
263
+ "$version": "3.0.0",
264
+ "implementation": {
265
+ "filesToCreate": {
266
+ "tests": [
267
+ { "path": "src/Tests/Integration/CrossModule/ForeignKeyValidationTests.cs", "type": "IntegrationTests", "module": "CrossModule" },
268
+ { "path": "src/Tests/Integration/CrossModule/PermissionMatrixTests.cs", "type": "SecurityTests", "module": "CrossModule" },
269
+ { "path": "src/Tests/Integration/CrossModule/E2EFlowTests.cs", "type": "E2ETests", "module": "CrossModule" }
270
+ ]
271
+ }
272
+ }
273
+ }
274
+ ```
275
+
276
+ Add to progress.txt after all module tasks.
277
+
231
278
  ---
232
279
 
233
280
  ### 7. Write Handoff to Feature.json
@@ -317,7 +364,7 @@ const seedDataCore = {
317
364
  code: m.code,
318
365
  label: m.name || m.code,
319
366
  description: m.description,
320
- icon: null, // set by ralph-loop
367
+ icon: inferIconFromModule(m) || "folder", // MUST be non-null — use sensible default
321
368
  iconType: "lucide",
322
369
  route: `/business/${master.metadata.application.toLowerCase()}/${m.code.toLowerCase()}`,
323
370
  displayOrder: (i + 1) * 10
@@ -386,6 +433,28 @@ const seedDataCore = {
386
433
  )
387
434
  };
388
435
 
436
+ // Icon inference from module context (NEVER leave as null)
437
+ function inferIconFromModule(module) {
438
+ const codeLC = module.code.toLowerCase();
439
+ const iconMap = {
440
+ 'employee': 'users', 'staff': 'users', 'personnel': 'users', 'user': 'users',
441
+ 'project': 'folder-kanban', 'task': 'check-square', 'work': 'briefcase',
442
+ 'time': 'clock', 'schedule': 'calendar', 'planning': 'calendar-days',
443
+ 'absence': 'calendar-off', 'leave': 'calendar-off', 'vacation': 'palm-tree',
444
+ 'finance': 'wallet', 'billing': 'receipt', 'invoice': 'file-text',
445
+ 'inventory': 'warehouse', 'stock': 'package', 'product': 'shopping-bag',
446
+ 'customer': 'building', 'client': 'building-2', 'contact': 'contact',
447
+ 'report': 'bar-chart', 'dashboard': 'layout-dashboard', 'analytics': 'trending-up',
448
+ 'document': 'file-text', 'notification': 'bell', 'setting': 'settings',
449
+ 'order': 'shopping-cart', 'vehicle': 'car', 'maintenance': 'wrench',
450
+ 'audit': 'shield-check', 'workflow': 'git-branch', 'approval': 'check-circle'
451
+ };
452
+ for (const [keyword, icon] of Object.entries(iconMap)) {
453
+ if (codeLC.includes(keyword)) return icon;
454
+ }
455
+ return "folder"; // fallback — NEVER null
456
+ }
457
+
389
458
  ba-writer.enrichSection({
390
459
  featureId: {feature_id},
391
460
  section: "seedDataCore",
@@ -393,12 +462,17 @@ ba-writer.enrichSection({
393
462
  })
394
463
  ```
395
464
 
396
- **POST-CHECK (non-blocking):**
465
+ **POST-CHECK (BLOCKING for icons, warning for counts):**
397
466
  ```
398
467
  IF seedDataCore.navigationModules.length !== master.modules.length:
399
468
  WARNING: seedDataCore has ${seedDataCore.navigationModules.length} nav modules but ${master.modules.length} modules exist
400
469
  IF seedDataCore.permissions.length === 0:
401
470
  WARNING: seedDataCore has 0 permissions — applicationRoles may be missing
471
+ IF seedDataCore.navigationModules.some(m => !m.icon || m.icon === null):
472
+ BLOCKING ERROR: "Navigation modules with null icons detected — ralph-loop will render empty navigation"
473
+ → Fix: Re-run inferIconFromModule() for modules with null icons
474
+ IF seedDataCore.navigationSections.length === 0:
475
+ WARNING: "0 navigation sections — every module should have at least 1 section (e.g., 'list')"
402
476
  ```
403
477
 
404
478
  #### 7c. Master Handoff (after ALL modules written + seedDataCore generated)
@@ -357,6 +357,33 @@ After writing the HTML file, verify:
357
357
  BLOCKING_ERROR("Module mismatch: expected [${expectedModules}] but wireframes has [${wireframeModules}]")
358
358
  ```
359
359
 
360
+ 9. **MODULE DATA COMPLETENESS** — every module in FEATURE_DATA.modules[] must carry ALL fields from feature.json
361
+ ```
362
+ FOR each htmlModule in FEATURE_DATA.modules[]:
363
+ masterModule = master.modules.find(m => m.code === htmlModule.code)
364
+
365
+ // name MUST be display name, NOT code
366
+ IF htmlModule.name === htmlModule.code AND masterModule.name !== masterModule.code:
367
+ BLOCKING_ERROR("Module '${htmlModule.code}' has name === code. Expected: '${masterModule.name}'")
368
+
369
+ // anticipatedSections MUST be present (drives Structure tab + navigation tree)
370
+ IF masterModule.anticipatedSections?.length > 0 AND (!htmlModule.anticipatedSections OR htmlModule.anticipatedSections.length === 0):
371
+ BLOCKING_ERROR("Module '${htmlModule.code}' lost anticipatedSections: master has ${masterModule.anticipatedSections.length}, HTML has 0")
372
+ → FIX: Copy anticipatedSections from master.modules[].anticipatedSections
373
+
374
+ // dependencies/dependents MUST be present (drives dependency graph)
375
+ IF masterModule.dependencies?.length > 0 AND (!htmlModule.dependencies OR htmlModule.dependencies.length === 0):
376
+ BLOCKING_ERROR("Module '${htmlModule.code}' lost dependencies array")
377
+ ```
378
+
379
+ Display verification table:
380
+ ```
381
+ POST-CHECK: Module data completeness
382
+ | Module | name | sections | deps | wireframes | specs | Match |
383
+ |----------------|---------|----------|------|------------|-------|-------|
384
+ | {code} | {name} | {n} | {n} | {n} | OK | OK/FAIL |
385
+ ```
386
+
360
387
  **IF ANY CHECK FAILS → DO NOT PROCEED. Fix the data mapping and regenerate.**
361
388
 
362
389
  ---