@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.
- package/dist/index.js +53 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +1 -0
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/project/api.ts.template +8 -29
- package/templates/project/appsettings.json.template +1 -0
- package/templates/skills/business-analyse/html/ba-interactive.html +562 -150
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +11 -6
- package/templates/skills/business-analyse/html/src/scripts/02-navigation.js +209 -4
- package/templates/skills/business-analyse/html/src/scripts/04-render-modules.js +2 -8
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +57 -2
- package/templates/skills/business-analyse/html/src/scripts/07-render-handoff.js +3 -1
- package/templates/skills/business-analyse/html/src/scripts/08-editing.js +112 -22
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +7 -0
- package/templates/skills/business-analyse/html/src/styles/02-layout.css +1 -1
- package/templates/skills/business-analyse/html/src/styles/03-navigation.css +89 -31
- package/templates/skills/business-analyse/html/src/styles/05-modules.css +64 -0
- package/templates/skills/business-analyse/html/src/template.html +8 -76
- package/templates/skills/business-analyse/references/deploy-data-build.md +9 -7
- package/templates/skills/business-analyse/references/html-data-mapping.md +20 -28
- package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -1
- package/templates/skills/business-analyse/steps/step-03c-compile.md +55 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +82 -15
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +77 -3
- 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:
|
|
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 (
|
|
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
|
---
|