@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.
- package/.documentation/init.html +409 -0
- package/dist/index.js +35 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +118 -70
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -2
- package/templates/mcp-scaffolding/controller.cs.hbs +5 -1
- package/templates/skills/apex/SKILL.md +6 -3
- package/templates/skills/apex/references/post-checks.md +225 -0
- package/templates/skills/apex/references/smartstack-api.md +29 -1
- package/templates/skills/apex/references/smartstack-frontend.md +27 -0
- package/templates/skills/apex/references/smartstack-layers.md +18 -2
- package/templates/skills/apex/steps/step-00-init.md +77 -1
- package/templates/skills/apex/steps/step-01-analyze.md +21 -0
- package/templates/skills/apex/steps/step-03-execute.md +94 -5
- package/templates/skills/apex/steps/step-04-examine.md +7 -1
- package/templates/skills/business-analyse/SKILL.md +4 -3
- package/templates/skills/business-analyse/_shared.md +9 -0
- package/templates/skills/business-analyse/schemas/application-schema.json +13 -0
- package/templates/skills/business-analyse/steps/step-00-init.md +190 -34
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +129 -10
- package/templates/skills/business-analyse/steps/step-01b-applications.md +184 -13
- package/templates/skills/business-analyse/steps/step-03c-compile.md +14 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +5 -1
- package/templates/skills/documentation/SKILL.md +175 -9
- package/templates/skills/efcore/steps/squash/step-03-create.md +6 -4
- package/templates/skills/gitflow/_shared.md +3 -1
- package/templates/skills/gitflow/steps/step-pr.md +34 -0
- package/templates/skills/ralph-loop/SKILL.md +31 -2
- package/templates/skills/ralph-loop/references/category-rules.md +29 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +85 -2
- package/templates/skills/ralph-loop/references/section-splitting.md +439 -0
- package/templates/skills/ralph-loop/references/team-orchestration.md +331 -14
- package/templates/skills/ralph-loop/steps/step-00-init.md +4 -0
- package/templates/skills/ralph-loop/steps/step-01-task.md +27 -0
- package/templates/skills/ralph-loop/steps/step-02-execute.md +206 -1
- package/templates/skills/ralph-loop/steps/step-05-report.md +19 -0
- package/scripts/health-check.sh +0 -168
- 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
|
|
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.
|
|
102
|
-
2.
|
|
103
|
-
3.
|
|
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.ts → regenerates 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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
##
|
|
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 (
|
|
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
|