@atlashub/smartstack-cli 4.44.0 → 4.45.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlashub/smartstack-cli",
3
- "version": "4.44.0",
3
+ "version": "4.45.0",
4
4
  "description": "SmartStack Claude Code automation toolkit - GitFlow, EF Core migrations, prompts and more",
5
5
  "author": {
6
6
  "name": "SmartStack",
@@ -471,11 +471,11 @@ Perform these structural checks before every write:
471
471
  - relationships[]: REQUIRED `target`, `type`, `description`
472
472
  - FORBIDDEN: `values` (use `validation`), `rules` (use `validation`)
473
473
 
474
- **analysis.businessRules** in rules.json — REQUIRED: `id`, `name`, `category`, `statement`, `priority`
474
+ **analysis.rules** in rules.json — Root key: `rules[]` — REQUIRED: `id`, `name`, `category`, `statement`, `priority`
475
475
  - OPTIONAL: `conditions[]`, `examples[]`, `testability`
476
476
  - category values: `validation`, `calculation`, `workflow`, `security`, `data` (lowercase only)
477
- - FORBIDDEN: `rule` (use `name`+`statement`), `condition` singular (use `conditions[]`)
478
- - AUTO-MAP: `rule` → split into `name` (short) + `statement` (IF/THEN)
477
+ - FORBIDDEN: `rule` (use `name`+`statement`), `condition` singular (use `conditions[]`), `businessRules` as root key (use `rules`)
478
+ - AUTO-MAP: `rule` → split into `name` (short) + `statement` (IF/THEN), `businessRules` → rename to `rules`
479
479
 
480
480
  **specification.useCases** in usecases.json — REQUIRED: `id`, `name`, `primaryActor`, `permission`, `preconditions[]`, `postconditions[]`, `mainScenario[]`
481
481
  - OPTIONAL: `alternativeScenarios[]`, `errorScenarios[]`, `linkedRules[]`
@@ -489,14 +489,18 @@ Perform these structural checks before every write:
489
489
  - FORBIDDEN: `name` (use `statement`), `linkedUCs` (use `linkedUseCases`), `linkedBRs` (use `linkedRules`)
490
490
  - AUTO-MAP: `name` → `statement`, `linkedUCs` → `linkedUseCases`, `linkedBRs` → `linkedRules`
491
491
 
492
- **specification.permissionMatrix** in permissions.json — REQUIRED shape: `{permissions[], roleAssignments[]}`
493
- - permissions[]: `{path, action, description}`
494
- - roleAssignments[]: `{role, permissions[]}`
495
- - FORBIDDEN: flat array format, top-level `roles` key
492
+ **specification.permissionMatrix** in permissions.json — Root keys: `permissionPaths[]`, `roles[]`, `matrix[]`
493
+ - permissionPaths[]: array of permission path strings (e.g., `"crm.contacts.read"`)
494
+ - roles[]: array of role definitions `{role, level}`
495
+ - matrix[]: array of `{role, permissions[]}` assignments
496
+ - FORBIDDEN: flat array format, `permissionSet` as wrapper, `actions` as root key
497
+ - AUTO-MAP: `permissionSet.permissions[]` → extract `.code`/`.path` into `permissionPaths[]`, `permissions[{code}]` → extract into `permissionPaths[]`
496
498
 
497
- **specification.uiWireframes** in screens.json — REQUIRED: `screen`, `section`, `mockup`, `componentMapping[]`, `layout`
499
+ **specification.uiWireframes** in screens.json — Root key: `screens[]` — each screen REQUIRED: `screen`, `section`, `mockup`, `componentMapping[]`, `layout`
498
500
  - componentMapping[]: `{wireframeElement, reactComponent}`
499
501
  - layout: `{type, regions[]}` where regions[]: `{id, position, span?, components[]}`
502
+ - FORBIDDEN: `sections[].resources[]` as root structure (use `screens[]`)
503
+ - AUTO-MAP: `sections[].resources[]` → flatten into `screens[]`
500
504
 
501
505
  **handoff** in handoff.json — REQUIRED: `complexity`, `filesToCreate`, `brToCodeMapping[]`, `apiEndpointSummary[]`, `prdFile`, `totalFiles`, `totalTasks`, `handedOffAt`
502
506
  - filesToCreate: REQUIRED 8 categories: `domain[]`, `application[]`, `infrastructure[]`, `api[]`, `frontend[]`, `seedData[]`, `tests[]`, `documentation[]`
@@ -598,21 +602,21 @@ Versions are stored as separate directories. Each directory contains index.json
598
602
  Before EVERY enrichSection() call for specification or handoff sections, validate referential integrity.
599
603
 
600
604
  ### After enrichSection("specification" or "usecases")
601
- 1. Build SET_BR from rules.json businessRules[].id
605
+ 1. Build SET_BR from rules.json rules[].id
602
606
  2. For each useCases[].linkedRules[] → verify ∈ SET_BR
603
607
  3. For each functionalRequirements[].linkedRules[] → verify ∈ SET_BR
604
608
  4. Build SET_UC from usecases[].useCases[].id
605
609
  5. For each functionalRequirements[].linkedUseCases[] → verify ∈ SET_UC
606
- 6. Build SET_PERM from permissions.json permissionMatrix.permissions[].path
607
- 7. For each roleAssignments[].permissions[] → verify ∈ SET_PERM
608
- 8. Build SET_SCREEN from screens.json uiWireframes[].screen
610
+ 6. Build SET_PERM from permissions.json permissionPaths[]
611
+ 7. For each matrix[].permissions[] → verify ∈ SET_PERM
612
+ 8. Build SET_SCREEN from screens.json screens[].screen
609
613
  9. For each sections[].wireframe → verify ∈ SET_SCREEN
610
614
 
611
615
  ### After enrichSection("handoff")
612
616
  1. Build SET_FR from specification functionalRequirements[].id
613
617
  2. Build SET_UC from specification useCases[].id
614
- 3. Build SET_SCREEN from specification uiWireframes[].screen
615
- 4. Build SET_BR from analysis businessRules[].id
618
+ 3. Build SET_SCREEN from specification screens[].screen
619
+ 4. Build SET_BR from analysis rules[].id
616
620
  5. For each filesToCreate.*[].linkedFRs[] → verify ∈ SET_FR
617
621
  6. For each filesToCreate.*[].linkedUCs[] → verify ∈ SET_UC
618
622
  7. For each filesToCreate.*[].linkedWireframes[] → verify ∈ SET_SCREEN
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: step-00-init
3
3
  description: Initialize Business Analysis - Auto-detect new/update, create index.json structure
4
- model: sonnet
5
4
  next_step: steps/step-01-cadrage.md
6
5
  ---
7
6
 
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: business-analyse-handoff
3
3
  description: "Transform consolidated business analysis into handoff data (8 categories) and PRD files for /business-analyse-develop consumption."
4
- model: sonnet
5
4
  user_invocable: true
6
5
  ---
7
6
 
@@ -10,14 +10,14 @@
10
10
 
11
11
  `/business-analyse` generates **separate JSON files** per module:
12
12
 
13
- | File | Content | Root key |
14
- |------|---------|----------|
15
- | `index.json` | Metadata, file references, summary | `metadata`, `files`, `summary` |
16
- | `entities.json` | Entity definitions | `entities[]` |
17
- | `rules.json` | Business rules | `rules[]` |
18
- | `usecases.json` | Use cases | `useCases[]` |
19
- | `permissions.json` | Roles and permission matrix | `roles[]`, `permissionPaths[]`, `matrix[]` |
20
- | `screens.json` | UI screen specifications | `screens[]` |
13
+ | File | Content | Root key (canonical) | Accepted variants |
14
+ |------|---------|----------------------|-------------------|
15
+ | `index.json` | Metadata, file references, summary | `metadata`, `files`, `summary` | — |
16
+ | `entities.json` | Entity definitions | `entities[]` | — |
17
+ | `rules.json` | Business rules | `rules[]` | `businessRules[]` |
18
+ | `usecases.json` | Use cases | `useCases[]` | `usecases[]` (lowercase) |
19
+ | `permissions.json` | Roles and permission matrix | `permissionPaths[]` | `permissionSet.permissions[]`, `permissions[]`, `actions[]` |
20
+ | `screens.json` | UI screen specifications | `screens[]` | `sections[].resources[]` |
21
21
 
22
22
  The validation script **assembles** these files before checking.
23
23
 
@@ -33,7 +33,7 @@ These verify data that `/business-analyse` produces:
33
33
 
34
34
  | # | Criterion | Minimum | Source File | Blocking |
35
35
  |---|-----------|---------|-------------|----------|
36
- | AC-01 | Entities present | 2 | `entities.json > entities[]` | YES |
36
+ | AC-01 | Entities present | 1 (or referencedEntities) | `entities.json > entities[]` | YES |
37
37
  | AC-02 | Entity attributes have `type` field | ALL | `entities.json > entities[].attributes[].type` | YES |
38
38
  | AC-03 | Use cases present | 2 | `usecases.json > useCases[]` | YES |
39
39
  | AC-04 | Business rules present | 2 | `rules.json > rules[]` | YES |
@@ -85,19 +85,32 @@ const rulesData = loadFile('rules') || {};
85
85
  const permissionsData = loadFile('permissions') || {};
86
86
  const screensData = loadFile('screens') || {};
87
87
 
88
+ // NORMALISATION: tolerate ba-writer + LLM field name variants
88
89
  const entities = entitiesData.entities || [];
89
- const useCases = usecasesData.useCases || [];
90
- const rules = rulesData.rules || [];
91
- const permissions = permissionsData.permissionPaths || permissionsData.permissions || [];
90
+ const hasReferencedEntities = (entitiesData.referencedEntities || []).length > 0;
91
+ const useCases = usecasesData.useCases || usecasesData.usecases || [];
92
+ const rules = rulesData.rules || rulesData.businessRules || [];
93
+
94
+ // Permissions: canonical permissionPaths[] OR extract from nested structures
95
+ const permissions = permissionsData.permissionPaths
96
+ || (permissionsData.permissionSet && permissionsData.permissionSet.permissions || []).map(function(p) { return p.code || p.path || ''; })
97
+ || (permissionsData.permissions || []).map(function(p) { return typeof p === 'string' ? p : (p.code || p.path || ''); })
98
+ || (permissionsData.actions || []).map(function(a) { return a.code || ''; })
99
+ || [];
100
+
101
+ // Screens: canonical screens[] OR flatten sections[].resources[]
92
102
  const screens = screensData.screens || [];
103
+ const sectionsAsScreens = (screensData.sections || []).reduce(function(acc, s) { return acc.concat(s.resources || []); }, []);
104
+ const allScreens = screens.length > 0 ? screens : sectionsAsScreens;
105
+
93
106
  const status = index.metadata?.status || 'unknown';
94
107
 
95
108
  const fails = [];
96
109
 
97
- // AC-01: Entities >= 2
98
- if (entities.length < 2) {
99
- fails.push('AC-01: entities = ' + entities.length + ' (min: 2)');
100
- console.error('FAIL: AC-01: entities >= 2 = ' + entities.length + ' (min: 2)');
110
+ // AC-01: Entities >= 1 (exempt modules with referencedEntities - vue perso pattern)
111
+ if (entities.length < 1 && !hasReferencedEntities) {
112
+ fails.push('AC-01: entities = ' + entities.length + ' (min: 1)');
113
+ console.error('FAIL: AC-01: entities >= 1 = ' + entities.length + ' (min: 1, no referencedEntities)');
101
114
  }
102
115
 
103
116
  // AC-02: Entity attributes have type
@@ -122,9 +135,9 @@ if (rules.length < 2) {
122
135
  }
123
136
 
124
137
  // AC-05: Screens >= 1
125
- if (screens.length < 1) {
126
- fails.push('AC-05: screens = ' + screens.length + ' (min: 1)');
127
- console.error('FAIL: AC-05: screens >= 1 = ' + screens.length + ' (min: 1)');
138
+ if (allScreens.length < 1) {
139
+ fails.push('AC-05: screens = ' + allScreens.length + ' (min: 1)');
140
+ console.error('FAIL: AC-05: screens >= 1 = ' + allScreens.length + ' (min: 1)');
128
141
  }
129
142
 
130
143
  // AC-06: Permissions >= 1
@@ -145,7 +158,7 @@ if (fails.length > 0) {
145
158
  process.exit(1);
146
159
  }
147
160
  console.log('PASS: All input acceptance criteria met (AC-01 to AC-07)');
148
- console.log(' entities: ' + entities.length + ', useCases: ' + useCases.length + ', rules: ' + rules.length + ', screens: ' + screens.length + ', permissions: ' + permissions.length);
161
+ console.log(' entities: ' + entities.length + (hasReferencedEntities ? ' (+ referencedEntities)' : '') + ', useCases: ' + useCases.length + ', rules: ' + rules.length + ', screens: ' + allScreens.length + ', permissions: ' + permissions.length);
149
162
  " "$MODULE_DIR"
150
163
  ```
151
164
 
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: step-00-validate
3
3
  description: Detect input, validate BA readiness with flat-file support, AC gate
4
- model: sonnet
5
4
  next_step: steps/step-01-transform.md
6
5
  ---
7
6
 
@@ -78,13 +77,26 @@ For each module, load the separate JSON files referenced in `index.json > files`
78
77
  // Module index.json contains file references:
79
78
  // { "files": { "entities": { "path": "entities.json" }, "usecases": { "path": "usecases.json" }, ... } }
80
79
 
80
+ const entitiesData = READ(moduleDir + '/entities.json');
81
+ const usecasesData = READ(moduleDir + '/usecases.json');
82
+ const rulesData = READ(moduleDir + '/rules.json');
83
+ const permissionsData = READ(moduleDir + '/permissions.json');
84
+ const screensData = READ(moduleDir + '/screens.json');
85
+
86
+ // NORMALISATION: tolerate ba-writer + LLM field name variants
81
87
  const moduleData = {
82
88
  index: READ(moduleDir + '/index.json'),
83
- entities: READ(moduleDir + '/entities.json').entities || [],
84
- useCases: READ(moduleDir + '/usecases.json').useCases || [],
85
- rules: READ(moduleDir + '/rules.json').rules || [],
86
- permissions: READ(moduleDir + '/permissions.json'),
87
- screens: READ(moduleDir + '/screens.json').screens || []
89
+ entities: entitiesData.entities || [],
90
+ hasReferencedEntities: (entitiesData.referencedEntities || []).length > 0,
91
+ useCases: usecasesData.useCases || usecasesData.usecases || [],
92
+ rules: rulesData.rules || rulesData.businessRules || [],
93
+ permissions: permissionsData.permissionPaths
94
+ || (permissionsData.permissionSet?.permissions || []).map(p => p.code || p.path)
95
+ || (permissionsData.permissions || []).map(p => typeof p === 'string' ? p : (p.code || p.path))
96
+ || [],
97
+ screens: (screensData.screens || []).length > 0
98
+ ? screensData.screens
99
+ : (screensData.sections || []).flatMap(s => s.resources || [])
88
100
  };
89
101
  ```
90
102
 
@@ -1,17 +1,15 @@
1
1
  ---
2
2
  name: step-01-transform
3
3
  description: Build handoff data per module - 8 categories from flat BA files
4
- model: sonnet
5
4
  next_step: steps/step-02-export.md
6
5
  ---
7
6
 
8
- > **Context files:** `references/handoff-file-templates.md` | `references/handoff-mappings.md` | `references/handoff-seeddata-generation.md` | `references/entity-domain-mapping.md`
9
-
10
7
  # Step 01: Transform (Handoff Data Generation)
11
8
 
12
9
  ## MANDATORY EXECUTION RULES
13
10
 
14
11
  - **ALWAYS** process modules in topological order (dependencies first)
12
+ - **ALWAYS** delegate each module to an **isolated Agent** (context isolation — CRITICAL for large projects)
15
13
  - **ALWAYS** load data from **flat files** (entities.json, usecases.json, rules.json, screens.json, permissions.json)
16
14
  - **ALWAYS** map to 8 categories (including "documentation")
17
15
  - **ALWAYS** propagate personRoleConfig verbatim from entities
@@ -19,270 +17,167 @@ next_step: steps/step-02-export.md
19
17
  - **ALWAYS** map entity to domain file path (1:1)
20
18
  - **ALWAYS** include dependencies[] per file entry
21
19
  - **NEVER** invent entities/BRs not in module JSON files
20
+ - **NEVER** load all module data in the main conversation (causes context overflow on 5+ modules)
22
21
  - **ALWAYS** generate API endpoints from use cases + entities (BA does not produce apiEndpoints)
23
22
 
24
23
  ## YOUR TASK
25
24
 
26
- For each module in topological order, load flat BA files, build the complete handoff data with 8 file categories, BR-to-code mapping, API endpoint summary, and write to feature.json via ba-writer.
25
+ Orchestrate the transform: determine module order, then delegate each module's transform to an Agent with isolated context. This prevents context accumulation across modules.
27
26
 
28
27
  ---
29
28
 
30
- ## DATA LOADING (Flat-File Architecture)
31
-
32
- For each module, load data from separate files:
33
-
34
- ```javascript
35
- // Module BA directory: docs/{AppCode}/{ModuleCode}/business-analyse/v{X.Y}/
36
- const moduleDir = module.baDir; // resolved in step-00
29
+ ## CONTEXT ISOLATION ARCHITECTURE
37
30
 
38
- // Read with explicit error detection (do NOT silently swallow parse failures)
39
- const entitiesFile = READ(moduleDir + '/entities.json');
40
- const usecasesFile = READ(moduleDir + '/usecases.json');
41
- const rulesFile = READ(moduleDir + '/rules.json');
42
- const permissions = READ(moduleDir + '/permissions.json');
43
- const screensFile = READ(moduleDir + '/screens.json');
44
-
45
- // Log missing files explicitly before falling back
46
- if (!entitiesFile) console.warn("⚠ " + moduleDir + "/entities.json not found — using empty");
47
- if (!usecasesFile) console.warn("⚠ " + moduleDir + "/usecases.json not found — using empty");
48
- if (!rulesFile) console.warn("⚠ " + moduleDir + "/rules.json not found — using empty");
49
-
50
- const entities = (entitiesFile?.entities) || [];
51
- const useCases = (usecasesFile?.useCases) || [];
52
- const rules = (rulesFile?.rules) || [];
53
- const screens = (screensFile?.screens) || [];
31
+ ```
32
+ Main conversation (orchestrator):
33
+ ├─ Determine topological order
34
+ ├─ FOR each module:
35
+ │ └─ Agent(ba-writer) ──► reads 5 files, builds handoff, writes result
36
+ (isolated context: ~500-1000 lines per module)
37
+ └─ Collect results, display summary
54
38
  ```
55
39
 
56
- **Source mapping (flat files -> handoff categories):**
57
-
58
- | Handoff needs | Source file | Root key |
59
- |---------------|------------|----------|
60
- | Entities, ValueObjects, Enums | `entities.json` | `entities[]` |
61
- | Use cases | `usecases.json` | `useCases[]` |
62
- | Business rules | `rules.json` | `rules[]` |
63
- | Roles, permissions | `permissions.json` | `roles[]`, `matrix[]`, `permissionPaths[]` |
64
- | Screens, sections, wireframes | `screens.json` | `screens[]` |
40
+ **WHY:** A 10-module project has ~10K lines of JSON data. Loading all at once exceeds Sonnet's effective context. Processing one module per Agent keeps each invocation under ~2K lines.
65
41
 
66
42
  ---
67
43
 
68
44
  ## EXECUTION SEQUENCE
69
45
 
70
- For **EACH module** in topological order:
46
+ ### 1. Determine Module Processing Order
71
47
 
72
- ### 1. Calculate Complexity
48
+ From step-00 data, extract the topological order of modules. Display:
73
49
 
74
- ```json
75
- {
76
- "complexity": "simple|medium|complex",
77
- "complexityDetails": {
78
- "entities": {count},
79
- "useCases": {count},
80
- "businessRules": {count},
81
- "calculated": "{level} (entities<=X, UCs<=Y, BRs<=Z)"
82
- }
83
- }
84
50
  ```
51
+ Module processing order:
52
+ 1. {module1} (0 dependencies)
53
+ 2. {module2} (depends on: module1)
54
+ ...
55
+ ```
56
+
57
+ ### 2. Process Each Module via Agent
85
58
 
59
+ For **EACH module** in topological order, use the **Agent tool** (subagent_type: `ba-writer`) with the following prompt structure:
60
+
61
+ ```
62
+ Transform module "{moduleCode}" for handoff.
63
+
64
+ ## Input
65
+ - Module BA directory: {moduleDir}
66
+ - Application code: {appCode}
67
+ - Application name: {appName}
68
+ - Feature description: {featureDescription}
69
+ - Module index: {moduleDir}/index.json
70
+
71
+ ## Instructions
72
+ Read the following 5 files from {moduleDir}:
73
+ 1. entities.json → entities[]
74
+ 2. usecases.json → useCases[]
75
+ 3. rules.json → rules[]
76
+ 4. permissions.json → roles[], matrix[], permissionPaths[]
77
+ 5. screens.json → screens[]
78
+
79
+ Then build the handoff data following these rules:
80
+
81
+ ### Complexity
86
82
  | Criteria | Simple | Medium | Complex |
87
83
  |----------|--------|--------|---------|
88
84
  | Entities | <=3 | <=6 | >6 |
89
85
  | Use Cases | <=5 | <=12 | >12 |
90
86
  | Business Rules | <=10 | <=20 | >20 |
91
87
 
92
- **Global complexity** = highest across all modules.
93
-
94
- ### 2. Generate API Endpoints from Use Cases
95
-
96
- Since `/business-analyse` does not produce `apiEndpoints`, generate them from use cases + entities:
97
-
98
- ```javascript
99
- // For each use case, derive the API endpoint:
100
- // UC "Create Employee" -> POST /api/{app}/{module}
101
- // UC "List Employees" -> GET /api/{app}/{module}
102
- // UC "Update Employee" -> PUT /api/{app}/{module}/{id}
103
- // UC "Delete Employee" -> DELETE /api/{app}/{module}/{id}
104
- // UC "Get Employee" -> GET /api/{app}/{module}/{id}
105
-
106
- // Use permission paths from permissions.json to determine operations
107
- // Map CRUD operations to HTTP methods
108
- ```
109
-
110
- ### 2b. Enrich Sections with UC/BR Links
111
-
112
- Using `sectionCode` from usecases.json and rules.json, link each UC and BR to its section:
113
-
114
- ```javascript
115
- // Build section-level UC/BR mapping
116
- const sectionMap = {};
117
- for (const section of screens) {
118
- sectionMap[section.sectionCode || section.code] = {
119
- useCases: useCases.filter(uc => uc.sectionCode === (section.sectionCode || section.code)).map(uc => uc.id),
120
- businessRules: rules.filter(br => br.sectionCode === (section.sectionCode || section.code)).map(br => br.id)
121
- };
122
- }
123
- // Attach to sections for PRD consumption
124
- ```
125
-
126
- > This mapping enables business-analyse-develop's section-splitting to know which UCs/BRs belong to which section.
88
+ ### API Endpoints (generate from use cases)
89
+ - UC "Create X" → POST /api/{app}/{module}
90
+ - UC "List X" → GET /api/{app}/{module}
91
+ - UC "Update X" → PUT /api/{app}/{module}/{id}
92
+ - UC "Delete X" DELETE /api/{app}/{module}/{id}
93
+ - UC "Get X" → GET /api/{app}/{module}/{id}
94
+ - Use permission paths from permissions.json
127
95
 
128
- ### 3. Map Specification to Files (8 Categories)
96
+ ### Section UC/BR Enrichment
97
+ Using sectionCode from usecases.json and rules.json, link each UC and BR to its section.
129
98
 
130
- > **Reference:** See loaded context `handoff-file-templates.md` for complete JSON templates.
131
- > All backend paths MUST include `{ApplicationName}/` hierarchy.
99
+ ### File Mapping (8 Categories)
100
+ Read `references/handoff-file-templates.md` for complete JSON templates.
101
+ All backend paths MUST include {ApplicationName}/ hierarchy.
132
102
 
133
103
  | Category | Source | Key rules |
134
104
  |----------|--------|-----------|
135
- | **Domain** | `entities.json > entities[]` | Entities, ValueObjects, Enums |
136
- | **Application** | `usecases.json > useCases[]` | Services, DTOs, Validators |
137
- | **Infrastructure** | `entities.json > entities[]` | EF Configurations, DbSet |
105
+ | **Domain** | entities[] | Entities, ValueObjects, Enums |
106
+ | **Application** | useCases[] | Services, DTOs, Validators |
107
+ | **Infrastructure** | entities[] | EF Configurations, DbSet |
138
108
  | **API** | Generated from useCases + entities | Controllers |
139
- | **Frontend** | `screens.json > screens[]` | Pages, Components, Hooks; split by file (NOT monolithic) |
140
- | **SeedData** | Generated from entities + permissions | CORE (2 app-level + per-module) + business |
141
- | **Tests** | All layers | Unit, Integration, Security tests |
142
- | **Documentation** | All layers | Technical docs, user guides, API specs (can be empty `[]`) |
109
+ | **Frontend** | screens[] | Pages, Components, Hooks; split by file (NOT monolithic) |
110
+ | **SeedData** | entities + permissions | CORE + business (include category field) |
111
+ | **Tests** | All layers | Unit, Integration, Security |
112
+ | **Documentation** | All layers | Technical docs (can be empty []) |
143
113
 
144
- **Frontend Task Splitting (MANDATORY):**
145
- - Each page as separate entry (not bundled mega-task)
146
- - FK fields: `"fkFields": ["EmployeeId->Employee", "DepartmentId->Department"]`
147
- - ALL pages use `/ui-components` skill
148
- - Route wiring: separate entry in `filesToCreate.frontend`
114
+ Frontend: each page as separate entry, FK fields, ALL pages use /ui-components.
115
+ Routes: PascalCase module codes kebab-case (NEVER include /business/ prefix).
149
116
 
150
- **Route Convention (CRITICAL):**
151
- - Transform PascalCase module codes to kebab-case in NavigationModule/Section routes
152
- - Example: `"HumanResources"` -> `"/human-resources"` (NEVER include `/business/` prefix)
117
+ ### BR-to-Code Mapping
118
+ Read `references/handoff-mappings.md` for mapping rules.
119
+ For each rule: ruleId, title, module, severity, implementationPoints[].
153
120
 
154
- **Documentation Category:**
155
- - Include `doc-data.ts` for documentation data export
156
- - Can be empty `[]` if no documentation is planned at this stage
121
+ ### personRoleConfig
122
+ If entity has personRoleConfig, copy verbatim into handoff.
157
123
 
158
- ### 4. Map Business Rules to Code
124
+ ### SeedData
125
+ Read `references/handoff-seeddata-generation.md` for core seed generation.
126
+ - category: "core" → Navigation, Permissions, Roles
127
+ - category: "business" → Domain-specific data
159
128
 
160
- > **Reference:** See loaded context `handoff-mappings.md` -- Section "Business Rules to Code Mapping"
161
-
162
- For each rule in `rules.json > rules[]` of EACH module:
163
- - ruleId, title, module, severity (from `rule.severity`)
164
- - implementationPoints: Array of {layer, component, method, implementation} across all layers
165
-
166
- ### 5. Propagate personRoleConfig (GAP #2 Fix)
167
-
168
- For each entity in `entities.json > entities[]`:
169
- - IF entity has `personRoleConfig` property:
170
- - Copy verbatim into handoff entity data
171
-
172
- ### 6. Generate SeedData Core/Business (GAP #3 Fix)
173
-
174
- Generate seed data from entities and permissions:
175
-
176
- Each seedData entry MUST include a `category` field:
177
-
178
- ```json
179
- {
180
- "path": "src/Infrastructure/Persistence/Seeding/Data/NavigationApplicationSeedData.cs",
181
- "type": "SeedData",
182
- "category": "core",
183
- "module": "shared"
184
- }
185
- ```
186
-
187
- - `category: "core"` -- Navigation, Permissions, Roles (mandatory infrastructure)
188
- - `category: "business"` -- Domain-specific reference/lookup data
189
-
190
- > **Reference:** See loaded context `handoff-seeddata-generation.md` for complete core seed generation.
191
-
192
- ### 7. Map Entity to Domain File (GAP #4 Fix)
193
-
194
- > **Reference:** See loaded context `entity-domain-mapping.md` for complete mapping rules.
195
-
196
- 1:1 mapping from BA entity to Domain file:
197
-
198
- | BA Element | Domain File Path |
199
- |------------|-----------------|
200
- | Entity | `src/Domain/Entities/{App}/{Module}/{EntityName}.cs` |
201
- | ValueObject | `src/Domain/{Module}/ValueObjects/{VOName}.cs` |
202
- | Enum | `src/Domain/{Module}/Enums/{EnumName}.cs` |
203
-
204
- ### 8. Add Dependencies per File Entry (GAP #7 Fix)
205
-
206
- Each file entry includes `dependencies[]` ordered by layer:
129
+ ### Entity Domain Mapping
130
+ Read `references/entity-domain-mapping.md` for mapping rules.
131
+ - Entity src/Domain/Entities/{App}/{Module}/{EntityName}.cs
132
+ - ValueObject src/Domain/{Module}/ValueObjects/{VOName}.cs
133
+ - Enum src/Domain/{Module}/Enums/{EnumName}.cs
207
134
 
135
+ ### Dependencies per File Entry
208
136
  | Layer | Dependencies |
209
137
  |-------|-------------|
210
- | domain | `[]` (no dependencies) |
211
- | infrastructure | `["domain"]` |
212
- | application | `["domain"]` |
213
- | api | `["application"]` |
214
- | seedData | `["domain", "infrastructure"]` |
215
- | frontend | `["api"]` |
216
- | tests | `["domain", "application", "infrastructure", "api"]` |
217
- | documentation | `[]` |
138
+ | domain | [] |
139
+ | infrastructure | ["domain"] |
140
+ | application | ["domain"] |
141
+ | api | ["application"] |
142
+ | seedData | ["domain", "infrastructure"] |
143
+ | frontend | ["api"] |
144
+ | tests | ["domain", "application", "infrastructure", "api"] |
145
+ | documentation | [] |
146
+
147
+ ### Write Result
148
+ Write via ba-writer.enrichModuleHandoff with the complete handoff payload:
149
+ - complexity, filesToCreate (8 categories), brToCodeMapping, apiEndpointSummary
150
+ - prdFile: ".ralph/prd-{moduleCode}.json"
151
+ - totalFiles, totalTasks, handedOffAt (ISO timestamp)
152
+ - featureDescription: {featureDescription}
153
+
154
+ ### POST-CHECK (BLOCKING)
155
+ After writing, verify:
156
+ 1. Handoff not empty
157
+ 2. All 8 categories present
158
+ 3. brToCodeMapping non-empty
159
+ 4. Section resources have entity field
160
+ Display: "POST-CHECK PASS: {moduleCode} -- 8 categories, {brCount} BRs mapped"
161
+ ```
162
+
163
+ ### 3. Display Progress
218
164
 
219
- ### 9. Write Handoff to Feature.json
165
+ After each Agent completes, display:
220
166
 
221
167
  ```
222
- FOR i = 0 to modules.length-1:
223
- 1. moduleCode = modules[i].code
224
- 2. Build handoff payload:
225
- - complexity (from step 1)
226
- - filesToCreate (full 8-category structure, filtered for this module)
227
- - brToCodeMapping (from step 4)
228
- - apiEndpointSummary (from step 2)
229
- - prdFile: ".ralph/prd-{moduleCode}.json"
230
- - totalFiles: count from filesToCreate
231
- - totalTasks: estimated from complexity
232
- - handedOffAt: ISO timestamp
233
- 3. Propagate featureDescription from app-level index.json:
234
- ```javascript
235
- handoffPayload.featureDescription = appIndex.metadata.featureDescription || null;
236
- ```
237
- 4. Write via ba-writer.enrichModuleHandoff({ moduleFeatureId, handoffData })
238
- 5. Display: "handoff {i+1}/{N}: {moduleCode} ({fileCount} files)"
168
+ handoff {i+1}/{N}: {moduleCode} ({fileCount} files)
239
169
  ```
240
170
 
241
- ### 10. POST-CHECK Per Module (BLOCKING)
171
+ ### 4. Display Summary
242
172
 
243
- Run the **output** AC script from `references/acceptance-criteria.md`:
244
-
245
- ```bash
246
- MODULE_JSON="{module_index_json_path}"
247
- node -e "
248
- // ... (output AC script from references/acceptance-criteria.md)
249
- " "$MODULE_JSON"
250
173
  ```
251
-
252
- For each module, verify:
253
-
254
- ```javascript
255
- const handoff = moduleFeature.handoff;
256
-
257
- // 1. Handoff not empty
258
- if (!handoff || Object.keys(handoff).length === 0) {
259
- BLOCKING_ERROR("Module {moduleCode}: handoff is empty");
260
- }
261
-
262
- // 2. All 8 categories present (AC-08)
263
- const categories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests', 'documentation'];
264
- const missing = categories.filter(cat => !handoff.filesToCreate[cat]);
265
- if (missing.length > 0) {
266
- BLOCKING_ERROR("Module {moduleCode}: missing categories: " + missing.join(', '));
267
- }
268
-
269
- // 3. BR-to-code mapping non-empty (AC-09)
270
- if (!handoff.brToCodeMapping || handoff.brToCodeMapping.length === 0) {
271
- BLOCKING_ERROR("Module {moduleCode}: brToCodeMapping is empty");
272
- }
273
-
274
- // 4. Validate section resources have entity field (enables section-splitting)
275
- const sections = screens || [];
276
- for (const section of sections) {
277
- for (const resource of (section.resources || [])) {
278
- if (!resource.entity) {
279
- BLOCKING_ERROR("Module {moduleCode}, section {section.code}: resource {resource.code} missing 'entity' field");
280
- }
281
- }
282
- }
283
-
284
- // 5. Display pass
285
- console.log("POST-CHECK PASS: {moduleCode} -- 8 categories, {brCount} BRs mapped, {sections.length} sections validated");
174
+ ================================================================
175
+ TRANSFORM COMPLETE
176
+ ================================================================
177
+ Modules processed: {N}/{N}
178
+ Total files mapped: {totalFiles}
179
+ Global complexity: {highest_complexity}
180
+ ================================================================
286
181
  ```
287
182
 
288
183
  ---
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: step-02-export
3
3
  description: Generate PRD files, verify integrity, output progress tracker and manifest
4
- model: sonnet
5
4
  ---
6
5
 
7
6
  > **Context files:** `references/prd-generation.md` | `templates/tpl-progress.md`
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: step-00-init
3
3
  description: Initialize review workflow — locate ba-review.json, detect feature, set variables
4
- model: sonnet
5
4
  next_step: steps/step-01-apply.md
6
5
  ---
7
6
 
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: business-analyse-status
3
3
  description: Display the current state of business analysis cycle, show progress per module, and recommend next steps.
4
- model: sonnet
5
4
  user-invocable: true
6
5
  ---
7
6