@atlashub/smartstack-cli 3.17.0 → 3.18.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 +1 -1
- package/templates/skills/business-analyse/SKILL.md +4 -4
- package/templates/skills/business-analyse/steps/step-00-init.md +23 -5
- package/templates/skills/business-analyse/steps/step-03d-validate.md +34 -1
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +9 -7
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +222 -40
- package/templates/skills/ralph-loop/SKILL.md +41 -1
- package/templates/skills/ralph-loop/references/category-rules.md +96 -2
- package/templates/skills/ralph-loop/references/compact-loop.md +85 -24
- package/templates/skills/ralph-loop/steps/step-00-init.md +30 -54
- package/templates/skills/ralph-loop/steps/step-01-task.md +102 -1
- package/templates/skills/ralph-loop/steps/step-04-check.md +87 -40
package/package.json
CHANGED
|
@@ -209,7 +209,7 @@ When step-00 detects that the description matches an existing application:
|
|
|
209
209
|
| 04c | `steps/step-04c-decide.md` | Opus | Final approval, write consolidation, proceed to handoff |
|
|
210
210
|
| 05a | `steps/step-05a-handoff.md` | Sonnet | Handoff: file mapping (7 categories), BR-to-code mapping, API summary, write handoff |
|
|
211
211
|
| 05b | `steps/step-05b-deploy.md` | Sonnet | Deploy: prd.json, progress.txt, manifest, ba-interactive.html |
|
|
212
|
-
| 05c | `steps/step-05c-ralph-readiness.md` |
|
|
212
|
+
| 05c | `steps/step-05c-ralph-readiness.md` | Opus | ULTRATHINK quality review + ralph readiness gate (MANDATORY) |
|
|
213
213
|
| 06 | `steps/step-06-review.md` | Opus | Apply review corrections, create new version, regenerate all artifacts |
|
|
214
214
|
|
|
215
215
|
</step_files>
|
|
@@ -252,10 +252,10 @@ Load ONLY relevant categories based on feature type:
|
|
|
252
252
|
| -------- | ----------------------------------- | ------------ |
|
|
253
253
|
| schema | `schemas/feature-schema.json` | All steps |
|
|
254
254
|
| spec | `templates/tpl-frd.md` | 02 |
|
|
255
|
-
| handoff | `templates/tpl-handoff.md` |
|
|
255
|
+
| handoff | `templates/tpl-handoff.md` | 05a |
|
|
256
256
|
| suggestions | `patterns/suggestion-catalog.md` | 01 |
|
|
257
|
-
| interactive | `html/ba-interactive.html` | 03d (incremental),
|
|
258
|
-
| mapping | `references/html-data-mapping.md` | 03d,
|
|
257
|
+
| interactive | `html/ba-interactive.html` | 03d (incremental), 05b (final deploy) |
|
|
258
|
+
| mapping | `references/html-data-mapping.md` | 03d, 05b (FEATURE_DATA + EMBEDDED_ARTIFACTS mapping) |
|
|
259
259
|
|
|
260
260
|
</template_files>
|
|
261
261
|
|
|
@@ -374,12 +374,30 @@ If initialization was interrupted:
|
|
|
374
374
|
|
|
375
375
|
1. Check `.business-analyse/config.json` for currentFeature
|
|
376
376
|
2. If feature ID exists, search for feature.json in `docs/business/`
|
|
377
|
-
3. If found, check `metadata.workflow.lastCompletedStep`:
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
377
|
+
3. If found, check status and `metadata.workflow.lastCompletedStep`:
|
|
378
|
+
|
|
379
|
+
**Status-based resume routing (check in this order):**
|
|
380
|
+
|
|
381
|
+
- If status = `"handed-off"` AND `ba-interactive.html` missing:
|
|
382
|
+
→ Resume at `step-05b-deploy.md` (deploy artifacts + HTML)
|
|
383
|
+
→ Display: "Handoff complete but HTML/artifacts missing — deploying..."
|
|
384
|
+
|
|
381
385
|
- If status = `"handed-off"` AND `.ralph/prd-*.json` files missing:
|
|
382
386
|
→ Resume at `step-05b-deploy.md` (only deploy artifacts needed)
|
|
383
|
-
→ Display: "Handoff complete but
|
|
387
|
+
→ Display: "Handoff complete but PRD files missing — deploying..."
|
|
388
|
+
|
|
389
|
+
- If status = `"consolidated"` OR lastCompletedStep = `"step-04-consolidation"`:
|
|
390
|
+
→ Resume directly at `step-05a-handoff.md` (skip steps 00-04)
|
|
391
|
+
→ Display: "Resuming from consolidation — proceeding to handoff..."
|
|
392
|
+
|
|
393
|
+
- If status = `"specified"` AND `metadata.workflow.allModulesSpecified === true`:
|
|
394
|
+
→ Resume at `step-04a-collect.md` (consolidation phase)
|
|
395
|
+
→ Display: "All modules specified — resuming at consolidation..."
|
|
396
|
+
|
|
397
|
+
- If status = `"specified"` AND `metadata.workflow.completedModules.length > 0` AND `metadata.workflow.completedModules.length < metadata.workflow.moduleOrder.length`:
|
|
398
|
+
→ Resume at `step-03a1-setup.md` (continue specifying remaining modules)
|
|
399
|
+
→ Display: "Resuming module specification ({completedCount}/{totalCount})..."
|
|
400
|
+
|
|
384
401
|
- Otherwise: offer to resume from last completed step
|
|
402
|
+
|
|
385
403
|
4. If not found, create fresh feature.json
|
|
@@ -165,6 +165,24 @@ ELSE:
|
|
|
165
165
|
|
|
166
166
|
---
|
|
167
167
|
|
|
168
|
+
### 9g. Anti-Premature-Completion Guard (MANDATORY)
|
|
169
|
+
|
|
170
|
+
> **CRITICAL — NEVER say "the analysis is complete" or "ready for /ralph-loop" at this point.**
|
|
171
|
+
> Step-03d is the END of SPECIFICATION, NOT the end of the BA workflow.
|
|
172
|
+
> Steps 04a → 04b → 04c (consolidation) + 05a → 05b → 05c (handoff) are STILL REQUIRED.
|
|
173
|
+
> Without handoff, /ralph-loop will generate an INCOMPLETE PRD (no frontend, no tests).
|
|
174
|
+
|
|
175
|
+
**FORBIDDEN phrases in step-03d output:**
|
|
176
|
+
- "L'analyse métier est complète" / "The business analysis is complete"
|
|
177
|
+
- "Prêt pour /ralph-loop" / "Ready for /ralph-loop"
|
|
178
|
+
- "Vous pouvez maintenant lancer /ralph-loop"
|
|
179
|
+
- Any variation suggesting the BA is finished or /ralph-loop can be invoked
|
|
180
|
+
|
|
181
|
+
**REQUIRED phrasing:**
|
|
182
|
+
- "Module {name} spécifié. {Remaining} modules restants." (if more modules)
|
|
183
|
+
- "Tous les modules spécifiés. Passage à la consolidation (étapes 04a-04c)..." (if last module)
|
|
184
|
+
- NEVER mention /ralph-loop — only step-05c (ralph readiness) validates the handoff
|
|
185
|
+
|
|
168
186
|
### 10. Module Summary with Roles & Permissions
|
|
169
187
|
|
|
170
188
|
Display comprehensive summary:
|
|
@@ -286,8 +304,23 @@ IF currentModuleIndex < moduleOrder.length:
|
|
|
286
304
|
Load: steps/step-03a1-setup.md
|
|
287
305
|
|
|
288
306
|
IF currentModuleIndex >= moduleOrder.length:
|
|
289
|
-
Display: "═══ Tous les modules spécifiés! Passage à la consolidation... ═══"
|
|
307
|
+
Display: "═══ Tous les modules spécifiés! Passage à la consolidation (04a→04c) puis handoff (05a→05c)... ═══"
|
|
308
|
+
Display: "⚠ NE PAS lancer /ralph-loop — la consolidation et le handoff sont encore nécessaires."
|
|
290
309
|
ba-writer.updateStatus({feature_id}, "specified")
|
|
310
|
+
|
|
311
|
+
// CHECKPOINT: Save progress BEFORE transition (protects against context exhaustion)
|
|
312
|
+
ba-writer.enrichSection({
|
|
313
|
+
featureId: {feature_id},
|
|
314
|
+
section: "metadata.workflow",
|
|
315
|
+
data: {
|
|
316
|
+
lastCompletedStep: "step-03d-validate",
|
|
317
|
+
allModulesSpecified: true
|
|
318
|
+
}
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
// MANDATORY TRANSITION — DO NOT STOP HERE
|
|
322
|
+
// If context is near exhaustion, the checkpoint above ensures the user
|
|
323
|
+
// can resume with /business-analyse and it will route to step-04a automatically.
|
|
291
324
|
Load: steps/step-04a-collect.md
|
|
292
325
|
```
|
|
293
326
|
|
|
@@ -360,10 +360,9 @@ Effort: {total_days} days ({total_hours} hours)
|
|
|
360
360
|
1. Ouvrir ba-interactive.html dans le navigateur
|
|
361
361
|
2. Partager avec les stakeholders pour validation
|
|
362
362
|
3. Si retours --> relancer /business-analyse pour une nouvelle itération
|
|
363
|
-
4. Validation
|
|
363
|
+
4. Validation qualité ULTRATHINK (automatique):
|
|
364
364
|
|
|
365
|
-
|
|
366
|
-
la complétude et l'intégrité avant développement
|
|
365
|
+
→ Lancement automatique de step-05c-ralph-readiness.md...
|
|
367
366
|
|
|
368
367
|
5. Une fois validé, lancer le développement:
|
|
369
368
|
|
|
@@ -376,16 +375,19 @@ Effort: {total_days} days ({total_hours} hours)
|
|
|
376
375
|
|
|
377
376
|
## NEXT STEP
|
|
378
377
|
|
|
379
|
-
**
|
|
378
|
+
**MANDATORY:** Load `steps/step-05c-ralph-readiness.md` — ULTRATHINK quality review & readiness gate.
|
|
379
|
+
|
|
380
|
+
> **This step is NON-NEGOTIABLE.** The BA skill MUST run step-05c before completing.
|
|
381
|
+
> DO NOT skip this step. DO NOT display a "done" message without running step-05c first.
|
|
380
382
|
|
|
381
383
|
This validation ensures:
|
|
382
|
-
-
|
|
384
|
+
- ULTRATHINK deep quality review of the entire BA output
|
|
385
|
+
- All module handoffs are complete and content is coherent
|
|
383
386
|
- PRD files are structurally valid
|
|
384
387
|
- Cross-module references are resolvable
|
|
388
|
+
- Specification quality meets production standards
|
|
385
389
|
- No blocking issues before development
|
|
386
390
|
|
|
387
|
-
User can skip validation and proceed directly to /ralph-loop, but validation is strongly recommended to catch issues early.
|
|
388
|
-
|
|
389
391
|
---
|
|
390
392
|
|
|
391
393
|
## MODE SUPPORT & TROUBLESHOOTING
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: step-05c-ralph-readiness
|
|
3
|
-
description:
|
|
4
|
-
model:
|
|
3
|
+
description: ULTRATHINK quality review + validation gate before ralph-loop
|
|
4
|
+
model: opus
|
|
5
5
|
next_step: null
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
> **Context files:** `_shared.md`
|
|
9
9
|
|
|
10
|
-
# Step 5c: Ralph Readiness Check
|
|
10
|
+
# Step 5c: ULTRATHINK Quality Review & Ralph Readiness Check
|
|
11
11
|
|
|
12
12
|
## MANDATORY EXECUTION RULES
|
|
13
13
|
|
|
14
|
+
- **ALWAYS** use ULTRATHINK mode for the quality review (section 0b)
|
|
14
15
|
- **ALWAYS** run ALL validation checks (NEVER skip)
|
|
15
16
|
- **BLOCKING RULE:** If ANY check fails → STOP, DO NOT proceed to ralph-loop
|
|
16
17
|
- **ALWAYS** provide actionable fix instructions for failures
|
|
@@ -19,7 +20,7 @@ next_step: null
|
|
|
19
20
|
|
|
20
21
|
## YOUR TASK
|
|
21
22
|
|
|
22
|
-
Perform
|
|
23
|
+
Perform a deep ULTRATHINK quality review of the entire business analysis output, then run comprehensive structural validation to ensure readiness for /ralph-loop. This is a **BLOCKING** gate — all checks must pass before development can proceed.
|
|
23
24
|
|
|
24
25
|
---
|
|
25
26
|
|
|
@@ -31,9 +32,177 @@ Display validation banner:
|
|
|
31
32
|
|
|
32
33
|
```
|
|
33
34
|
═══════════════════════════════════════════════════════════════
|
|
34
|
-
RALPH READINESS CHECK
|
|
35
|
+
ULTRATHINK QUALITY REVIEW & RALPH READINESS CHECK
|
|
36
|
+
{application_name}
|
|
35
37
|
═══════════════════════════════════════════════════════════════
|
|
36
|
-
|
|
38
|
+
Phase 1: Deep quality review (ULTRATHINK)...
|
|
39
|
+
Phase 2: Structural validation (8 checks)...
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### 0b. ULTRATHINK Deep Quality Review (MANDATORY)
|
|
45
|
+
|
|
46
|
+
> **This section MUST be executed in ULTRATHINK mode.**
|
|
47
|
+
> Take the time to deeply analyze the ENTIRE business analysis output.
|
|
48
|
+
> This is the last chance to catch quality issues before development begins.
|
|
49
|
+
|
|
50
|
+
**Objective:** Perform a thorough, deep-thinking review of the business analysis quality — not just structural checks, but semantic coherence, completeness, and production-readiness.
|
|
51
|
+
|
|
52
|
+
**Process:**
|
|
53
|
+
|
|
54
|
+
1. **Read ALL module feature.json files** (master + each module)
|
|
55
|
+
2. **Activate ULTRATHINK** and analyze the following 6 dimensions:
|
|
56
|
+
|
|
57
|
+
#### Dimension 1: Specification Coherence
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
For EACH module:
|
|
61
|
+
- Do use cases (UCs) tell a coherent story?
|
|
62
|
+
- Are functional requirements (FRs) logically derived from UCs?
|
|
63
|
+
- Do business rules (BRs) cover all edge cases mentioned in UCs?
|
|
64
|
+
- Are gherkin scenarios testing the RIGHT behaviors (not trivial CRUD)?
|
|
65
|
+
- Do entity relationships make domain sense?
|
|
66
|
+
|
|
67
|
+
Flag: Orphan FRs (not linked to any UC), UCs with no FR coverage,
|
|
68
|
+
BRs that don't map to any entity/field
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Dimension 2: Permission & Security Model
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
For EACH module:
|
|
75
|
+
- Is the permission hierarchy logical? (admin > manager > contributor > viewer)
|
|
76
|
+
- Are there actions that should be restricted but aren't?
|
|
77
|
+
- Do API endpoints all have permissions assigned?
|
|
78
|
+
- Are there over-permissive roles? (e.g., contributor with delete access)
|
|
79
|
+
- Cross-module: can a user in Module A access data in Module B through indirect routes?
|
|
80
|
+
|
|
81
|
+
Flag: Endpoints without permissions, roles with excessive access,
|
|
82
|
+
missing permission paths
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### Dimension 3: Data Model Integrity
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
For EACH module:
|
|
89
|
+
- Are all entity relationships bidirectional where needed?
|
|
90
|
+
- Are FK references correct (target entity exists, correct field type)?
|
|
91
|
+
- Are there missing audit fields (CreatedAt, UpdatedAt, CreatedBy)?
|
|
92
|
+
- Do lifecycle states cover all business scenarios?
|
|
93
|
+
- Are cascade delete/update rules safe? (no orphan risk)
|
|
94
|
+
|
|
95
|
+
Cross-module:
|
|
96
|
+
- Are shared entity references correct?
|
|
97
|
+
- Is the dependency graph honest? (no hidden dependencies)
|
|
98
|
+
|
|
99
|
+
Flag: Missing relationships, unsafe cascades, missing audit fields,
|
|
100
|
+
hidden cross-module dependencies
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Dimension 4: UI/UX Completeness
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
For EACH module:
|
|
107
|
+
- Does every section have at least one wireframe?
|
|
108
|
+
- Do wireframes cover ALL use cases? (no UC without UI representation)
|
|
109
|
+
- Are navigation entries correct and complete?
|
|
110
|
+
- Do wireframe actions map to real API endpoints?
|
|
111
|
+
- Are form fields aligned with entity attributes?
|
|
112
|
+
- Are validation rules defined for all user-input fields?
|
|
113
|
+
|
|
114
|
+
Flag: UCs with no wireframe, wireframes with unmapped actions,
|
|
115
|
+
missing form validations, navigation gaps
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Dimension 5: i18n & Messages Quality
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
For EACH module:
|
|
122
|
+
- Are all user-facing strings covered by i18n keys?
|
|
123
|
+
- Are error messages specific enough? (not generic "Error occurred")
|
|
124
|
+
- Do validation messages reference the field name?
|
|
125
|
+
- Are success/confirmation messages present for all write operations?
|
|
126
|
+
- Are there missing translations in any language?
|
|
127
|
+
|
|
128
|
+
Flag: Generic error messages, missing field-specific validations,
|
|
129
|
+
incomplete language coverage
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Dimension 6: Implementation Feasibility
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
For EACH module:
|
|
136
|
+
- Is the handoff.filesToCreate list realistic? (no missing files, no impossible paths)
|
|
137
|
+
- Do brToCodeMapping entries have enough detail for generation?
|
|
138
|
+
- Are API endpoint paths following REST conventions?
|
|
139
|
+
- Are DTO structures aligned with entity attributes?
|
|
140
|
+
- Is the seed data sufficient for testing all use cases?
|
|
141
|
+
- Are there any features that would require infrastructure not in the stack?
|
|
142
|
+
|
|
143
|
+
Flag: Unrealistic file counts, vague BR mappings, non-RESTful routes,
|
|
144
|
+
missing seed data for critical test scenarios
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
3. **Produce Quality Verdict:**
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
═══════════════════════════════════════════════════════════════
|
|
151
|
+
ULTRATHINK QUALITY REVIEW - RESULTS
|
|
152
|
+
═══════════════════════════════════════════════════════════════
|
|
153
|
+
|
|
154
|
+
| Dimension | Score | Issues |
|
|
155
|
+
|-----------|-------|--------|
|
|
156
|
+
| Specification Coherence | A/B/C/D | {count} issues |
|
|
157
|
+
| Permission & Security | A/B/C/D | {count} issues |
|
|
158
|
+
| Data Model Integrity | A/B/C/D | {count} issues |
|
|
159
|
+
| UI/UX Completeness | A/B/C/D | {count} issues |
|
|
160
|
+
| i18n & Messages | A/B/C/D | {count} issues |
|
|
161
|
+
| Implementation Feasibility | A/B/C/D | {count} issues |
|
|
162
|
+
|
|
163
|
+
Overall Quality: {A/B/C/D}
|
|
164
|
+
A = Production-ready (0 critical, ≤3 warnings)
|
|
165
|
+
B = Good (0 critical, >3 warnings)
|
|
166
|
+
C = Needs fixes (1-2 critical issues)
|
|
167
|
+
D = Major rework needed (>2 critical issues)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
4. **Display Issues (if any):**
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
Critical Issues (MUST fix before /ralph-loop):
|
|
174
|
+
✗ [Dimension] Issue description
|
|
175
|
+
→ Fix: Specific action to resolve
|
|
176
|
+
|
|
177
|
+
Warnings (SHOULD fix, not blocking):
|
|
178
|
+
⚠ [Dimension] Issue description
|
|
179
|
+
→ Recommendation: How to improve
|
|
180
|
+
|
|
181
|
+
Suggestions (nice-to-have):
|
|
182
|
+
ℹ [Dimension] Suggestion
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
5. **Decision:**
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
IF overall quality = D:
|
|
189
|
+
BLOCKING ERROR: Major quality issues detected
|
|
190
|
+
→ Return to appropriate step to fix critical issues
|
|
191
|
+
→ DO NOT proceed to structural validation
|
|
192
|
+
|
|
193
|
+
IF overall quality = C:
|
|
194
|
+
Ask via AskUserQuestion:
|
|
195
|
+
question: "Des problèmes de qualité ont été détectés. Comment souhaitez-vous procéder ?"
|
|
196
|
+
header: "Qualité"
|
|
197
|
+
options:
|
|
198
|
+
- label: "Corriger les problèmes critiques"
|
|
199
|
+
description: "Retourner aux étapes concernées pour corriger"
|
|
200
|
+
- label: "Continuer malgré les problèmes"
|
|
201
|
+
description: "Accepter les risques et poursuivre la validation structurelle"
|
|
202
|
+
|
|
203
|
+
IF overall quality = A or B:
|
|
204
|
+
Display: "✓ Quality review passed — proceeding to structural validation..."
|
|
205
|
+
→ Continue to section 1
|
|
37
206
|
```
|
|
38
207
|
|
|
39
208
|
---
|
|
@@ -394,10 +563,11 @@ Progress Tracker Validation:
|
|
|
394
563
|
|
|
395
564
|
**Process:**
|
|
396
565
|
|
|
397
|
-
1. Aggregate all validation results
|
|
566
|
+
1. Aggregate all validation results (quality review + 7 structural checks)
|
|
398
567
|
2. Calculate readiness score:
|
|
399
568
|
```
|
|
400
569
|
passedChecks / totalChecks * 100
|
|
570
|
+
Quality gate: overall quality must be A or B
|
|
401
571
|
```
|
|
402
572
|
|
|
403
573
|
3. Display final report:
|
|
@@ -407,17 +577,23 @@ Progress Tracker Validation:
|
|
|
407
577
|
RALPH READINESS CHECK - COMPLETE
|
|
408
578
|
═══════════════════════════════════════════════════════════════
|
|
409
579
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
580
|
+
ULTRATHINK Quality Review:
|
|
581
|
+
Quality Score: {A/B} — {Production-ready / Good}
|
|
582
|
+
Dimensions: {6/6 reviewed}
|
|
583
|
+
Critical issues: {0}
|
|
584
|
+
Warnings: {count}
|
|
585
|
+
|
|
586
|
+
Structural Validation Summary:
|
|
587
|
+
✓ Module status validation: PASS ({n}/{n} modules)
|
|
588
|
+
✓ PRD files validation: PASS ({n}/{n} files)
|
|
589
|
+
✓ Dependency graph validation: PASS ({n} edges)
|
|
590
|
+
✓ Cross-module references validation: PASS ({n} references)
|
|
591
|
+
✓ Handoff completeness check: PASS ({n}/{n} modules)
|
|
592
|
+
⚠ i18n keys validation: WARNING ({n} missing translation)
|
|
417
593
|
✓ Master feature validation: PASS
|
|
418
594
|
✓ Progress tracker validation: PASS
|
|
419
595
|
|
|
420
|
-
Readiness Score: 100% (
|
|
596
|
+
Readiness Score: 100% (8/8 checks passed, {n} warnings)
|
|
421
597
|
|
|
422
598
|
═══════════════════════════════════════════════════════════════
|
|
423
599
|
|
|
@@ -425,7 +601,7 @@ Status: READY FOR DEVELOPMENT ✓
|
|
|
425
601
|
|
|
426
602
|
Next Steps:
|
|
427
603
|
1. Address warnings (recommended but not blocking):
|
|
428
|
-
-
|
|
604
|
+
- {list warnings from quality review + structural checks}
|
|
429
605
|
|
|
430
606
|
2. Review progress tracker: .ralph/progress.txt
|
|
431
607
|
|
|
@@ -434,14 +610,14 @@ Next Steps:
|
|
|
434
610
|
/ralph-loop -r
|
|
435
611
|
|
|
436
612
|
4. Ralph-loop will:
|
|
437
|
-
- Process modules in topological order: [
|
|
438
|
-
- Generate
|
|
439
|
-
- Execute
|
|
613
|
+
- Process modules in topological order: [{module list}]
|
|
614
|
+
- Generate {n} files across 7 layers
|
|
615
|
+
- Execute {n} tasks tracked in progress.txt
|
|
440
616
|
|
|
441
617
|
═══════════════════════════════════════════════════════════════
|
|
442
618
|
```
|
|
443
619
|
|
|
444
|
-
**IF readiness score < 100% (critical checks failed):**
|
|
620
|
+
**IF readiness score < 100% OR quality = C/D (critical checks failed):**
|
|
445
621
|
|
|
446
622
|
```
|
|
447
623
|
═══════════════════════════════════════════════════════════════
|
|
@@ -450,21 +626,24 @@ Next Steps:
|
|
|
450
626
|
|
|
451
627
|
Status: NOT READY FOR DEVELOPMENT ✗
|
|
452
628
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
-
|
|
629
|
+
{IF quality = C/D:}
|
|
630
|
+
Quality Issues Found:
|
|
631
|
+
✗ ULTRATHINK quality review: {C/D} — {Needs fixes / Major rework}
|
|
632
|
+
- {List critical quality issues from section 0b}
|
|
633
|
+
- Fix: Return to appropriate step (see quality review details above)
|
|
457
634
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
635
|
+
{IF structural checks failed:}
|
|
636
|
+
Structural Issues Found:
|
|
637
|
+
✗ {check name}: FAIL ({details})
|
|
638
|
+
- {specific issue}
|
|
639
|
+
- Fix: {specific action}
|
|
461
640
|
|
|
462
641
|
Required Actions:
|
|
463
642
|
1. Fix all critical issues listed above
|
|
464
643
|
2. Re-run validation: load step-05c-ralph-readiness.md
|
|
465
|
-
3. Only proceed to /ralph-loop when all
|
|
644
|
+
3. Only proceed to /ralph-loop when all checks pass AND quality ≥ B
|
|
466
645
|
|
|
467
|
-
DO NOT PROCEED TO /ralph-loop UNTIL ALL
|
|
646
|
+
DO NOT PROCEED TO /ralph-loop UNTIL ALL CHECKS PASS
|
|
468
647
|
═══════════════════════════════════════════════════════════════
|
|
469
648
|
```
|
|
470
649
|
|
|
@@ -474,22 +653,25 @@ DO NOT PROCEED TO /ralph-loop UNTIL ALL CRITICAL CHECKS PASS
|
|
|
474
653
|
|
|
475
654
|
Before displaying final report, VERIFY:
|
|
476
655
|
|
|
477
|
-
1. **
|
|
478
|
-
2. **
|
|
479
|
-
3. **
|
|
480
|
-
4. **
|
|
481
|
-
5. **
|
|
482
|
-
6. **
|
|
656
|
+
1. **ULTRATHINK quality review executed** (6 dimensions analyzed)
|
|
657
|
+
2. **Quality verdict displayed** with scores per dimension
|
|
658
|
+
3. **ALL 8 structural validation checks executed** (never skip)
|
|
659
|
+
4. **Results clearly marked** (PASS/FAIL/WARNING)
|
|
660
|
+
5. **Actionable fixes provided** for all failures
|
|
661
|
+
6. **Readiness score calculated** correctly
|
|
662
|
+
7. **Next steps displayed** with exact commands
|
|
663
|
+
8. **Blocking errors prevent progression** (no false positives)
|
|
483
664
|
|
|
484
665
|
---
|
|
485
666
|
|
|
486
667
|
## SUCCESS CRITERIA
|
|
487
668
|
|
|
488
|
-
-
|
|
669
|
+
- ULTRATHINK quality review completed with overall score A or B
|
|
670
|
+
- All 8 critical validation checks executed (quality review + 7 structural)
|
|
489
671
|
- Clear PASS/FAIL/WARNING status for each check
|
|
490
672
|
- Readiness score displayed (100% = all critical checks passed)
|
|
491
673
|
- Actionable fix instructions for all failures
|
|
492
|
-
- User can proceed to /ralph-loop only if readiness score = 100%
|
|
674
|
+
- User can proceed to /ralph-loop only if readiness score = 100% AND quality ≥ B
|
|
493
675
|
- Warnings documented but not blocking
|
|
494
676
|
|
|
495
677
|
---
|
|
@@ -498,6 +680,7 @@ Before displaying final report, VERIFY:
|
|
|
498
680
|
|
|
499
681
|
**Why this gate matters:**
|
|
500
682
|
|
|
683
|
+
- **ULTRATHINK catches semantic issues** that structural checks miss (orphan UCs, incoherent permissions, missing UI flows)
|
|
501
684
|
- Prevents incomplete handoffs from reaching development
|
|
502
685
|
- Catches structural issues early (PRD validation)
|
|
503
686
|
- Verifies cross-module integrity before code generation
|
|
@@ -506,8 +689,7 @@ Before displaying final report, VERIFY:
|
|
|
506
689
|
|
|
507
690
|
**When to run this gate:**
|
|
508
691
|
|
|
509
|
-
- Automatically at end of step-05b-deploy.md (
|
|
510
|
-
- Manually before /ralph-loop if user wants to verify
|
|
692
|
+
- **Automatically at end of step-05b-deploy.md (MANDATORY)**
|
|
511
693
|
- After fixing any handoff issues to re-validate
|
|
512
694
|
|
|
513
695
|
**What happens if checks fail:**
|
|
@@ -515,4 +697,4 @@ Before displaying final report, VERIFY:
|
|
|
515
697
|
- Development is BLOCKED until issues are fixed
|
|
516
698
|
- User returns to appropriate step to fix issues
|
|
517
699
|
- Re-run validation after fixes
|
|
518
|
-
- Only proceed when all critical checks pass
|
|
700
|
+
- Only proceed when all critical checks pass AND quality review passes
|
|
@@ -95,8 +95,41 @@ LOAD → GENERATE → COMPILE → TEST → [FAIL?] → FIX → RE-TEST → [PASS
|
|
|
95
95
|
- `scaffold_tests` — test generation
|
|
96
96
|
</mcp_requirements>
|
|
97
97
|
|
|
98
|
+
<execution_guarantee>
|
|
99
|
+
|
|
100
|
+
## EXECUTION GUARANTEE — READ THIS FIRST
|
|
101
|
+
|
|
102
|
+
**Ralph-loop executes ALL tasks from start to finish. No exceptions.**
|
|
103
|
+
|
|
104
|
+
When the user invokes `/ralph-loop`, they are giving you the instruction to:
|
|
105
|
+
1. Initialize the loop (step-00)
|
|
106
|
+
2. Load ALL tasks (step-01)
|
|
107
|
+
3. Execute the FIRST task (step-02)
|
|
108
|
+
4. Commit (step-03)
|
|
109
|
+
5. Enter the COMPACT LOOP (step-04 → compact-loop.md)
|
|
110
|
+
6. **Execute ALL remaining tasks autonomously** (compact loop repeats)
|
|
111
|
+
7. Generate the final report (step-05)
|
|
112
|
+
|
|
113
|
+
**You MUST NOT:**
|
|
114
|
+
- Stop after the first task to "ask for confirmation"
|
|
115
|
+
- Set `max_iterations = 1` or any reduced value
|
|
116
|
+
- Ask the user to choose between supervised/autonomous mode
|
|
117
|
+
- Ask the user to choose a completion promise
|
|
118
|
+
- Wait for user input between iterations
|
|
119
|
+
- Delegate the loop to sub-agents (except team mode)
|
|
120
|
+
|
|
121
|
+
**The ONLY valid stop conditions are:**
|
|
122
|
+
- ALL tasks completed (→ step-05 report)
|
|
123
|
+
- `max_iterations` reached (user set via `-m N`)
|
|
124
|
+
- Dead-end (all remaining blocked/failed)
|
|
125
|
+
- User Ctrl+C
|
|
126
|
+
|
|
127
|
+
**If you stop for any other reason, you have VIOLATED this guarantee.**
|
|
128
|
+
|
|
129
|
+
</execution_guarantee>
|
|
130
|
+
|
|
98
131
|
<entry_point>
|
|
99
|
-
**FIRST ACTION:** Load `steps/step-00-init.md`
|
|
132
|
+
**FIRST ACTION:** Load `steps/step-00-init.md` — then execute ALL steps through to step-05 without stopping.
|
|
100
133
|
</entry_point>
|
|
101
134
|
|
|
102
135
|
<step_files>
|
|
@@ -134,6 +167,13 @@ LOAD → GENERATE → COMPILE → TEST → [FAIL?] → FIX → RE-TEST → [PASS
|
|
|
134
167
|
|
|
135
168
|
<execution_rules>
|
|
136
169
|
|
|
170
|
+
### NON-NEGOTIABLE — Autonomous Full Execution
|
|
171
|
+
- **EXECUTE ALL TASKS** — from first to last, no user interaction, no pause, no confirmation
|
|
172
|
+
- **NEVER ask the user** — no mode selection, no completion promise choice, no "shall I continue?"
|
|
173
|
+
- **NEVER stop after first task** — the first task is just the beginning, NOT the end
|
|
174
|
+
- **NEVER set max_iterations = 1** — unless the user explicitly passed `-m 1`
|
|
175
|
+
|
|
176
|
+
### Loop Mechanics
|
|
137
177
|
- **Single module:** Main agent runs compact loop (NEVER delegate to sub-agent)
|
|
138
178
|
- **Multi-module (2+):** Team lead + module workers via TeamCreate (see references/team-orchestration.md)
|
|
139
179
|
- **Load step files ONCE** — after first iteration, use compact-loop.md
|
|
@@ -141,13 +141,86 @@ Rules:
|
|
|
141
141
|
- DTOs separate from domain entities
|
|
142
142
|
- Service interfaces in Application, implementations in Infrastructure
|
|
143
143
|
|
|
144
|
-
**Tenant isolation (BLOCKING):**
|
|
144
|
+
**Tenant isolation (BLOCKING — SECURITY CRITICAL):**
|
|
145
|
+
|
|
146
|
+
> **ROOT CAUSE (test-v4-005):** Services were generated WITHOUT TenantId filtering,
|
|
147
|
+
> creating cross-tenant data leakage on ALL 70+ CRUD endpoints.
|
|
148
|
+
> This is an OWASP A01 (Broken Access Control) vulnerability.
|
|
149
|
+
|
|
145
150
|
- ALL queries on tenant entities MUST include `.Where(x => x.TenantId == _currentUser.TenantId)`
|
|
146
151
|
- ALL entity creation MUST pass `_currentUser.TenantId` as first parameter to `Entity.Create(tenantId, ...)`
|
|
147
152
|
- NEVER use `new Entity { }` without `TenantId =` — always prefer factory method `Entity.Create()`
|
|
148
153
|
- NEVER use `Guid.Empty` as a placeholder for userId, tenantId, or any business identifier
|
|
149
154
|
- Service constructor MUST inject `ICurrentUserService _currentUser` to access TenantId
|
|
150
155
|
|
|
156
|
+
**MANDATORY Service Template (use as skeleton for ALL services):**
|
|
157
|
+
|
|
158
|
+
```csharp
|
|
159
|
+
public class {Entity}Service : I{Entity}Service
|
|
160
|
+
{
|
|
161
|
+
private readonly IExtensionsDbContext _db;
|
|
162
|
+
private readonly ICurrentUserService _currentUser;
|
|
163
|
+
|
|
164
|
+
public {Entity}Service(IExtensionsDbContext db, ICurrentUserService currentUser)
|
|
165
|
+
{
|
|
166
|
+
_db = db;
|
|
167
|
+
_currentUser = currentUser;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public async Task<PagedResult<{Entity}Response>> GetAllAsync(/* filters */, CancellationToken ct)
|
|
171
|
+
{
|
|
172
|
+
var tenantId = _currentUser.TenantId;
|
|
173
|
+
var query = _db.{Entities}
|
|
174
|
+
.Where(x => x.TenantId == tenantId) // ← MANDATORY tenant filter
|
|
175
|
+
.AsQueryable();
|
|
176
|
+
// ... apply filters, pagination, projection to Response DTO
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public async Task<{Entity}Response?> GetByIdAsync(Guid id, CancellationToken ct)
|
|
180
|
+
{
|
|
181
|
+
var tenantId = _currentUser.TenantId;
|
|
182
|
+
var entity = await _db.{Entities}
|
|
183
|
+
.Where(x => x.TenantId == tenantId) // ← MANDATORY tenant filter
|
|
184
|
+
.FirstOrDefaultAsync(x => x.Id == id, ct);
|
|
185
|
+
// ...
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public async Task<{Entity}Response> CreateAsync(Create{Entity}Dto dto, CancellationToken ct)
|
|
189
|
+
{
|
|
190
|
+
var entity = {Entity}.Create(_currentUser.TenantId, /* dto fields */);
|
|
191
|
+
// ← TenantId as FIRST parameter
|
|
192
|
+
_db.{Entities}.Add(entity);
|
|
193
|
+
await _db.SaveChangesAsync(ct);
|
|
194
|
+
return MapToResponse(entity);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
public async Task<{Entity}Response> UpdateAsync(Guid id, Update{Entity}Dto dto, CancellationToken ct)
|
|
198
|
+
{
|
|
199
|
+
var entity = await _db.{Entities}
|
|
200
|
+
.Where(x => x.TenantId == _currentUser.TenantId) // ← MANDATORY
|
|
201
|
+
.FirstOrDefaultAsync(x => x.Id == id, ct)
|
|
202
|
+
?? throw new NotFoundException(nameof({Entity}), id);
|
|
203
|
+
// ... update fields
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public async Task DeleteAsync(Guid id, CancellationToken ct)
|
|
207
|
+
{
|
|
208
|
+
var entity = await _db.{Entities}
|
|
209
|
+
.Where(x => x.TenantId == _currentUser.TenantId) // ← MANDATORY
|
|
210
|
+
.FirstOrDefaultAsync(x => x.Id == id, ct)
|
|
211
|
+
?? throw new NotFoundException(nameof({Entity}), id);
|
|
212
|
+
// ...
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private static {Entity}Response MapToResponse({Entity} entity) => new()
|
|
216
|
+
{
|
|
217
|
+
// Map entity fields to response DTO
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**POST-CHECK after writing ANY service:** Grep the file for `TenantId`. If 0 occurrences → FAIL, rewrite with tenant filtering.
|
|
223
|
+
|
|
151
224
|
**Lifecycle-aware services:**
|
|
152
225
|
- Services operating on entities with a `lifeCycle` (status field) MUST validate entity state before mutations
|
|
153
226
|
- Example: `if (entity.Status == EmployeeStatus.Terminated) throw new BusinessException("Cannot update terminated employee")`
|
|
@@ -161,6 +234,22 @@ Rules:
|
|
|
161
234
|
- DependencyInjection.cs MUST NOT be empty or contain only TODO comments
|
|
162
235
|
- After writing validators, VERIFY DI registration exists — if missing, add it immediately
|
|
163
236
|
|
|
237
|
+
**POST-CHECK after writing validators:**
|
|
238
|
+
```bash
|
|
239
|
+
# Count Create validators vs Update validators
|
|
240
|
+
CREATE_COUNT=$(find . -path "*/Validators/*" -name "Create*Validator.cs" | wc -l)
|
|
241
|
+
UPDATE_COUNT=$(find . -path "*/Validators/*" -name "Update*Validator.cs" | wc -l)
|
|
242
|
+
if [ "$CREATE_COUNT" -ne "$UPDATE_COUNT" ]; then
|
|
243
|
+
echo "VALIDATOR MISMATCH: $CREATE_COUNT Create vs $UPDATE_COUNT Update → MUST be equal"
|
|
244
|
+
# List missing UpdateValidators and CREATE them
|
|
245
|
+
fi
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Mapper pattern (DRY):**
|
|
249
|
+
- Each service MUST include a `private static {Entity}Response MapToResponse({Entity} entity)` method
|
|
250
|
+
- For complex mappings with related entities, use an extension method in `Application/Mappings/{Module}Mappings.cs`
|
|
251
|
+
- NEVER duplicate mapping logic between GetAll, GetById, Create, Update — always call MapToResponse
|
|
252
|
+
|
|
164
253
|
**FORBIDDEN:**
|
|
165
254
|
- Empty DependencyInjection.cs with `// TODO` placeholder
|
|
166
255
|
- CreateValidator without matching UpdateValidator
|
|
@@ -169,6 +258,7 @@ Rules:
|
|
|
169
258
|
- `new Entity { }` without TenantId assignment
|
|
170
259
|
- `Guid.Empty` as a business value in services or controllers
|
|
171
260
|
- Entity.Create() without tenantId as first parameter
|
|
261
|
+
- Duplicated mapping logic (entity→response) in multiple methods
|
|
172
262
|
|
|
173
263
|
---
|
|
174
264
|
|
|
@@ -280,9 +370,13 @@ useXxx with raw axios inside hooks → hooks MUST use the shared apiCl
|
|
|
280
370
|
|
|
281
371
|
**MCP:** `scaffold_tests`, `analyze_test_coverage`
|
|
282
372
|
|
|
373
|
+
> **CRITICAL:** Test generation is a MANDATORY category. If the PRD has no test tasks,
|
|
374
|
+
> the category completeness check (step-01 section 4b) will inject a guardrail task.
|
|
375
|
+
> Test projects MUST be created as the FIRST action in this category — before generating any test files.
|
|
376
|
+
|
|
283
377
|
**Execution sequence:**
|
|
284
378
|
|
|
285
|
-
1. **Ensure test projects exist:**
|
|
379
|
+
1. **Ensure test projects exist (FIRST — before any test generation):**
|
|
286
380
|
```bash
|
|
287
381
|
# Unit test project
|
|
288
382
|
UNIT_TEST_PROJECT="tests/${PROJECT_NAME}.Tests.Unit"
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# Compact Loop — Inline Execution
|
|
2
2
|
|
|
3
3
|
> **Loaded by:** step-04 section 5 (after first full iteration)
|
|
4
|
-
> **Purpose:** Execute
|
|
5
|
-
> **
|
|
4
|
+
> **Purpose:** Execute ALL remaining tasks autonomously without stopping.
|
|
5
|
+
> **EXECUTION GUARANTEE:** This loop runs until ALL tasks are done, max iterations, or dead-end.
|
|
6
|
+
> **ABSOLUTE RULES:**
|
|
7
|
+
> - NEVER stop the loop
|
|
8
|
+
> - NEVER wait for user input
|
|
9
|
+
> - NEVER ask for confirmation
|
|
10
|
+
> - NEVER re-read step files
|
|
11
|
+
> - NEVER pause between iterations
|
|
12
|
+
> - Execute A → B → C → D → back to step-04 section 1 → repeat
|
|
6
13
|
|
|
7
14
|
---
|
|
8
15
|
|
|
@@ -208,10 +215,49 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
|
|
|
208
215
|
|
|
209
216
|
## C. Commit Batch
|
|
210
217
|
|
|
218
|
+
### C1. Update PRD Status (MANDATORY — BEFORE git commit)
|
|
219
|
+
|
|
220
|
+
> **CRITICAL:** PRD status MUST be updated BEFORE committing.
|
|
221
|
+
> In test-v4-005, the compact loop executed 44 tasks but NEVER updated prd.json status.
|
|
222
|
+
> This broke ALL downstream guardrails (module completeness check never triggered).
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
const now = new Date().toISOString();
|
|
226
|
+
const COMMIT_HASH_PENDING = 'pending-commit'; // Updated after git commit
|
|
227
|
+
|
|
228
|
+
for (const task of batch) {
|
|
229
|
+
if (task.status !== 'failed') task.status = 'completed';
|
|
230
|
+
task.completed_at = now;
|
|
231
|
+
task.iteration = prd.config.current_iteration;
|
|
232
|
+
task.commit_hash = COMMIT_HASH_PENDING;
|
|
233
|
+
}
|
|
234
|
+
prd.config.current_iteration++;
|
|
235
|
+
prd.updated_at = now;
|
|
236
|
+
writeJSON('.ralph/prd.json', prd);
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### C2. Update Progress File (MANDATORY)
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
const completed = prd.tasks.filter(t => t.status === 'completed').length;
|
|
243
|
+
const total = prd.tasks.length;
|
|
244
|
+
const moduleName = prd.project?.module || 'unknown';
|
|
245
|
+
|
|
246
|
+
// Append to progress.txt (NOT overwrite)
|
|
247
|
+
appendFile('.ralph/progress.txt',
|
|
248
|
+
`Iteration ${prd.config.current_iteration - 1}: ${batch.map(t => t.id).join('/')} COMPLETED — ` +
|
|
249
|
+
`${batch[0].category} (${batch.length} tasks). ${completed}/${total} done.\n` +
|
|
250
|
+
` Files: ${batch.reduce((acc, t) => acc + (t.files_changed?.created?.length || 0), 0)} created\n`
|
|
251
|
+
);
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### C3. Git Commit
|
|
255
|
+
|
|
211
256
|
```bash
|
|
212
257
|
# Stage all changed files from batch
|
|
213
258
|
git add {all_files_from_batch}
|
|
214
|
-
git add .ralph/prd.json
|
|
259
|
+
git add .ralph/prd.json .ralph/progress.txt
|
|
260
|
+
[ -f .ralph/modules-queue.json ] && git add .ralph/modules-queue.json
|
|
215
261
|
|
|
216
262
|
git commit -m "$(cat <<'EOF'
|
|
217
263
|
feat({scope}): [{category}] {batch.length} tasks — {short summary}
|
|
@@ -227,44 +273,59 @@ EOF
|
|
|
227
273
|
COMMIT_HASH=$(git rev-parse --short HEAD)
|
|
228
274
|
```
|
|
229
275
|
|
|
230
|
-
|
|
276
|
+
### C4. Finalize PRD with Commit Hash
|
|
277
|
+
|
|
231
278
|
```javascript
|
|
232
|
-
|
|
279
|
+
// Update commit hash now that we have the real one
|
|
233
280
|
for (const task of batch) {
|
|
234
|
-
if (task.
|
|
235
|
-
task.completed_at = now;
|
|
236
|
-
task.iteration = prd.config.current_iteration;
|
|
237
|
-
task.commit_hash = COMMIT_HASH;
|
|
281
|
+
if (task.commit_hash === 'pending-commit') task.commit_hash = COMMIT_HASH;
|
|
238
282
|
}
|
|
239
283
|
prd.history.push({
|
|
240
|
-
iteration: prd.config.current_iteration,
|
|
284
|
+
iteration: prd.config.current_iteration - 1,
|
|
241
285
|
task_ids: batch.map(t => t.id),
|
|
242
286
|
action: 'batch-completed',
|
|
243
287
|
timestamp: now,
|
|
244
288
|
commit_hash: COMMIT_HASH,
|
|
245
289
|
notes: "{summary}"
|
|
246
290
|
});
|
|
247
|
-
prd.config.current_iteration++;
|
|
248
|
-
prd.updated_at = now;
|
|
249
291
|
writeJSON('.ralph/prd.json', prd);
|
|
250
292
|
```
|
|
251
293
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
294
|
+
### C5. PRD Sync Verification (HARD CHECK)
|
|
295
|
+
|
|
296
|
+
> **MANDATORY:** Verify prd.json reflects reality before looping back.
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
const prdCheck = readJSON('.ralph/prd.json');
|
|
300
|
+
const batchIds = batch.map(t => t.id);
|
|
301
|
+
const actuallyCompleted = prdCheck.tasks.filter(t => batchIds.includes(t.id) && t.status === 'completed');
|
|
302
|
+
|
|
303
|
+
if (actuallyCompleted.length !== batch.filter(t => t.status !== 'failed').length) {
|
|
304
|
+
console.error('PRD SYNC ERROR: Tasks executed but not marked completed in prd.json');
|
|
305
|
+
console.error(`Expected: ${batch.filter(t => t.status !== 'failed').length} completed, Got: ${actuallyCompleted.length}`);
|
|
306
|
+
// Force re-write
|
|
307
|
+
for (const task of batch) {
|
|
308
|
+
const prdTask = prdCheck.tasks.find(t => t.id === task.id);
|
|
309
|
+
if (prdTask && task.status === 'completed') prdTask.status = 'completed';
|
|
310
|
+
if (prdTask) prdTask.commit_hash = COMMIT_HASH;
|
|
311
|
+
}
|
|
312
|
+
writeJSON('.ralph/prd.json', prdCheck);
|
|
313
|
+
console.log('PRD SYNC REPAIRED');
|
|
314
|
+
}
|
|
257
315
|
```
|
|
258
316
|
|
|
259
317
|
---
|
|
260
318
|
|
|
261
|
-
## D. Loop Back
|
|
319
|
+
## D. Loop Back (MANDATORY — NO PAUSE)
|
|
262
320
|
|
|
263
321
|
**IMMEDIATELY return to step-04 section 1 (Read Current State).**
|
|
264
|
-
DO NOT stop. DO NOT wait for user. DO NOT re-read step files.
|
|
265
322
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
-
|
|
269
|
-
|
|
270
|
-
-
|
|
323
|
+
DO NOT stop. DO NOT wait for user. DO NOT ask "should I continue?". DO NOT re-read step files.
|
|
324
|
+
DO NOT display a summary and pause. DO NOT output partial results and wait.
|
|
325
|
+
**Go directly to step-04 section 1. NOW.**
|
|
326
|
+
|
|
327
|
+
The ONLY exit conditions (enforced by step-04 sections 2-4):
|
|
328
|
+
- ALL tasks complete (all modules if multi-module) → step-05
|
|
329
|
+
- Max iterations reached → step-05
|
|
330
|
+
- Dead-end (all remaining blocked/failed) → step-05
|
|
331
|
+
- User Ctrl+C (external interrupt)
|
|
@@ -8,9 +8,12 @@ next_step: steps/step-01-task.md
|
|
|
8
8
|
|
|
9
9
|
## MANDATORY RULES:
|
|
10
10
|
|
|
11
|
+
- **FULLY AUTONOMOUS** — execute ALL tasks without stopping or asking the user
|
|
11
12
|
- NEVER skip MCP verification
|
|
12
13
|
- ALWAYS parse ALL flags before any action
|
|
13
14
|
- ONLY check resume if -r flag is set
|
|
15
|
+
- **NEVER ask the user** to choose a mode, confirm execution, or select options
|
|
16
|
+
- **NEVER set max_iterations = 1** — unless the user explicitly passed `-m 1`
|
|
14
17
|
- CONTEXT BUDGET: Keep output COMPACT
|
|
15
18
|
- **NEVER DELEGATE** the main Ralph loop to a sub-agent (single module)
|
|
16
19
|
- **Multi-module (2+ modules):** Use Agent Teams for parallel execution
|
|
@@ -48,69 +51,36 @@ mcp__context7__resolve-library-id: libraryName: "test" → {mcp_context7} = tru
|
|
|
48
51
|
|
|
49
52
|
If ANY fails: show error, suggest `smartstack check-mcp`, STOP.
|
|
50
53
|
|
|
51
|
-
## 3.
|
|
54
|
+
## 3. Execution Mode (FULLY AUTONOMOUS)
|
|
52
55
|
|
|
53
|
-
> **
|
|
56
|
+
> **CRITICAL:** Ralph-loop is FULLY AUTONOMOUS by default.
|
|
57
|
+
> It executes ALL tasks from start to finish WITHOUT stopping.
|
|
58
|
+
> The user launched `/ralph-loop` — this IS the instruction to execute everything.
|
|
54
59
|
|
|
55
|
-
|
|
60
|
+
**DO NOT** ask the user to confirm, choose a mode, or approve execution.
|
|
61
|
+
**DO NOT** set `max_iterations = 1` or any reduced value.
|
|
62
|
+
**DO NOT** stop after the first task to "check quality".
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
|
|
62
|
-
**Stratégie recommandée :**
|
|
63
|
-
|
|
64
|
-
1. **Première itération supervisée** - Lancer manuellement la première tâche pour vérifier :
|
|
65
|
-
- La qualité du code généré
|
|
66
|
-
- Le temps d'exécution des tests
|
|
67
|
-
- La clarté des messages d'erreur
|
|
68
|
-
|
|
69
|
-
2. **Mode autonome limité** - Si première itération OK, relancer avec `--max-iterations 5-10`
|
|
70
|
-
|
|
71
|
-
3. **Mode autonome complet** - Une fois confiant, augmenter à `--max-iterations 50`
|
|
72
|
-
|
|
73
|
-
### Checkpoint Prompt (Optional)
|
|
74
|
-
|
|
75
|
-
Si vous détectez que c'est la première utilisation de ralph-loop sur ce projet (pas de `.ralph/logs/`), proposer :
|
|
64
|
+
The loop runs autonomously until:
|
|
65
|
+
- ALL tasks are completed (success)
|
|
66
|
+
- `max_iterations` is reached (user explicitly set via `-m N`)
|
|
67
|
+
- Dead-end detected (all remaining tasks blocked/failed)
|
|
68
|
+
- User Ctrl+C (external interrupt)
|
|
76
69
|
|
|
77
70
|
```javascript
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
header: "Mode",
|
|
83
|
-
multiSelect: false,
|
|
84
|
-
options: [
|
|
85
|
-
{ label: "Supervisé (recommandé)", description: "Exécuter 1 tâche, puis demander confirmation" },
|
|
86
|
-
{ label: "Autonome limité", description: "Max 10 itérations automatiques" },
|
|
87
|
-
{ label: "Autonome complet", description: "Jusqu'à 50 itérations (mode AFK)" }
|
|
88
|
-
]
|
|
89
|
-
}]
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
if (answer === "Supervisé") {
|
|
93
|
-
max_iterations = 1;
|
|
94
|
-
console.log("Mode supervisé : 1 tâche sera exécutée. Relancez avec -r pour continuer.");
|
|
95
|
-
} else if (answer === "Autonome limité") {
|
|
96
|
-
max_iterations = Math.min(max_iterations, 10);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
71
|
+
// NO user prompt. NO mode selection. JUST EXECUTE.
|
|
72
|
+
// max_iterations is already set from flags (default: 50).
|
|
73
|
+
// If user wants fewer iterations, they use -m N explicitly.
|
|
74
|
+
console.log(`Mode: AUTONOMOUS | Max iterations: ${max_iterations}`);
|
|
99
75
|
```
|
|
100
76
|
|
|
101
|
-
###
|
|
102
|
-
|
|
103
|
-
⚠️ **IMPORTANT :** Si vos tests prennent >30 secondes, ralph-loop peut devenir inefficace.
|
|
77
|
+
### Speed Warning (informational only — does NOT block)
|
|
104
78
|
|
|
79
|
+
If tests are slow (>30s detected in previous logs), display a one-line warning but **continue execution**:
|
|
105
80
|
```
|
|
106
|
-
|
|
107
|
-
- Unitaires : <5s
|
|
108
|
-
- Intégration : <15s
|
|
109
|
-
- E2E : <30s (à exécuter en dehors du loop)
|
|
81
|
+
⚠ Slow tests detected. Consider disabling E2E during ralph-loop.
|
|
110
82
|
```
|
|
111
83
|
|
|
112
|
-
Si tests lents détectés (via logs), avertir l'utilisateur et suggérer de désactiver tests E2E pendant le loop.
|
|
113
|
-
|
|
114
84
|
## 4. Resume Mode
|
|
115
85
|
|
|
116
86
|
If `{resume_mode} = true`:
|
|
@@ -213,9 +183,15 @@ if (PRD_COUNT > 1) {
|
|
|
213
183
|
}
|
|
214
184
|
```
|
|
215
185
|
|
|
216
|
-
## 5. Completion Promise
|
|
186
|
+
## 5. Completion Promise (auto-set)
|
|
217
187
|
|
|
218
|
-
|
|
188
|
+
```javascript
|
|
189
|
+
// Auto-set if not provided — NEVER ask the user
|
|
190
|
+
if (!completion_promise) {
|
|
191
|
+
completion_promise = "COMPLETE";
|
|
192
|
+
}
|
|
193
|
+
// The promise is output ONLY when ALL tasks are done. No user interaction needed.
|
|
194
|
+
```
|
|
219
195
|
|
|
220
196
|
## 6. Collect Metadata
|
|
221
197
|
|
|
@@ -94,11 +94,62 @@ If `.ralph/prd.json` exists:
|
|
|
94
94
|
2. **v3 FAST PATH:** If `$version === "3.0.0"` AND `tasks[]` exists:
|
|
95
95
|
- Inject runtime fields if missing (status, config, feature, created, updated_at, history)
|
|
96
96
|
- Write back to `.ralph/prd.json`
|
|
97
|
+
- **Run CATEGORY COMPLETENESS CHECK (section 4b) before proceeding**
|
|
97
98
|
- Skip directly to section 5 (find next task)
|
|
98
99
|
3. **v2 legacy:** If `$version === "2.0.0"` → find next eligible task (section 5), skip to section 5
|
|
99
100
|
4. **FORMAT A (deprecated):** If `.project && .requirements && !.$version` → run `transformPrdJsonToRalphV2()` → section 5
|
|
100
101
|
|
|
101
|
-
If `.ralph/prd.json` does not exist: continue to section
|
|
102
|
+
If `.ralph/prd.json` does not exist: continue to section 1b.
|
|
103
|
+
|
|
104
|
+
### 1b. BA Handoff Quality Gate (BLOCKING)
|
|
105
|
+
|
|
106
|
+
> **CRITICAL:** Before generating ANY tasks, verify the BA handoff is complete.
|
|
107
|
+
> A missing handoff means no frontend files, no test plan, no BR-to-code mapping.
|
|
108
|
+
> Generating tasks without handoff produces an INCOMPLETE PRD (backend-only).
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// Find the source feature.json for the current module
|
|
112
|
+
const sourceFeatureJson = prd?.metadata?.sourceFeatureJson
|
|
113
|
+
|| findFile('docs/business/**/business-analyse/**/feature.json');
|
|
114
|
+
|
|
115
|
+
if (sourceFeatureJson) {
|
|
116
|
+
const feature = readJSON(sourceFeatureJson);
|
|
117
|
+
const handoff = feature.handoff || {};
|
|
118
|
+
|
|
119
|
+
// CHECK 1: Handoff status must be "handed-off"
|
|
120
|
+
if (handoff.status !== 'handed-off') {
|
|
121
|
+
console.error(`
|
|
122
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
123
|
+
║ BLOCKING: BA HANDOFF INCOMPLETE ║
|
|
124
|
+
║ ║
|
|
125
|
+
║ feature.json handoff.status = "${handoff.status || 'missing'}"
|
|
126
|
+
║ Expected: "handed-off" ║
|
|
127
|
+
║ ║
|
|
128
|
+
║ The /business-analyse did not complete steps 04a→05c. ║
|
|
129
|
+
║ Without handoff, the PRD will be MISSING: ║
|
|
130
|
+
║ - Frontend tasks (pages, components, routes) ║
|
|
131
|
+
║ - Test tasks (unit, integration, security) ║
|
|
132
|
+
║ - BR-to-code mappings ║
|
|
133
|
+
║ - API endpoint summary ║
|
|
134
|
+
║ ║
|
|
135
|
+
║ ACTION: Run /business-analyse to complete the handoff, ║
|
|
136
|
+
║ then re-run /ralph-loop. ║
|
|
137
|
+
╚══════════════════════════════════════════════════════════════╝`);
|
|
138
|
+
STOP;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// CHECK 2: filesToCreate must have all 7 categories
|
|
142
|
+
const filesToCreate = handoff.filesToCreate || {};
|
|
143
|
+
const requiredCategories = ['domain', 'application', 'infrastructure', 'api', 'frontend', 'seedData', 'tests'];
|
|
144
|
+
const missingInHandoff = requiredCategories.filter(c => !filesToCreate[c] || filesToCreate[c].length === 0);
|
|
145
|
+
|
|
146
|
+
if (missingInHandoff.length > 0) {
|
|
147
|
+
console.warn(`⚠ Handoff has empty categories: ${missingInHandoff.join(', ')}`);
|
|
148
|
+
console.warn('PRD generation may produce incomplete tasks. Consider re-running /business-analyse step-05a.');
|
|
149
|
+
// WARNING only — allow proceeding if handoff.status is correct
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
102
153
|
|
|
103
154
|
## 2. Analyze Task Description
|
|
104
155
|
|
|
@@ -128,6 +179,56 @@ Initialize `.ralph/progress.txt`:
|
|
|
128
179
|
- Dependency references are valid (exist, no forward/circular)
|
|
129
180
|
- Task count 3-30
|
|
130
181
|
|
|
182
|
+
### 4b. Category Completeness Check (BLOCKING)
|
|
183
|
+
|
|
184
|
+
> **CRITICAL:** The PRD MUST contain tasks for ALL required categories.
|
|
185
|
+
> A PRD with only backend categories (domain, infrastructure, application, api) is INCOMPLETE.
|
|
186
|
+
> This check prevents the "no frontend generated" failure mode.
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
const REQUIRED_CATEGORIES = ['domain', 'infrastructure', 'application', 'api', 'frontend', 'test'];
|
|
190
|
+
const presentCategories = new Set(prd.tasks.map(t => t.category));
|
|
191
|
+
const missingCategories = REQUIRED_CATEGORIES.filter(c => !presentCategories.has(c));
|
|
192
|
+
|
|
193
|
+
if (missingCategories.length > 0) {
|
|
194
|
+
console.warn(`⚠ PRD MISSING CATEGORIES: ${missingCategories.join(', ')}`);
|
|
195
|
+
|
|
196
|
+
// AUTO-INJECT guardrail tasks for missing categories
|
|
197
|
+
let maxIdNum = Math.max(...prd.tasks.map(t => {
|
|
198
|
+
const num = parseInt(t.id.replace(/[^0-9]/g, ''), 10);
|
|
199
|
+
return isNaN(num) ? 0 : num;
|
|
200
|
+
}));
|
|
201
|
+
const prefix = prd.tasks[0]?.id?.replace(/[0-9]+$/, '') || 'GUARD-';
|
|
202
|
+
const lastBackendTask = prd.tasks.filter(t => t.category === 'api').pop()?.id || prd.tasks[prd.tasks.length - 1]?.id;
|
|
203
|
+
|
|
204
|
+
for (const cat of missingCategories) {
|
|
205
|
+
maxIdNum++;
|
|
206
|
+
const taskId = `${prefix}${String(maxIdNum).padStart(3, '0')}`;
|
|
207
|
+
const guardrailTask = {
|
|
208
|
+
id: taskId,
|
|
209
|
+
description: `[GUARDRAIL] Generate ${cat} layer for ${prd.project?.module || 'module'}`,
|
|
210
|
+
status: 'pending',
|
|
211
|
+
category: cat,
|
|
212
|
+
dependencies: cat === 'test' ? [lastBackendTask] : (cat === 'frontend' ? [lastBackendTask] : []),
|
|
213
|
+
acceptance_criteria: [
|
|
214
|
+
cat === 'frontend' ? 'React pages created via MCP scaffold_api_client + scaffold_routes, wired to App.tsx' :
|
|
215
|
+
cat === 'test' ? 'Unit + Integration test projects created, scaffold_tests MCP called, dotnet test passes' :
|
|
216
|
+
`${cat} layer fully implemented per category-rules.md`
|
|
217
|
+
],
|
|
218
|
+
started_at: null, completed_at: null, iteration: null,
|
|
219
|
+
commit_hash: null, files_changed: [], validation: null, error: null
|
|
220
|
+
};
|
|
221
|
+
prd.tasks.push(guardrailTask);
|
|
222
|
+
console.log(` → Injected guardrail: [${taskId}] ${cat}`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
writeJSON('.ralph/prd.json', prd);
|
|
226
|
+
console.log(`PRD updated: ${prd.tasks.length} tasks (${missingCategories.length} guardrails added)`);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Why this matters:** In test-v4-005, the PRD was generated with only backend categories (domain, infrastructure, application, api, seedData, validation). The frontend and test categories were entirely absent, resulting in 0 frontend pages and 0 tests generated across 3 modules.
|
|
231
|
+
|
|
131
232
|
## 5. Find Current Task
|
|
132
233
|
|
|
133
234
|
```javascript
|
|
@@ -71,6 +71,68 @@ if [ -f "web/package.json" ] || [ -f "package.json" ]; then
|
|
|
71
71
|
fi
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
### 1.7. Category Completeness Check (RUNS EVERY ITERATION)
|
|
75
|
+
|
|
76
|
+
> **CRITICAL:** This check runs REGARDLESS of allDone status.
|
|
77
|
+
> In test-v4-005, allDone was never true (PRD status not updated), so the
|
|
78
|
+
> module completeness check in section 3b never triggered, and missing
|
|
79
|
+
> frontend/test categories were never detected.
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
const presentCategories = new Set(prd.tasks.map(t => t.category));
|
|
83
|
+
const REQUIRED_CATEGORIES = ['domain', 'infrastructure', 'application', 'api', 'frontend', 'test'];
|
|
84
|
+
const missingFromPrd = REQUIRED_CATEGORIES.filter(c => !presentCategories.has(c));
|
|
85
|
+
|
|
86
|
+
if (missingFromPrd.length > 0) {
|
|
87
|
+
console.warn(`⚠ PRD MISSING CATEGORIES: ${missingFromPrd.join(', ')}`);
|
|
88
|
+
|
|
89
|
+
// Inject guardrail tasks for missing categories
|
|
90
|
+
let maxIdNum = Math.max(...prd.tasks.map(t => parseInt(t.id.replace(/[^0-9]/g, ''), 10) || 0));
|
|
91
|
+
const prefix = prd.tasks[0]?.id?.replace(/[0-9]+$/, '') || 'GUARD-';
|
|
92
|
+
const lastApiTask = prd.tasks.filter(t => t.category === 'api').pop()?.id;
|
|
93
|
+
|
|
94
|
+
for (const cat of missingFromPrd) {
|
|
95
|
+
maxIdNum++;
|
|
96
|
+
const taskId = `${prefix}${String(maxIdNum).padStart(3, '0')}`;
|
|
97
|
+
prd.tasks.push({
|
|
98
|
+
id: taskId,
|
|
99
|
+
description: `[GUARDRAIL] Generate missing ${cat} layer for ${prd.project?.module || 'module'}`,
|
|
100
|
+
status: 'pending', category: cat,
|
|
101
|
+
dependencies: lastApiTask ? [lastApiTask] : [],
|
|
102
|
+
acceptance_criteria: [
|
|
103
|
+
cat === 'frontend' ? 'React pages + routes wired to App.tsx (standard + tenant blocks)' :
|
|
104
|
+
cat === 'test' ? 'Unit + integration test projects with passing dotnet test' :
|
|
105
|
+
`${cat} layer complete`
|
|
106
|
+
],
|
|
107
|
+
started_at: null, completed_at: null, iteration: null,
|
|
108
|
+
commit_hash: null, files_changed: [], validation: null, error: null
|
|
109
|
+
});
|
|
110
|
+
console.log(` → Injected [${taskId}] ${cat} guardrail`);
|
|
111
|
+
}
|
|
112
|
+
writeJSON('.ralph/prd.json', prd);
|
|
113
|
+
|
|
114
|
+
// Re-count after injection
|
|
115
|
+
const newPending = prd.tasks.filter(t => t.status === 'pending').length;
|
|
116
|
+
console.log(`PRD updated: +${missingFromPrd.length} guardrails, ${newPending} pending tasks`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Also check: artifact existence for categories with completed tasks
|
|
120
|
+
const completedCats = new Set(prd.tasks.filter(t => t.status === 'completed').map(t => t.category));
|
|
121
|
+
const artifactChecks = {
|
|
122
|
+
'frontend': () => glob.sync('**/src/pages/**/*.tsx').length > 0,
|
|
123
|
+
'test': () => glob.sync('tests/**/*Tests.cs').length > 0,
|
|
124
|
+
'api': () => glob.sync('src/*/Controllers/**/*Controller.cs').length > 0
|
|
125
|
+
};
|
|
126
|
+
for (const [cat, check] of Object.entries(artifactChecks)) {
|
|
127
|
+
if (completedCats.has(cat) && !check()) {
|
|
128
|
+
console.warn(`ARTIFACT MISSING: ${cat} tasks marked completed but no files found — resetting`);
|
|
129
|
+
prd.tasks.filter(t => t.category === cat && t.status === 'completed')
|
|
130
|
+
.forEach(t => { t.status = 'pending'; t.error = 'Artifacts missing — re-execute'; t.completed_at = null; });
|
|
131
|
+
writeJSON('.ralph/prd.json', prd);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
74
136
|
## 2. Check Iteration Limit
|
|
75
137
|
|
|
76
138
|
If `current_iteration > max_iterations`:
|
|
@@ -82,6 +144,13 @@ Set `prd.status = 'partial'` → step-05.
|
|
|
82
144
|
|
|
83
145
|
## 3. Check All Tasks Complete
|
|
84
146
|
|
|
147
|
+
**Re-read state after section 1.7 (categories may have been injected):**
|
|
148
|
+
```javascript
|
|
149
|
+
const tasksCompletedNow = prd.tasks.filter(t => t.status === 'completed').length;
|
|
150
|
+
const tasksTotalNow = prd.tasks.length;
|
|
151
|
+
const allDone = (tasksCompletedNow + prd.tasks.filter(t => t.status === 'skipped').length) === tasksTotalNow;
|
|
152
|
+
```
|
|
153
|
+
|
|
85
154
|
If `allDone`:
|
|
86
155
|
|
|
87
156
|
### 3a. Team Mode (multi-module with Agent Teams)
|
|
@@ -107,42 +176,15 @@ if (fileExists(queuePath)) {
|
|
|
107
176
|
const queue = readJSON(queuePath);
|
|
108
177
|
const currentModule = queue.modules[queue.currentIndex];
|
|
109
178
|
|
|
110
|
-
// MODULE COMPLETENESS CHECK
|
|
179
|
+
// MODULE COMPLETENESS CHECK (lightweight — heavy check already done in section 1.7)
|
|
180
|
+
// Verify all expected layers have completed tasks
|
|
111
181
|
const completedCats = new Set(prd.tasks.filter(t => t.status === 'completed').map(t => t.category));
|
|
112
182
|
const expected = ['domain', 'infrastructure', 'application', 'api', 'frontend', 'test'];
|
|
113
183
|
const missing = expected.filter(c => !completedCats.has(c));
|
|
114
184
|
|
|
115
|
-
// ARTIFACT EXISTENCE CHECK: categories with completed tasks must have real files
|
|
116
|
-
const artifactChecks = {
|
|
117
|
-
'infrastructure': () => fs.existsSync('src/*/Persistence/Migrations') && fs.readdirSync('src/*/Persistence/Migrations').length > 0,
|
|
118
|
-
'test': () => fs.existsSync(`tests/${projectName}.Tests.Unit`) && glob.sync('tests/**/*Tests.cs').length > 0,
|
|
119
|
-
'api': () => glob.sync('src/*/Controllers/**/*Controller.cs').length > 0,
|
|
120
|
-
'frontend': () => glob.sync('**/src/pages/**/*.tsx').length > 0
|
|
121
|
-
};
|
|
122
|
-
for (const [cat, check] of Object.entries(artifactChecks)) {
|
|
123
|
-
if (completedCats.has(cat) && !check()) {
|
|
124
|
-
// Tasks marked completed but artifacts missing — reset to pending
|
|
125
|
-
prd.tasks.filter(t => t.category === cat && t.status === 'completed')
|
|
126
|
-
.forEach(t => { t.status = 'pending'; t.error = 'Artifacts missing — re-execute'; t.completed_at = null; });
|
|
127
|
-
missing.push(cat);
|
|
128
|
-
console.log(`ARTIFACT RESET: ${cat} tasks reset to pending (no files found)`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
185
|
if (missing.length > 0) {
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
for (const cat of missing) {
|
|
136
|
-
maxId++;
|
|
137
|
-
prd.tasks.push({
|
|
138
|
-
id: maxId, description: `[${cat}] GUARDRAIL: Generate missing ${cat} for ${currentModule.code}`,
|
|
139
|
-
status: 'pending', category: cat, dependencies: [],
|
|
140
|
-
acceptance_criteria: `${cat} layer fully implemented`, started_at: null, completed_at: null,
|
|
141
|
-
iteration: null, commit_hash: null, files_changed: { created: [], modified: [] },
|
|
142
|
-
validation: null, error: null, module: currentModule.code
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
writeJSON('.ralph/prd.json', prd);
|
|
186
|
+
// Section 1.7 should have injected guardrails already — fall through to compact loop
|
|
187
|
+
console.log(`Module ${currentModule.code}: missing categories ${missing.join(', ')} — continuing loop`);
|
|
146
188
|
// Fall through to section 5 (compact loop)
|
|
147
189
|
} else {
|
|
148
190
|
// Module complete — advance
|
|
@@ -198,28 +240,33 @@ DEAD-END: {completed} done, {failed} failed, {blocked} blocked
|
|
|
198
240
|
```
|
|
199
241
|
Set `prd.status = 'failed'` → step-05.
|
|
200
242
|
|
|
201
|
-
## 5. Compact Loop (
|
|
243
|
+
## 5. Compact Loop (MANDATORY — EXECUTE IMMEDIATELY)
|
|
202
244
|
|
|
203
|
-
> **
|
|
204
|
-
> DO NOT stop. DO NOT wait for user. DO NOT re-read step files.
|
|
205
|
-
> **Read `references/compact-loop.md` and execute inline.**
|
|
245
|
+
> **THIS IS NOT OPTIONAL.** If there are pending tasks, you MUST enter the compact loop NOW.
|
|
246
|
+
> DO NOT stop. DO NOT wait for user. DO NOT ask for confirmation. DO NOT re-read step files.
|
|
247
|
+
> **Read `references/compact-loop.md` and execute ALL sections inline.**
|
|
248
|
+
> **Stopping here is a VIOLATION of the execution guarantee.**
|
|
206
249
|
|
|
207
250
|
If `hasPending && iteration < max`:
|
|
208
251
|
|
|
209
252
|
1. Read `references/compact-loop.md`
|
|
210
|
-
2. Execute sections A → B → C → D inline
|
|
211
|
-
3.
|
|
253
|
+
2. Execute sections A → B → C → D inline (find tasks → execute batch → commit → loop back)
|
|
254
|
+
3. **IMMEDIATELY** return to section 1 of THIS step (do NOT pause)
|
|
255
|
+
4. Repeat until ALL tasks are complete, max iterations reached, or dead-end
|
|
212
256
|
|
|
213
257
|
---
|
|
214
258
|
|
|
215
|
-
## CRITICAL RULES:
|
|
259
|
+
## CRITICAL RULES — EXECUTION GUARANTEE:
|
|
216
260
|
|
|
217
261
|
- **NEVER** output completion promise unless ALL tasks done (all modules if multi)
|
|
218
262
|
- **NEVER** delegate the loop to sub-agents (except team mode for multi-module)
|
|
219
|
-
- **NEVER** stop between iterations
|
|
263
|
+
- **NEVER** stop between iterations — this is the CORE PROMISE of ralph-loop
|
|
264
|
+
- **NEVER** ask the user "should I continue?" or "is this OK?" — JUST CONTINUE
|
|
265
|
+
- **NEVER** pause to show intermediate results and wait for feedback
|
|
220
266
|
- **BATCH** same-category tasks (max 5)
|
|
221
267
|
- **MODULE COMPLETENESS:** All layers must have completed tasks before advancing
|
|
222
|
-
- Only valid stop
|
|
268
|
+
- **Only valid stop conditions:** all complete, max iterations, dead-end, or user Ctrl+C
|
|
269
|
+
- **If you stop for any other reason, you have VIOLATED the execution guarantee.**
|
|
223
270
|
|
|
224
271
|
---
|
|
225
272
|
|