@atlashub/smartstack-cli 3.34.0 → 3.36.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 (39) hide show
  1. package/.documentation/init.html +409 -0
  2. package/dist/index.js +35 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/mcp-entry.mjs +118 -70
  5. package/dist/mcp-entry.mjs.map +1 -1
  6. package/package.json +1 -2
  7. package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
  8. package/templates/skills/apex/SKILL.md +6 -3
  9. package/templates/skills/apex/references/post-checks.md +225 -0
  10. package/templates/skills/apex/references/smartstack-api.md +29 -1
  11. package/templates/skills/apex/references/smartstack-frontend.md +27 -0
  12. package/templates/skills/apex/references/smartstack-layers.md +18 -2
  13. package/templates/skills/apex/steps/step-00-init.md +77 -1
  14. package/templates/skills/apex/steps/step-01-analyze.md +21 -0
  15. package/templates/skills/apex/steps/step-03-execute.md +94 -5
  16. package/templates/skills/apex/steps/step-04-examine.md +7 -1
  17. package/templates/skills/business-analyse/SKILL.md +4 -3
  18. package/templates/skills/business-analyse/_shared.md +9 -0
  19. package/templates/skills/business-analyse/schemas/application-schema.json +13 -0
  20. package/templates/skills/business-analyse/steps/step-00-init.md +190 -34
  21. package/templates/skills/business-analyse/steps/step-01-cadrage.md +129 -10
  22. package/templates/skills/business-analyse/steps/step-01b-applications.md +184 -13
  23. package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
  24. package/templates/skills/business-analyse/steps/step-03d-validate.md +5 -1
  25. package/templates/skills/documentation/SKILL.md +175 -9
  26. package/templates/skills/efcore/steps/squash/step-03-create.md +6 -4
  27. package/templates/skills/gitflow/_shared.md +3 -1
  28. package/templates/skills/gitflow/steps/step-pr.md +34 -0
  29. package/templates/skills/ralph-loop/SKILL.md +31 -2
  30. package/templates/skills/ralph-loop/references/category-rules.md +29 -0
  31. package/templates/skills/ralph-loop/references/compact-loop.md +85 -2
  32. package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
  33. package/templates/skills/ralph-loop/references/team-orchestration.md +331 -14
  34. package/templates/skills/ralph-loop/steps/step-00-init.md +4 -0
  35. package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
  36. package/templates/skills/ralph-loop/steps/step-02-execute.md +206 -1
  37. package/templates/skills/ralph-loop/steps/step-05-report.md +19 -0
  38. package/scripts/health-check.sh +0 -168
  39. package/scripts/postinstall.js +0 -18
@@ -81,7 +81,68 @@ Identify the specific name:
81
81
 
82
82
  ### STEP 3: EXECUTION
83
83
 
84
- **For NEW documentation (type = user|developer|database|testing):**
84
+ **For NEW documentation (type = user) - AUTOMATIC MOCK UI GENERATION:**
85
+
86
+ Use the automated generator script that creates complete documentation with Mock UI components:
87
+
88
+ ```bash
89
+ npx tsx scripts/generate-doc-with-mock-ui.ts \
90
+ --module {module} \
91
+ --context {context} \
92
+ --application {application} \
93
+ --app-path "D:/01 - projets/SmartStack.app/02-Develop"
94
+ ```
95
+
96
+ **What it does automatically:**
97
+
98
+ 1. **Find & Extract Entity** (e.g., users → User.cs)
99
+ - Locates Domain entity file
100
+ - Extracts all properties with types
101
+
102
+ 2. **Extract API Endpoints** (via `extract-api-endpoints.ts`)
103
+ - Scans controller for all endpoints
104
+ - Parses `[HttpGet]`, `[HttpPost]`, `[NavRoute]`, `[RequirePermission]`
105
+ - Resolves permission constants
106
+ - Output: JSON array of endpoints with method, path, handler, permission
107
+
108
+ 3. **Extract Business Rules** (via `extract-business-rules.ts`)
109
+ - Scans Domain entity for guard clauses and DomainExceptions
110
+ - Scans unit tests for edge case scenarios
111
+ - Auto-assigns BR-XXX IDs and categorizes rules
112
+ - Output: JSON array of business rules with id, name, category, statement
113
+
114
+ 4. **Generate Mock UI Components**
115
+ - **KPIs**: Automatic stats based on entity properties
116
+ - Total count
117
+ - Active/Inactive (if IsActive property)
118
+ - Status breakdown (if Status property)
119
+ - Time-based stats (if DateTime property)
120
+ - **Table**: Smart column selection (6 most relevant properties)
121
+ - Filters out: Hash, Token, *Id (FK), normalized, internal fields
122
+ - Prioritizes: name/title → email → status → date
123
+ - **Form**: Create form with intelligent field types
124
+ - Email → type="email" with placeholder
125
+ - Bool → checkbox
126
+ - DateTime → type="date"
127
+ - Description/Notes → textarea
128
+ - Default → type="text"
129
+
130
+ 5. **Generate Complete TSX File**
131
+ - Full React component with breadcrumb, sections, mock data
132
+ - Section 1: Introduction
133
+ - Section 2: Access (navigation path + URL)
134
+ - Section 3: Interface Overview (KPIs + Table Mock UI)
135
+ - Section 4: Create Form (generated form fields)
136
+ - Section 5: API Reference (endpoints table)
137
+
138
+ 6. **Manual Steps (Post-Generation)**
139
+ - Save generated TSX to `docs/business/{context}/{application}/{module}/index.tsx`
140
+ - Update docs-manifest.json
141
+ - Update App.tsx routing
142
+ - Update DocPanelContext.tsx mapping
143
+ - Generate i18n FR file (if needed)
144
+
145
+ **For NEW documentation (type = developer|database|testing):**
85
146
 
86
147
  Follow the data-driven workflow from [templates.md](templates.md):
87
148
 
@@ -92,22 +153,127 @@ Follow the data-driven workflow from [templates.md](templates.md):
92
153
  4. Generate i18n FR file (source language only)
93
154
  5. Update docs-manifest.json
94
155
  6. Update App.tsx routing and parent indexes
95
- 7. Update DocPanelContext.tsx mapping (contextual doc panel)
96
156
  ```
97
157
 
98
158
  **For UPDATE documentation (type = update):**
99
159
 
160
+ Re-run the generator script to refresh automatically extracted data:
161
+
100
162
  ```
101
- 1. Read docs-manifest.jsonfind target module
102
- 2. Invoke docs-context-reader agent get current doc state
103
- 3. Identify code changes since last doc update (git diff)
104
- 4. Map changes to documentation sections (see data-schema.md)
105
- 5. Update doc-data.ts with new/modified data
106
- 6. Update i18n FR file if labels changed
107
- 7. Update docs-manifest.json timestamps
163
+ 1. Run generate-doc-with-mock-ui.tsregenerates with latest API/rules
164
+ 2. Update i18n FR file if labels changed
165
+ 3. Update docs-manifest.json timestamps
108
166
  ```
109
167
 
110
168
  > **i18n simplifié:** Seul FR (source) est généré. EN/IT/DE sont déférés à un pipeline de traduction séparé.
169
+
170
+ ---
171
+
172
+ ## EXTRACTION SCRIPTS REFERENCE
173
+
174
+ ### extract-api-endpoints.ts
175
+
176
+ **Purpose:** Extract all API endpoints from SmartStack controllers
177
+
178
+ **Input:**
179
+ - `--module {module}` - Module name (e.g., users, tenants)
180
+ - `--app-path {path}` - Path to SmartStack.app
181
+
182
+ **What it extracts:**
183
+ - Controller file path (e.g., `UsersController.cs`)
184
+ - HTTP method (`[HttpGet]`, `[HttpPost]`, `[HttpPut]`, `[HttpDelete]`, `[HttpPatch]`)
185
+ - Route suffix (e.g., `{id:guid}`, `activate`)
186
+ - Base path from `[NavRoute("platform.administration.users")]`
187
+ - Permission from `[RequirePermission(Permissions.Admin.Users.View)]`
188
+ - Handler method name
189
+
190
+ **Output:** JSON array
191
+ ```json
192
+ [
193
+ {
194
+ "method": "GET",
195
+ "path": "/api/platform/administration/users",
196
+ "handler": "GetUsers",
197
+ "permission": "platform.administration.users.read"
198
+ }
199
+ ]
200
+ ```
201
+
202
+ **Permission resolution:**
203
+ - Loads `Permissions.cs` constants
204
+ - Maps `Permissions.Admin.Users.View` → `"platform.administration.users.read"`
205
+
206
+ ---
207
+
208
+ ### extract-business-rules.ts
209
+
210
+ **Purpose:** Extract business rules from Domain entities and unit tests
211
+
212
+ **Input:**
213
+ - `--module {module}` - Module name (e.g., users, tenants)
214
+ - `--app-path {path}` - Path to SmartStack.app
215
+
216
+ **Phase 1: Domain Entity Extraction**
217
+ - Scans Domain entity (e.g., `User.cs`)
218
+ - Looks for guard clauses: `if (...) throw new DomainException("...")`
219
+ - Looks for validation in Create/Update methods
220
+ - Extracts exception messages and context
221
+
222
+ **Phase 2: Unit Tests Extraction**
223
+ - Scans unit test file (e.g., `UserTests.cs`)
224
+ - Looks for test methods with `[Fact]` attribute
225
+ - Extracts test names and scenarios (edge cases)
226
+ - Maps to business rule statements
227
+
228
+ **Output:** JSON array
229
+ ```json
230
+ [
231
+ {
232
+ "id": "BR-001",
233
+ "name": "Email requis",
234
+ "category": "Validation",
235
+ "statement": "Un utilisateur doit avoir une adresse email valide et non vide"
236
+ }
237
+ ]
238
+ ```
239
+
240
+ **Auto-categorization:**
241
+ - Validation: Required fields, format checks
242
+ - Security: Password rules, access control
243
+ - Business Logic: State transitions, calculations
244
+
245
+ ---
246
+
247
+ ### generate-doc-with-mock-ui.ts
248
+
249
+ **Purpose:** Main generator - creates complete documentation TSX with Mock UI
250
+
251
+ **Input:**
252
+ - `--module {module}` - Module name (e.g., users)
253
+ - `--context {context}` - Context (e.g., platform)
254
+ - `--application {application}` - Application (e.g., administration)
255
+ - `--app-path {path}` - Path to SmartStack.app
256
+
257
+ **Workflow:**
258
+ 1. Find Domain entity file (users → User.cs via singularize)
259
+ 2. Extract entity properties (name, type, nullable, required)
260
+ 3. Call `extract-api-endpoints.ts`
261
+ 4. Call `extract-business-rules.ts`
262
+ 5. Generate mock data (5 sample records with realistic values)
263
+ 6. Generate KPI stats (Total, Active/Inactive, Status breakdown)
264
+ 7. Generate table UI (smart column selection - 6 most relevant)
265
+ 8. Generate form UI (intelligent field types based on property)
266
+ 9. Output complete TSX file to stdout
267
+
268
+ **Smart Features:**
269
+ - **Singularize**: users → User.cs, tenants → Tenant.cs
270
+ - **Property filtering**: Excludes hash, token, *Id, normalized, internal
271
+ - **Priority selection**: name/title > email > status > date
272
+ - **Field type detection**: email → email input, bool → checkbox
273
+ - **Mock value generation**: Realistic emails, names, dates, GUIDs
274
+
275
+ **Output:** Complete React TSX component (400-500 lines)
276
+
111
277
  </workflow>
112
278
 
113
279
  <execution_rules>
@@ -55,10 +55,11 @@ echo "DbContext Type: $DBCONTEXT_TYPE"
55
55
 
56
56
  const result = await mcp__smartstack__suggest_migration({
57
57
  description: DESCRIPTION,
58
- context: DBCONTEXT_TYPE // NEVER hardcode!
58
+ context: DBCONTEXT_TYPE, // NEVER hardcode!
59
+ squash: true // Squash format: {context}_v{version} (no sequence/description)
59
60
  });
60
61
 
61
- // Result example: core_v1.9.0_001_MultitenantConsolidated
62
+ // Result example: core_v1.9.0 (squash — just version, no _001_Description)
62
63
  MIGRATION_NAME = result.migrationName;
63
64
  ```
64
65
 
@@ -66,11 +67,12 @@ MIGRATION_NAME = result.migrationName;
66
67
  - Calculating name manually
67
68
  - Hardcoding context as "core"
68
69
  - Using underscores instead of dots in version
70
+ - Adding sequence/description to squash migrations
69
71
 
70
72
  ### 3. Create Migration with EF Core
71
73
 
72
74
  ```bash
73
- # MIGRATION_NAME = result from MCP (e.g., core_v1.9.0_001_MultitenantConsolidated)
75
+ # MIGRATION_NAME = result from MCP (e.g., core_v1.9.0)
74
76
  # DBCONTEXT = CoreDbContext or ExtensionsDbContext (from detect_dbcontext)
75
77
 
76
78
  echo ""
@@ -211,7 +213,7 @@ After step-03-create:
211
213
 
212
214
  | Variable | Description |
213
215
  |----------|-------------|
214
- | `{migration_name}` | Name from MCP (e.g., core_v1.9.0_001_...) |
216
+ | `{migration_name}` | Name from MCP (e.g., core_v1.9.0) |
215
217
  | `{migration_file}` | Full path to .cs file |
216
218
  | `{designer_file}` | Full path to .Designer.cs file |
217
219
 
@@ -462,7 +462,9 @@ GitFlow configuration JSON template v2.1.0 (aligned with `templates/config.json`
462
462
  "enabled": true,
463
463
  "validateOnCommit": true,
464
464
  "blockDestructive": true,
465
- "migrationNaming": "{context}_v{version}_{sequence}_{Description}"
465
+ "migrationNaming": "{context}_v{version}_{sequence}_{Description}",
466
+ "migrationNamingSquash": "{context}_v{version}",
467
+ "squashBeforePR": true
466
468
  },
467
469
  "workflow": {
468
470
  "push": {
@@ -122,6 +122,40 @@ else
122
122
  fi
123
123
  ```
124
124
 
125
+ ### 4b. Enforce Migration Squash (Feature Branches)
126
+
127
+ **BLOCKING**: Feature branches must have at most 1 migration before creating a PR.
128
+
129
+ ```bash
130
+ if [ "$BRANCH_TYPE" = "feature" ]; then
131
+ MIGRATION_DIR=$(find . -path "*/Persistence/Migrations" -type d 2>/dev/null | head -1)
132
+ if [ -n "$MIGRATION_DIR" ]; then
133
+ # Count migration .cs files added by this feature (not in target branch)
134
+ NEW_MIGRATIONS=$(git diff --name-only "origin/$TARGET_BRANCH...HEAD" -- "$MIGRATION_DIR" \
135
+ | grep -E '\.cs$' \
136
+ | grep -v 'Designer\|ModelSnapshot' \
137
+ | wc -l)
138
+
139
+ if [ "$NEW_MIGRATIONS" -gt 1 ]; then
140
+ echo ""
141
+ echo "❌ MULTIPLE MIGRATIONS DETECTED ($NEW_MIGRATIONS migrations)"
142
+ echo "→ Feature branches must have exactly 1 migration (squashed) before PR"
143
+ echo "→ Run: /efcore squash"
144
+ echo ""
145
+ echo "Migrations found:"
146
+ git diff --name-only "origin/$TARGET_BRANCH...HEAD" -- "$MIGRATION_DIR" \
147
+ | grep -E '\.cs$' \
148
+ | grep -v 'Designer\|ModelSnapshot'
149
+ STOP
150
+ elif [ "$NEW_MIGRATIONS" -eq 1 ]; then
151
+ echo "✓ Single migration detected (squashed)"
152
+ else
153
+ echo "✓ No migrations in this feature"
154
+ fi
155
+ fi
156
+ fi
157
+ ```
158
+
125
159
  ### 5. Generate PR Content
126
160
 
127
161
  **Title:**
@@ -36,6 +36,7 @@ Execute the Ralph Weegund technique — iterative module orchestration. Ralph re
36
36
  | `-c TEXT` | `--completion-promise TEXT` | Completion signal text |
37
37
  | `-v` | `--verbose` | Detailed logging |
38
38
  | `-r` | `--resume` | Resume from previous state |
39
+ | `-p` | `--parallel` | Teams mode: Phase 0 (entities) sequential, then spawn parallel teammates per application/module |
39
40
  </parameters>
40
41
 
41
42
  <workflow>
@@ -50,9 +51,30 @@ Execute the Ralph Weegund technique — iterative module orchestration. Ralph re
50
51
  - Find eligible → batch by category (max 5) → execute → test → commit → loop
51
52
  7. Report (step-05)
52
53
 
53
- **Multi-module (2+ modules, from BA handoff):**
54
+ **Multi-module (2+ modules) with `-p` (parallel mode):**
55
+ 1. Init: detect prd-*.json, parse `-p` flag (step-00)
56
+ 2. **Phase 0 (Ralph sequential):**
57
+ - Ralph generates ALL entities from ALL modules via `/apex --foundation`
58
+ - Creates ONE migration with all entities
59
+ - Commits: `chore(foundation): entities for all modules`
60
+ 3. **Phase 1-N (Teams parallel):**
61
+ ```
62
+ Team Lead → TeamCreate("smartstack-{project}")
63
+ Spawn teammates (1 per application OR 1 per module if app > 3 modules):
64
+ - Task(subagent_type: "apex", name: "apex-hr")
65
+ - Task(subagent_type: "apex", name: "apex-crm")
66
+ - Task(subagent_type: "apex", name: "apex-pm")
67
+ Each teammate generates:
68
+ - Services + Controllers + Seed data + Frontend + Tests
69
+ - NO entities (already done in Phase 0)
70
+ - NO migrations (ModelSnapshot already complete)
71
+ → Teammates work in parallel → Ralph collects results → TeamDelete
72
+ ```
73
+ 4. Report with per-module aggregation (step-05)
74
+
75
+ **Multi-module (2+ modules) WITHOUT `-p` (sequential mode — legacy):**
54
76
  1. Init: detect prd-*.json, read dependency layers (step-00)
55
- 2. **IF dependency graph available:** Agent Teams (parallel)
77
+ 2. **IF dependency graph available:** Agent Teams (parallel, legacy)
56
78
  ```
57
79
  Team Lead → TeamCreate("ralph-{app}")
58
80
  Layer 0: Spawn "mod-employees" (foundation) → wait LAYER_READY
@@ -79,6 +101,10 @@ LOAD → DELEGATE TO /apex -d → VERIFY PRD STATE → COMMIT PRD → NEXT MODUL
79
101
  | `{current_iteration}` | number | Current iteration |
80
102
  | `{current_module}` | string\|null | Current module (multi-module) |
81
103
  | `{modules_queue}` | object\|null | Module queue (multi-module) |
104
+ | `{section_split_mode}` | boolean | Section splitting active for current module (>4 entities + >1 section) |
105
+ | `{section_phases}` | SectionPhase[] | Phase execution plan (Phase 0: foundation, Phase 1..N: per-section) |
106
+ | `{parallel_mode}` | boolean | Teams mode enabled via `-p` flag. Ralph generates Phase 0 (entities) sequentially, then spawns parallel teammates. |
107
+ | `{team_name}` | string\|null | Team name for parallel mode (e.g., "smartstack-hr") |
82
108
  </state_variables>
83
109
 
84
110
  <mcp_requirements>
@@ -141,6 +167,7 @@ When the user invokes `/ralph-loop`, they are giving you the instruction to:
141
167
  |------|-------------|
142
168
  | `references/category-rules.md` | Step-01 and compact loop (category ordering and dependency rules) |
143
169
  | `references/compact-loop.md` | Step-04 section 5 (module loop with /apex delegation) |
170
+ | `references/section-splitting.md` | Step-01 section 4c when module has >4 entities + >1 section |
144
171
  | `references/team-orchestration.md` | Step-00 when multi-module detected (2+ PRDs) |
145
172
  </step_files>
146
173
 
@@ -151,6 +178,8 @@ When the user invokes `/ralph-loop`, they are giving you the instruction to:
151
178
  ├── progress.txt # Persistent memory
152
179
  ├── modules-queue.json # Multi-module tracking (if applicable)
153
180
  ├── prd-{module}.json # Per-module PRDs (from ss derive-prd, unified v3 format)
181
+ ├── prd-{module}-phase0.json # Section split: Foundation (domain+infra+migration)
182
+ ├── prd-{module}-section-{code}.json # Section split: Per-section (app+api+seed+frontend+tests)
154
183
  ├── logs/
155
184
  └── reports/
156
185
  └── {feature}.md
@@ -65,3 +65,32 @@ A valid PRD MUST contain tasks in these categories:
65
65
  - `test` — at least 1 test task
66
66
 
67
67
  If any category is missing, ralph step-01 injects a guardrail task.
68
+
69
+ ---
70
+
71
+ ## Section-Level Splitting (>4 Entities)
72
+
73
+ When a module has many entities, a single `/apex -d` call saturates the context window.
74
+ Section-level splitting breaks the module into smaller, manageable phases.
75
+
76
+ **Activation threshold:** `> 4 domain tasks` AND `> 1 architecture section`
77
+
78
+ | Phase | Content | Depends On |
79
+ |-------|---------|------------|
80
+ | Phase 0 | ALL domain + infrastructure + migration + module seed data | — |
81
+ | Phase 1 | Section A: services, controllers, section seed, pages, i18n, tests | Phase 0 |
82
+ | Phase 2 | Section B: idem | Phase 0 (+ Phase 1 if FK cross-section) |
83
+ | Phase N | Section N: idem | Phase 0 (+ earlier phases if FK) |
84
+ | Final | Cross-validation (dotnet build, typecheck, MCP validate) | All phases |
85
+
86
+ **Key rules:**
87
+ - Phase 0 creates ALL entity classes + ALL EF configs + ONE migration (avoids ModelSnapshot conflicts)
88
+ - Section phases NEVER create entities or migrations — only services, controllers, pages on top
89
+ - FK cross-section dependencies determine section execution order (topological sort)
90
+ - Orphan entities (not in any section) are included in Phase 0 with their services/controllers
91
+ - Each phase produces a temporary PRD file: `.ralph/prd-{module}-phase0.json`, `.ralph/prd-{module}-section-{code}.json`
92
+ - Temporary PRD files are cleaned up in step-05 (report)
93
+
94
+ **Backward compatible:** Modules with `<= 4 domain tasks` or `1 section` → standard execution, zero impact.
95
+
96
+ See `references/section-splitting.md` for full detection, mapping, and execution logic.
@@ -23,10 +23,93 @@ Display compact progress:
23
23
 
24
24
  ---
25
25
 
26
- ## A. Find Eligible Tasks
26
+ ## A0. Section-Split Mode (checked BEFORE standard batching)
27
27
 
28
28
  ```javascript
29
29
  const prd = readJSON('.ralph/prd.json');
30
+
31
+ if (prd._sectionSplit?.enabled) {
32
+ // SECTION-SPLIT: Delegate per-phase instead of per-category batch
33
+
34
+ // Find next pending phase with dependencies met
35
+ const nextPhase = prd._sectionSplit.phases.find(p => p.status === 'pending');
36
+
37
+ if (!nextPhase) {
38
+ // All phases done — check if master PRD tasks are all complete
39
+ goto CHECK_COMPLETION;
40
+ }
41
+
42
+ const depsOk = nextPhase.dependsOn.every(depIdx =>
43
+ prd._sectionSplit.phases[depIdx].status === 'completed'
44
+ );
45
+
46
+ if (!depsOk) {
47
+ // Phase blocked — should not happen with topological sort
48
+ console.warn(`Phase ${nextPhase.phase} blocked — dependencies incomplete`);
49
+ goto CHECK_COMPLETION;
50
+ }
51
+
52
+ const phaseLabel = nextPhase.type === 'foundation'
53
+ ? `Phase 0: Foundation (${nextPhase.entities.length} entities + migration)`
54
+ : `Phase ${nextPhase.phase}: Section "${nextPhase.sectionCode}" (${nextPhase.entities.length} entities)`;
55
+ console.log(`[{iteration}/{max}] SECTION SPLIT: ${phaseLabel}`);
56
+
57
+ // INVOKE /apex -d {nextPhase.prdFile}
58
+ // Apex sees a normal (smaller) PRD and executes normally
59
+
60
+ // After apex returns: merge results back into master PRD
61
+ // Read references/section-splitting.md sections 7-9
62
+ const phasePrd = readJSON(nextPhase.prdFile);
63
+ for (const phaseTask of phasePrd.tasks) {
64
+ const masterTask = prd.tasks.find(t => t.id === phaseTask.id);
65
+ if (masterTask) {
66
+ masterTask.status = phaseTask.status;
67
+ masterTask.completed_at = phaseTask.completed_at;
68
+ masterTask.commit_hash = phaseTask.commit_hash;
69
+ masterTask.files_changed = phaseTask.files_changed;
70
+ masterTask.error = phaseTask.error;
71
+ masterTask.validation = phaseTask.validation;
72
+ }
73
+ }
74
+
75
+ // Handle phase failure
76
+ if (phasePrd.tasks.some(t => t.status === 'failed')) {
77
+ const retryCount = nextPhase._retryCount || 0;
78
+ if (retryCount < 2) {
79
+ nextPhase.status = 'pending';
80
+ nextPhase._retryCount = retryCount + 1;
81
+ console.log(`Phase ${nextPhase.phase} had failures — retry ${retryCount + 1}/2`);
82
+ // Reset failed tasks in phase PRD for retry
83
+ for (const task of phasePrd.tasks) {
84
+ if (task.status === 'failed') { task.status = 'pending'; task.error = null; }
85
+ }
86
+ writeJSON(nextPhase.prdFile, phasePrd);
87
+ } else {
88
+ nextPhase.status = 'failed';
89
+ console.error(`Phase ${nextPhase.phase} failed after 2 retries`);
90
+ }
91
+ } else {
92
+ nextPhase.status = 'completed';
93
+ }
94
+
95
+ prd._sectionSplit.currentPhase = nextPhase.phase;
96
+ writeJSON('.ralph/prd.json', prd);
97
+
98
+ // → Skip to section C (commit PRD state), then D (loop back)
99
+ goto COMMIT_PRD;
100
+ }
101
+ ```
102
+
103
+ > **IMPORTANT:** When `_sectionSplit.enabled`, the standard category-based batching (section A below)
104
+ > is SKIPPED. The loop delegates per-phase to apex instead of per-category-batch.
105
+
106
+ ---
107
+
108
+ ## A. Find Eligible Tasks
109
+
110
+ > **Note:** This section is SKIPPED when `prd._sectionSplit?.enabled` (handled by A0 above).
111
+
112
+ ```javascript
30
113
  const MAX_RETRIES = 3;
31
114
 
32
115
  // RETRY: Reset failed tasks to pending if retries remain (max 3 attempts per task)
@@ -115,7 +198,7 @@ writeJSON('.ralph/prd.json', prd);
115
198
  Apex handles everything for the current module:
116
199
  - Reads PRD, extracts context (context_code, app_name, module_code, entities, sections)
117
200
  - Executes ALL layers: domain → infrastructure → migration → application → api → seed data → frontend → tests
118
- - Runs full POST-CHECKs (43 checks from `references/post-checks.md`)
201
+ - Runs full POST-CHECKs (50 checks from `references/post-checks.md`)
119
202
  - Commits per layer (atomic commits)
120
203
  - Validates with MCP (`validate_conventions`)
121
204
  - Updates task statuses in the PRD file directly