@atlashub/smartstack-cli 2.7.0 → 2.7.2

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.
@@ -208,6 +208,115 @@ Store results in consolidation.semanticChecks[]:
208
208
  - ≥1 ERROR → BLOCK (fix before handoff, ask user for each)
209
209
  - WARNING only → PASS with user notification
210
210
 
211
+ ### 4-bis. Structural Schema Conformity Check (MANDATORY)
212
+
213
+ > **Post-generation validation.** After semantic checks, verify that ALL module feature.json files conform to the JSON schema structure. This catches field name mismatches, missing sections, and wrong nesting.
214
+
215
+ For EACH module feature.json, run these structural checks:
216
+
217
+ **A. Required Sections Presence**
218
+
219
+ | Section | Required | Check |
220
+ |---------|----------|-------|
221
+ | `metadata` | YES | Must have: app, module, language, featureDescription, featureType |
222
+ | `discovery` | YES | Must exist (even if minimal) |
223
+ | `analysis.entities[]` | YES | Must have ≥1 entity |
224
+ | `analysis.businessRules[]` | YES | Must have ≥1 BR |
225
+ | `analysis.objectives[]` | YES | Must have ≥1 objective |
226
+ | `analysis.processFlow` | YES | Must have entryPoints, mainFlow, decisionPoints |
227
+ | `analysis.dataLifecycle` | YES | Must have retention, archival, deletion, gdprRelevant |
228
+ | `specification.useCases[]` | YES | Must have ≥1 UC |
229
+ | `specification.functionalRequirements[]` | YES | Must have ≥1 FR |
230
+ | `specification.permissionMatrix` | YES | Must be `{permissions[], roleAssignments[]}` (NOT flat array) |
231
+ | `specification.sections[]` | YES | Must have ≥1 section with resources |
232
+ | `specification.uiWireframes[]` | YES | Must have ≥1 wireframe with `layout` object |
233
+ | `specification.lifeCycles[]` | IF entities have status | States must be objects (NOT strings) |
234
+ | `specification.seedDataCore` | YES | Must have 5 arrays: navigationModules, navigationTranslations, permissions, rolePermissions, permissionConstants |
235
+ | `specification.gherkinScenarios` | YES | Must be `{feature, scenarios[]}` (NOT flat array) |
236
+ | `specification.navigation` | YES | Must have entries[] |
237
+ | `specification.i18nKeys[]` | YES | Must have ≥1 key with fr, en, nl, de |
238
+ | `validation` | YES | Must have completenessChecks, consistencyChecks, semanticChecks, decision |
239
+ | `handoff` | Written by step-05 | Checked post-handoff |
240
+
241
+ **B. Field Name Conformity**
242
+
243
+ For each section, verify NO FORBIDDEN field names are used:
244
+
245
+ | Section | FORBIDDEN fields | Correct fields |
246
+ |---------|-----------------|----------------|
247
+ | `entities[].attributes[]` | `type`, `values`, `rules` | `description`, `unique`, `validation` |
248
+ | `businessRules[]` | `rule`, `condition` (singular), `action` | `name`, `statement`, `conditions[]` |
249
+ | `useCases[]` | `actor`, `linkedBRs`, `linkedFRs` | `primaryActor`, `linkedRules` |
250
+ | `functionalRequirements[]` | `name`, `description`, `linkedUCs`, `linkedBRs` | `statement`, `linkedUseCases`, `linkedRules` |
251
+ | `permissionMatrix` | flat array with `resource`/`roles` | `{permissions[], roleAssignments[]}` |
252
+ | `lifeCycles[].states[]` | string values like `"Active"` | objects with `{id, displayName, color, isTerminal}` |
253
+ | `seedDataCore` | flat object, string values | 5 typed arrays |
254
+ | `gherkinScenarios` | flat scenario array | `{feature, scenarios[]}` nested |
255
+
256
+ **C. ID Pattern Conformity**
257
+
258
+ | ID Type | Pattern | Example |
259
+ |---------|---------|---------|
260
+ | BR | `BR-(VAL\|CALC\|WF\|SEC\|DATA)-{PREFIX}-\d{3}` | BR-VAL-RM-001 |
261
+ | UC | `UC-{PREFIX}-\d{3}` | UC-RM-001 |
262
+ | FR | `FR-{PREFIX}-\d{3}` | FR-RM-001 |
263
+ | Permissions | `business.{app}.{module}.{resource}.{action}` | business.freebike.repairs.create |
264
+
265
+ Verify all IDs use the correct module prefix (2-4 uppercase letters).
266
+
267
+ **D. Cross-Module ID Uniqueness**
268
+
269
+ Verify no ID collision across modules:
270
+ ```
271
+ SET all_ids = {}
272
+ FOR each module:
273
+ FOR each BR, UC, FR id:
274
+ IF id IN all_ids → ERROR: "Duplicate {id} in {module1} and {module2}"
275
+ ADD id to all_ids
276
+ ```
277
+
278
+ **E. Wireframe Layout Completeness**
279
+
280
+ For each `uiWireframes[]`:
281
+ ```
282
+ IF missing componentMapping[] → ERROR
283
+ IF missing layout object → ERROR
284
+ IF missing layout.regions[] → ERROR
285
+ FOR each region in layout.regions[]:
286
+ IF missing position → ERROR
287
+ IF missing components[] → ERROR
288
+ ```
289
+
290
+ **F. SeedDataCore Translation Coverage**
291
+
292
+ ```
293
+ FOR each navigationModules[].code:
294
+ FOR each language in [fr, en, nl, de]:
295
+ IF NOT EXISTS navigationTranslations[] with moduleCode AND language → ERROR
296
+ ```
297
+
298
+ **Result aggregation:**
299
+ ```json
300
+ {
301
+ "structuralChecks": [
302
+ { "check": "required-sections", "module": "...", "status": "PASS|ERROR", "details": "Missing: analysis.objectives" },
303
+ { "check": "field-names", "module": "...", "status": "PASS|ERROR", "details": "businessRules[0] uses 'rule' instead of 'name'+'statement'" },
304
+ { "check": "id-patterns", "module": "...", "status": "PASS|ERROR", "details": "BR-001 missing category segment" },
305
+ { "check": "id-uniqueness", "module": "...", "status": "PASS|ERROR", "details": "UC-RM-003 duplicated in Vehicles and Repairs" },
306
+ { "check": "wireframe-layout", "module": "...", "status": "PASS|ERROR", "details": "Wireframe repairs-list missing layout object" },
307
+ { "check": "seeddata-translations", "module": "...", "status": "PASS|ERROR", "details": "Missing nl translation for NavigationModuleRepairs" }
308
+ ]
309
+ }
310
+ ```
311
+
312
+ **Blocking rule:**
313
+ - 0 ERROR → PASS (merge structuralChecks into consolidation.semanticChecks[])
314
+ - ≥1 ERROR → BLOCK. For each ERROR:
315
+ 1. Attempt AUTO-FIX (rename fields, restructure)
316
+ 2. Re-write the module feature.json with fixes
317
+ 3. Re-check
318
+ 4. If still ERROR → ask user
319
+
211
320
  ### 5. End-to-End Flows
212
321
 
213
322
  Identify business processes that span multiple modules:
@@ -308,21 +417,77 @@ IF "Modifier les interactions":
308
417
 
309
418
  ### 9. Write Consolidation
310
419
 
420
+ > **STRUCTURE CARD: consolidation** — Must match `application-schema.json`. Follow this structure exactly.
421
+
311
422
  ```
312
423
  ba-writer.enrichSection({
313
424
  featureId: {feature_id},
314
425
  section: "consolidation",
315
426
  data: {
316
- crossModuleInteractions: { fkReferences, sharedEntities, events, sharedReferenceData },
317
- permissionCoherence: { roleConsistency, pathFormat, hierarchy, conflicts, resolved },
318
- e2eFlows: [...],
319
- globalRiskAssessment: {...}
427
+ crossModuleInteractions: [
428
+ {
429
+ "fromModule": "Orders",
430
+ "toModule": "Customers",
431
+ "interactionType": "FK-reference|event-publish|event-subscribe|shared-lookup|cascade-delete|cascade-update",
432
+ "description": "Order references customer via FK",
433
+ "entities": ["Order→Customer"]
434
+ }
435
+ ],
436
+ sharedEntities: [
437
+ {
438
+ "entity": "Customer",
439
+ "ownerModule": "Customers",
440
+ "referencedBy": ["Orders", "Invoices"],
441
+ "sharedFields": ["code", "name"]
442
+ }
443
+ ],
444
+ permissionCoherence: {
445
+ "rolesConsistent": true,
446
+ "pathFormatConsistent": true,
447
+ "hierarchyRespected": true,
448
+ "conflicts": [],
449
+ "warnings": []
450
+ },
451
+ e2eFlows: [
452
+ {
453
+ "name": "Order to Invoice",
454
+ "modules": ["Customers", "Orders", "Invoices"],
455
+ "steps": [
456
+ { "module": "Orders", "action": "Create order", "permission": "business.sales.orders.create", "dataFlow": "Customer → Order" }
457
+ ]
458
+ }
459
+ ],
460
+ globalRiskAssessment: [
461
+ {
462
+ "risk": "Cross-module coupling complexity",
463
+ "category": "coupling|complexity|dependency-chain|security|scope",
464
+ "severity": "critical|high|medium|low",
465
+ "mitigation": "Event-driven communication instead of direct FK"
466
+ }
467
+ ],
468
+ semanticChecks: [
469
+ { "check": "permission-orpheline", "status": "PASS|WARNING|ERROR", "details": "..." },
470
+ { "check": "uc-sans-fr", "status": "PASS|WARNING|ERROR", "details": "..." },
471
+ { "check": "wireframe-coverage", "status": "PASS|WARNING|ERROR", "details": "..." }
472
+ ],
473
+ decision: {
474
+ "approved": true,
475
+ "reason": "All cross-module validations passed",
476
+ "approvedBy": "Client",
477
+ "approvedAt": "{ISO timestamp}"
478
+ }
320
479
  }
321
480
  })
322
481
 
323
482
  ba-writer.updateStatus({feature_id}, "consolidated")
324
483
  ```
325
484
 
485
+ > **STRUCTURE DIFFERENCES FROM OLD FORMAT:**
486
+ > - `crossModuleInteractions` is a FLAT ARRAY (not `{fkReferences, sharedEntities, events}` nested object)
487
+ > - `sharedEntities` is TOP-LEVEL (not nested inside crossModuleInteractions)
488
+ > - `decision` is an OBJECT with `approved`, `reason`, `approvedBy`, `approvedAt` (not `clientApproval` string)
489
+ > - `globalRiskAssessment` is an ARRAY of risk objects (not `{totalEntities: {value, threshold}}`)
490
+
326
491
  Add changelog entry:
327
492
  ```json
328
493
  {
@@ -759,6 +759,30 @@ COLORS:
759
759
 
760
760
  #### 9a. Module Handoff Loop (MANDATORY)
761
761
 
762
+ > **STRUCTURE CARD: handoff** — Field names are EXACT. Include ALL fields below.
763
+ > ```json
764
+ > {
765
+ > "complexity": "simple|medium|complex",
766
+ > "filesToCreate": {
767
+ > "domain": [{"path": "...", "type": "Entity|ValueObject|Enum", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
768
+ > "application": [{"path": "...", "type": "Service|Dto|Validator", "linkedFRs": [], "linkedUCs": [], "module": "..."}],
769
+ > "infrastructure": [{"path": "...", "type": "Repository|DbContext", "linkedFRs": [], "module": "..."}],
770
+ > "api": [{"path": "...", "type": "ApiController", "linkedUCs": [], "linkedFRs": [], "module": "..."}],
771
+ > "frontend": [{"path": "...", "type": "Page|Component|Hook|DashboardPage", "linkedUCs": [], "linkedWireframes": [], "module": "..."}],
772
+ > "seedData": [{"path": "...", "type": "HasData", "category": "core|business", "source": "...", "module": "..."}],
773
+ > "tests": [{"path": "...", "type": "UnitTests|IntegrationTests|SecurityTests", "linkedFRs": [], "linkedUCs": [], "module": "..."}]
774
+ > },
775
+ > "brToCodeMapping": [{"ruleId": "BR-...", "files": ["path1", "path2"], "implementation": "description"}],
776
+ > "apiEndpointSummary": [{"method": "GET|POST|PUT|DELETE", "path": "/api/...", "permission": "business.{app}.{module}.{action}", "linkedUC": "UC-..."}],
777
+ > "prdFile": ".ralph/prd-{module}.json",
778
+ > "totalFiles": 0,
779
+ > "totalTasks": 0,
780
+ > "handedOffAt": "{ISO timestamp}"
781
+ > }
782
+ > ```
783
+ > **MANDATORY fields:** ALL of the above. `filesToCreate` MUST have all 7 categories (even if empty arrays).
784
+ > **FORBIDDEN:** `handoff: {}` (empty object is a CRITICAL BUG). Missing `brToCodeMapping` or `apiEndpointSummary`.
785
+
762
786
  **For i = 0; i < modules.length; i++:**
763
787
 
764
788
  ```