@atlashub/smartstack-cli 1.35.0 → 1.37.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 (27) hide show
  1. package/package.json +1 -1
  2. package/templates/skills/_shared.md +7 -7
  3. package/templates/skills/application/steps/step-01-navigation.md +226 -43
  4. package/templates/skills/application/steps/step-03-roles.md +160 -38
  5. package/templates/skills/application/steps/step-04-backend.md +126 -19
  6. package/templates/skills/application/steps/step-05-frontend.md +4 -1
  7. package/templates/skills/application/templates-backend.md +8 -8
  8. package/templates/skills/application/templates-frontend.md +8 -8
  9. package/templates/skills/application/templates-seed.md +200 -1
  10. package/templates/skills/gitflow/_shared.md +188 -53
  11. package/templates/skills/gitflow/phases/abort.md +28 -16
  12. package/templates/skills/gitflow/phases/cleanup.md +13 -9
  13. package/templates/skills/gitflow/phases/status.md +16 -17
  14. package/templates/skills/gitflow/steps/step-commit.md +11 -5
  15. package/templates/skills/gitflow/steps/step-finish.md +43 -33
  16. package/templates/skills/gitflow/steps/step-init.md +7 -2
  17. package/templates/skills/gitflow/steps/step-merge.md +24 -10
  18. package/templates/skills/gitflow/steps/step-pr.md +42 -28
  19. package/templates/skills/gitflow/steps/step-start.md +19 -13
  20. package/templates/skills/gitflow/templates/config.json +7 -4
  21. package/templates/skills/ralph-loop/SKILL.md +57 -11
  22. package/templates/skills/ralph-loop/steps/step-00-init.md +170 -30
  23. package/templates/skills/ralph-loop/steps/step-01-task.md +243 -40
  24. package/templates/skills/ralph-loop/steps/step-02-execute.md +142 -24
  25. package/templates/skills/ralph-loop/steps/step-03-commit.md +140 -36
  26. package/templates/skills/ralph-loop/steps/step-04-check.md +128 -44
  27. package/templates/skills/ralph-loop/steps/step-05-report.md +175 -88
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: step-00-init
3
- description: Initialize Ralph loop - parse args, verify MCP, setup state
3
+ description: Initialize Ralph loop - parse args, verify MCP, setup state, migrate v1
4
4
  next_step: steps/step-01-task.md
5
5
  ---
6
6
 
@@ -13,10 +13,11 @@ next_step: steps/step-01-task.md
13
13
  - ONLY check for resume if -r flag is set
14
14
  - YOU ARE AN INITIALIZER, not an executor
15
15
  - FORBIDDEN to load step-01 until init is complete
16
+ - ALWAYS check prd.json version and migrate if v1
16
17
 
17
18
  ## YOUR TASK:
18
19
 
19
- Initialize the Ralph loop by parsing flags, verifying MCP availability, and setting up the execution environment.
20
+ Initialize the Ralph loop by parsing flags, verifying MCP availability, setting up the execution environment, and validating integrity on resume.
20
21
 
21
22
  ---
22
23
 
@@ -73,26 +74,32 @@ mcp__smartstack__validate_conventions:
73
74
 
74
75
  **Check Context7 MCP:**
75
76
  ```
76
- mcp__plugin_context7_context7__resolve-library-id:
77
+ mcp__context7__resolve-library-id:
77
78
  libraryName: "test"
78
79
  query: "connectivity check"
79
80
  (just to verify connectivity)
80
81
  ```
81
82
 
83
+ **Record MCP status for metadata:**
84
+ ```
85
+ {mcp_smartstack} = true/false
86
+ {mcp_context7} = true/false
87
+ ```
88
+
82
89
  **If ANY MCP fails:**
83
90
  ```
84
91
  ╔══════════════════════════════════════════════════════════════════╗
85
- ║ ❌ MCP SERVER UNAVAILABLE
92
+ ║ ❌ MCP SERVER UNAVAILABLE
86
93
  ╠══════════════════════════════════════════════════════════════════╣
87
- ║ Server: {failed_server}
88
- ║ Status: Connection failed
94
+ ║ Server: {failed_server}
95
+ ║ Status: Connection failed
89
96
  ╠══════════════════════════════════════════════════════════════════╣
90
- ║ RALPH CANNOT PROCEED WITHOUT MCP
91
-
92
- ║ Troubleshooting:
93
- ║ 1. Run: smartstack check-mcp
94
- ║ 2. Restart Claude Code
95
- ║ 3. Check MCP server configuration
97
+ ║ RALPH CANNOT PROCEED WITHOUT MCP
98
+
99
+ ║ Troubleshooting:
100
+ ║ 1. Run: smartstack check-mcp
101
+ ║ 2. Restart Claude Code
102
+ ║ 3. Check MCP server configuration
96
103
  ╚══════════════════════════════════════════════════════════════════╝
97
104
 
98
105
  STOP - Do not proceed.
@@ -103,16 +110,122 @@ STOP - Do not proceed.
103
110
  **If {resume_mode} = true:**
104
111
 
105
112
  1. Check for existing `.ralph/prd.json`
106
- 2. If found:
107
- - Read prd.json to restore state
108
- - Read progress.txt for context
109
- - Set {current_iteration} from state
110
- - Continue to step-01
111
- 3. If not found:
113
+ 2. If not found:
112
114
  - Error: "No active Ralph loop to resume"
113
115
  - Ask user to start new loop
116
+ - STOP
117
+
118
+ 3. If found, **validate schema version:**
119
+
120
+ ```javascript
121
+ const prd = readJSON('.ralph/prd.json');
114
122
 
115
- ### 4. Initialize .ralph/ Structure
123
+ // v1 detection: has "passes" field in tasks or no "$version"
124
+ const isV1 = !prd.$version || prd.tasks?.some(t => 'passes' in t);
125
+
126
+ if (isV1) {
127
+ // AUTO-MIGRATE v1 → v2
128
+ migrateV1toV2(prd);
129
+ }
130
+ ```
131
+
132
+ **v1 → v2 Migration logic:**
133
+
134
+ ```javascript
135
+ function migrateV1toV2(prd) {
136
+ prd.$version = "2.0.0";
137
+ prd.status = prd.tasks.every(t => t.passes) ? "completed" : "in_progress";
138
+ prd.updated_at = new Date().toISOString();
139
+
140
+ // Migrate source field
141
+ if (typeof prd.source === 'string') {
142
+ prd.source = { type: "ba-handoff", handoff_path: prd.source, frd_path: null, brd_path: null };
143
+ } else if (prd.source === null || prd.source === undefined) {
144
+ prd.source = null;
145
+ }
146
+
147
+ // Group flat config fields
148
+ prd.config = {
149
+ max_iterations: prd.max_iterations || 50,
150
+ completion_promise: prd.completion_promise || "COMPLETE",
151
+ current_iteration: prd.current_iteration || 1
152
+ };
153
+ delete prd.max_iterations;
154
+ delete prd.completion_promise;
155
+ delete prd.current_iteration;
156
+
157
+ // Add metadata
158
+ prd.metadata = {
159
+ cli_version: "unknown (migrated)",
160
+ branch: getCurrentBranch(),
161
+ project_path: process.cwd(),
162
+ mcp_servers: { smartstack: {mcp_smartstack}, context7: {mcp_context7} }
163
+ };
164
+
165
+ // Migrate tasks
166
+ prd.tasks = prd.tasks.map(t => ({
167
+ id: t.id,
168
+ description: t.description,
169
+ status: t.passes ? "completed" : "pending",
170
+ category: "other",
171
+ dependencies: [],
172
+ acceptance_criteria: null,
173
+ started_at: null,
174
+ completed_at: t.passes ? prd.updated_at : null,
175
+ iteration: null,
176
+ commit_hash: null,
177
+ files_changed: { created: [], modified: [] },
178
+ validation: null,
179
+ error: null
180
+ }));
181
+
182
+ // Initialize history
183
+ prd.history = [];
184
+
185
+ // Write migrated file
186
+ writeJSON('.ralph/prd.json', prd);
187
+ echo "✅ Migrated prd.json from v1 to v2";
188
+ }
189
+ ```
190
+
191
+ 4. **Validate integrity (v2 resume):**
192
+
193
+ ```bash
194
+ # Check branch consistency
195
+ CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
196
+ PRD_BRANCH={prd.metadata.branch}
197
+
198
+ if [ "$CURRENT_BRANCH" != "$PRD_BRANCH" ]; then
199
+ echo "⚠️ Branch mismatch: prd.json was created on '$PRD_BRANCH', now on '$CURRENT_BRANCH'"
200
+ # Ask user: continue on current branch or switch
201
+ AskUserQuestion:
202
+ header: "Branch"
203
+ question: "prd.json was created on '$PRD_BRANCH' but you're on '$CURRENT_BRANCH'. Continue?"
204
+ options:
205
+ - label: "Continue on $CURRENT_BRANCH"
206
+ description: "Update metadata and continue"
207
+ - label: "Cancel"
208
+ description: "Switch branch manually first"
209
+ fi
210
+
211
+ # Check for external commits since last update
212
+ LAST_UPDATED={prd.updated_at}
213
+ EXTERNAL_COMMITS=$(git log --since="$LAST_UPDATED" --oneline --not --author="Co-Authored-By: Claude" | wc -l)
214
+
215
+ if [ "$EXTERNAL_COMMITS" -gt 0 ]; then
216
+ echo "⚠️ $EXTERNAL_COMMITS external commits detected since last Ralph iteration"
217
+ echo " prd.json state may not reflect current code state"
218
+ fi
219
+ ```
220
+
221
+ 5. **Restore state from prd.json:**
222
+ - Read `prd.config.current_iteration` → `{current_iteration}`
223
+ - Read `prd.config.completion_promise` → `{completion_promise}`
224
+ - Read `prd.config.max_iterations` → `{max_iterations}`
225
+ - Read progress.txt for context
226
+ - Continue to step-01
227
+
228
+ ### 4. Initialize .ralph/ Structure (new loop)
116
229
 
117
230
  **Create directory structure:**
118
231
 
@@ -149,7 +262,27 @@ AskUserQuestion:
149
262
  description: "Specify custom text"
150
263
  ```
151
264
 
152
- ### 6. Log Initialization
265
+ ### 6. Collect Metadata
266
+
267
+ **Gather execution context:**
268
+
269
+ ```bash
270
+ CLI_VERSION=$(node -e "console.log(require('package.json').version)" 2>/dev/null || echo "unknown")
271
+ CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
272
+ PROJECT_PATH=$(pwd)
273
+ ```
274
+
275
+ **Store metadata for prd.json creation (step-01):**
276
+ ```
277
+ {metadata} = {
278
+ cli_version: CLI_VERSION,
279
+ branch: CURRENT_BRANCH,
280
+ project_path: PROJECT_PATH,
281
+ mcp_servers: { smartstack: {mcp_smartstack}, context7: {mcp_context7} }
282
+ }
283
+ ```
284
+
285
+ ### 7. Log Initialization
153
286
 
154
287
  **If {verbose_mode} = true:**
155
288
 
@@ -159,25 +292,29 @@ Write to `.ralph/logs/{timestamp}.log`:
159
292
  Task: {task_description}
160
293
  Max iterations: {max_iterations}
161
294
  Completion promise: {completion_promise}
162
- MCP Status: SmartStack ✅, Context7 ✅
295
+ MCP Status: SmartStack {mcp_smartstack ? "✅" : "❌"}, Context7 {mcp_context7 ? "" : "❌"}
296
+ Schema: v2.0.0
297
+ Branch: {CURRENT_BRANCH}
163
298
  ```
164
299
 
165
- ### 7. Show Summary and Proceed
300
+ ### 8. Show Summary and Proceed
166
301
 
167
302
  **Always show COMPACT summary:**
168
303
 
169
304
  ```
170
305
  ╔══════════════════════════════════════════════════════════════════╗
171
- ║ RALPH LOOP INITIALIZED
306
+ ║ RALPH LOOP INITIALIZED
172
307
  ╠══════════════════════════════════════════════════════════════════╣
173
- ║ Task: {task_description}
174
- ║ Max iterations: {max_iterations}
175
- ║ Completion: <promise>{completion_promise}</promise>
176
- ║ MCP: ✅ Ready
308
+ ║ Task: {task_description}
309
+ ║ Max iterations: {max_iterations}
310
+ ║ Completion: <promise>{completion_promise}</promise>
311
+ ║ MCP: ✅ Ready
312
+ ║ Schema: v2.0.0 ║
313
+ ║ Branch: {CURRENT_BRANCH} ║
177
314
  ╠══════════════════════════════════════════════════════════════════╣
178
- ║ Files:
179
- ║ - .ralph/prd.json (tasks)
180
- ║ - .ralph/progress.txt (memory)
315
+ ║ Files:
316
+ ║ - .ralph/prd.json (tasks)
317
+ ║ - .ralph/progress.txt (memory)
181
318
  ╚══════════════════════════════════════════════════════════════════╝
182
319
 
183
320
  -> Loading tasks...
@@ -193,6 +330,9 @@ MCP Status: SmartStack ✅, Context7 ✅
193
330
  - MCP servers verified and available
194
331
  - .ralph/ directory structure created
195
332
  - Completion promise defined
333
+ - Metadata collected (branch, version, MCP status)
334
+ - v1 prd.json migrated to v2 (if resume)
335
+ - Branch integrity validated (if resume)
196
336
  - Output is COMPACT
197
337
  - Proceeded to step-01 immediately after summary
198
338
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: step-01-task
3
- description: Load or create tasks from prd.json
3
+ description: Load or create tasks from prd.json (v2 schema)
4
4
  next_step: steps/step-02-execute.md
5
5
  ---
6
6
 
@@ -8,7 +8,7 @@ next_step: steps/step-02-execute.md
8
8
 
9
9
  ## YOUR TASK:
10
10
 
11
- Load the current task from prd.json or create initial task breakdown.
11
+ Load the current task from prd.json or create initial task breakdown with categories, dependencies, and acceptance criteria.
12
12
 
13
13
  **ULTRA THINK about task decomposition.**
14
14
 
@@ -20,9 +20,9 @@ Load the current task from prd.json or create initial task breakdown.
20
20
 
21
21
  **If `.ralph/prd.json` exists:**
22
22
  - Read and parse the file
23
- - Find the next task with `passes: false`
24
- - Load into state
25
- - Skip to step 4
23
+ - Verify `$version` is `"2.0.0"` (if not, STOP - run step-00 migration first)
24
+ - Find the next eligible task (see step 5)
25
+ - Skip to step 5
26
26
 
27
27
  **If `.ralph/prd.json` does NOT exist:**
28
28
  - Continue to step 2 (create tasks)
@@ -35,42 +35,162 @@ Load the current task from prd.json or create initial task breakdown.
35
35
  - What order should they be executed?
36
36
  - What are the success criteria for each?
37
37
  - What files will be modified?
38
+ - What layer does each task belong to?
39
+ - What dependencies exist between tasks?
40
+
41
+ **Check for BA handoff source:**
42
+
43
+ ```bash
44
+ # If a handoff document exists, use it to derive tasks
45
+ HANDOFF=$(find . -path "*development-handoff*" -name "*.md" | head -1)
46
+ BA_OUTPUT=$(find . -path ".claude/output/ba/*" -name "4-*.md" | head -1)
47
+ SOURCE_PATH=${HANDOFF:-$BA_OUTPUT}
48
+ ```
49
+
50
+ **If handoff found:**
51
+ - Read the handoff document
52
+ - Derive tasks from its specifications (per-layer breakdown)
53
+ - Set `source.type = "ba-handoff"` and `source.handoff_path`
54
+ - Look for FRD and BRD in the same directory
55
+
56
+ **If no handoff:**
57
+ - Generate task breakdown from `{task_description}`
58
+ - Set `source = null`
38
59
 
39
60
  **Generate task breakdown:**
40
61
 
41
- For `{task_description}`, identify 3-10 subtasks.
62
+ For `{task_description}`, identify **3-30 subtasks** organized by category.
63
+
64
+ **Task categories (use SmartStack layer order):**
65
+
66
+ | Category | Description | Examples |
67
+ |----------|-------------|---------|
68
+ | `domain` | Domain entities and value objects | Create entities, enums, interfaces |
69
+ | `application` | CQRS handlers, DTOs, validators | Commands, Queries, DTOs, FluentValidation |
70
+ | `infrastructure` | EF Core, external services | DbContext configs, migrations, services |
71
+ | `api` | Controllers, middleware | REST endpoints, filters, middleware |
72
+ | `frontend` | React pages, components, hooks | Pages, API services, React Query hooks |
73
+ | `i18n` | Translations | Translation JSON files |
74
+ | `test` | Unit and integration tests | xUnit tests, React testing library |
75
+ | `validation` | Build, lint, MCP checks | dotnet build, pnpm build, MCP validate |
76
+ | `other` | Anything else | Documentation, configuration |
42
77
 
43
78
  **Example for "implement user authentication":**
44
79
  ```json
45
80
  {
46
81
  "tasks": [
47
- { "id": 1, "description": "Create User entity in Domain layer", "passes": false },
48
- { "id": 2, "description": "Add User DbSet to ApplicationDbContext", "passes": false },
49
- { "id": 3, "description": "Create EF Core migration", "passes": false },
50
- { "id": 4, "description": "Implement IPasswordService", "passes": false },
51
- { "id": 5, "description": "Implement IJwtService", "passes": false },
52
- { "id": 6, "description": "Create AuthController with login endpoint", "passes": false },
53
- { "id": 7, "description": "Add authentication middleware", "passes": false },
54
- { "id": 8, "description": "Write integration tests", "passes": false }
82
+ {
83
+ "id": 1,
84
+ "description": "Create User entity in SmartStack.Domain/Entities/Business/",
85
+ "status": "pending",
86
+ "category": "domain",
87
+ "dependencies": [],
88
+ "acceptance_criteria": "Entity compiles with all required properties per handoff spec"
89
+ },
90
+ {
91
+ "id": 2,
92
+ "description": "Add User DbSet to ApplicationDbContext and create EF Core configuration",
93
+ "status": "pending",
94
+ "category": "infrastructure",
95
+ "dependencies": [1],
96
+ "acceptance_criteria": "DbContext compiles, configuration maps all properties"
97
+ },
98
+ {
99
+ "id": 3,
100
+ "description": "Create EF Core migration for User table",
101
+ "status": "pending",
102
+ "category": "infrastructure",
103
+ "dependencies": [2],
104
+ "acceptance_criteria": "Migration applies without errors, 3 files present"
105
+ },
106
+ {
107
+ "id": 4,
108
+ "description": "Implement IPasswordService and IJwtService",
109
+ "status": "pending",
110
+ "category": "application",
111
+ "dependencies": [1],
112
+ "acceptance_criteria": "Services compile, follow existing patterns"
113
+ },
114
+ {
115
+ "id": 5,
116
+ "description": "Create CQRS Commands: LoginCommand + RegisterCommand with handlers",
117
+ "status": "pending",
118
+ "category": "application",
119
+ "dependencies": [4],
120
+ "acceptance_criteria": "Handlers compile, validators defined"
121
+ },
122
+ {
123
+ "id": 6,
124
+ "description": "Create AuthController with login/register endpoints",
125
+ "status": "pending",
126
+ "category": "api",
127
+ "dependencies": [5],
128
+ "acceptance_criteria": "Endpoints respond correctly, Swagger displays them"
129
+ },
130
+ {
131
+ "id": 7,
132
+ "description": "Write unit tests for User entity and validators",
133
+ "status": "pending",
134
+ "category": "test",
135
+ "dependencies": [5],
136
+ "acceptance_criteria": "All tests pass, >80% coverage on new code"
137
+ },
138
+ {
139
+ "id": 8,
140
+ "description": "Run dotnet build, dotnet test, MCP validate_conventions",
141
+ "status": "pending",
142
+ "category": "validation",
143
+ "dependencies": [6, 7],
144
+ "acceptance_criteria": "Build succeeds, all tests pass, MCP validation clean"
145
+ }
55
146
  ]
56
147
  }
57
148
  ```
58
149
 
59
- ### 3. Create prd.json
150
+ **Task count validation:**
151
+ - MINIMUM: 3 tasks (anything less is too coarse)
152
+ - MAXIMUM: 30 tasks (anything more needs re-grouping)
153
+ - If over 30, merge related subtasks into larger units
154
+
155
+ ### 3. Create prd.json (v2)
60
156
 
61
157
  **Write `.ralph/prd.json`:**
62
158
 
63
159
  ```json
64
160
  {
161
+ "$version": "2.0.0",
65
162
  "feature": "{task_description}",
66
- "created": "{timestamp}",
67
- "max_iterations": {max_iterations},
68
- "completion_promise": "{completion_promise}",
69
- "current_iteration": 1,
70
- "tasks": [
71
- { "id": 1, "description": "...", "passes": false },
72
- { "id": 2, "description": "...", "passes": false }
73
- ]
163
+ "status": "in_progress",
164
+ "created": "{ISO_TIMESTAMP}",
165
+ "updated_at": "{ISO_TIMESTAMP}",
166
+ "metadata": {metadata},
167
+ "config": {
168
+ "max_iterations": {max_iterations},
169
+ "completion_promise": "{completion_promise}",
170
+ "current_iteration": 1
171
+ },
172
+ "source": {source_object_or_null},
173
+ "tasks": [{generated_tasks_with_all_fields}],
174
+ "history": []
175
+ }
176
+ ```
177
+
178
+ **IMPORTANT: Every task MUST have ALL fields:**
179
+ ```json
180
+ {
181
+ "id": 1,
182
+ "description": "...",
183
+ "status": "pending",
184
+ "category": "domain|application|infrastructure|api|frontend|i18n|test|validation|other",
185
+ "dependencies": [],
186
+ "acceptance_criteria": "...",
187
+ "started_at": null,
188
+ "completed_at": null,
189
+ "iteration": null,
190
+ "commit_hash": null,
191
+ "files_changed": { "created": [], "modified": [] },
192
+ "validation": null,
193
+ "error": null
74
194
  }
75
195
  ```
76
196
 
@@ -81,6 +201,8 @@ For `{task_description}`, identify 3-10 subtasks.
81
201
 
82
202
  ## Task: {task_description}
83
203
  ## Started: {timestamp}
204
+ ## Schema: v2.0.0
205
+ ## Source: {source_type or "direct"}
84
206
 
85
207
  ---
86
208
 
@@ -93,27 +215,102 @@ Starting fresh implementation.
93
215
  (To be updated after each iteration)
94
216
  ```
95
217
 
96
- ### 4. Find Current Task
218
+ ### 4. Validate Task Integrity
97
219
 
98
- **Find the next task with `passes: false`:**
220
+ **After creation, verify:**
99
221
 
100
222
  ```javascript
101
- const currentTask = tasks.find(t => !t.passes);
223
+ // Check all tasks have required fields
224
+ const requiredFields = ['id', 'description', 'status', 'category',
225
+ 'dependencies', 'acceptance_criteria', 'started_at', 'completed_at',
226
+ 'iteration', 'commit_hash', 'files_changed', 'validation', 'error'];
227
+
228
+ for (const task of prd.tasks) {
229
+ for (const field of requiredFields) {
230
+ if (!(field in task)) {
231
+ ERROR: "Task ${task.id} missing field: ${field}";
232
+ }
233
+ }
234
+ }
235
+
236
+ // Check dependency references are valid
237
+ const taskIds = prd.tasks.map(t => t.id);
238
+ for (const task of prd.tasks) {
239
+ for (const dep of task.dependencies) {
240
+ if (!taskIds.includes(dep)) {
241
+ ERROR: "Task ${task.id} depends on non-existent task ${dep}";
242
+ }
243
+ }
244
+ }
245
+
246
+ // Check no circular dependencies
247
+ // (simple: a task cannot depend on a task with higher or equal id)
248
+ for (const task of prd.tasks) {
249
+ for (const dep of task.dependencies) {
250
+ if (dep >= task.id) {
251
+ ERROR: "Task ${task.id} has forward/circular dependency on task ${dep}";
252
+ }
253
+ }
254
+ }
255
+
256
+ // Check task count
257
+ if (prd.tasks.length < 3 || prd.tasks.length > 30) {
258
+ WARNING: "Task count ${prd.tasks.length} outside recommended range (3-30)";
259
+ }
260
+ ```
261
+
262
+ ### 5. Find Current Task
263
+
264
+ **Find the next eligible task:**
265
+
266
+ ```javascript
267
+ function findNextTask(tasks) {
268
+ for (const task of tasks) {
269
+ if (task.status !== 'pending') continue;
270
+
271
+ // Check all dependencies are completed
272
+ const depsOk = task.dependencies.every(depId => {
273
+ const dep = tasks.find(t => t.id === depId);
274
+ return dep && dep.status === 'completed';
275
+ });
276
+
277
+ // Check if any dependency failed (→ block this task)
278
+ const depsBlocked = task.dependencies.some(depId => {
279
+ const dep = tasks.find(t => t.id === depId);
280
+ return dep && (dep.status === 'failed' || dep.status === 'blocked');
281
+ });
282
+
283
+ if (depsBlocked) {
284
+ task.status = 'blocked';
285
+ task.error = `Blocked by failed dependency`;
286
+ continue;
287
+ }
288
+
289
+ if (depsOk) return task;
290
+ }
291
+ return null; // No eligible tasks
292
+ }
293
+
294
+ const currentTask = findNextTask(prd.tasks);
102
295
  ```
103
296
 
104
- **If all tasks are `passes: true`:**
105
- - This shouldn't happen in step-01
106
- - If it does, skip to step-05 (report)
297
+ **If no eligible task found:**
298
+ - Check if all tasks are completed → skip to step-05 (report)
299
+ - Check if remaining tasks are all blocked → report as partial, step-05
300
+ - Otherwise → unexpected state, STOP
107
301
 
108
302
  **Store in state:**
109
303
  ```
110
304
  {current_task_id} = currentTask.id
111
305
  {current_task_description} = currentTask.description
112
- {tasks_completed} = tasks.filter(t => t.passes).length
306
+ {current_task_category} = currentTask.category
307
+ {current_task_criteria} = currentTask.acceptance_criteria
308
+ {tasks_completed} = tasks.filter(t => t.status === 'completed').length
113
309
  {tasks_total} = tasks.length
310
+ {tasks_blocked} = tasks.filter(t => t.status === 'blocked').length
114
311
  ```
115
312
 
116
- ### 5. Read Previous Progress
313
+ ### 6. Read Previous Progress
117
314
 
118
315
  **If iteration > 1:**
119
316
 
@@ -123,23 +320,26 @@ Read `.ralph/progress.txt` to understand:
123
320
  - Files that were modified
124
321
  - Issues encountered
125
322
 
126
- **This provides context for the current iteration.**
323
+ **Also read `history[]` from prd.json for structured context.**
127
324
 
128
- ### 6. Show Task Status
325
+ ### 7. Show Task Status
129
326
 
130
327
  **Display current state:**
131
328
 
132
329
  ```
133
330
  ╔══════════════════════════════════════════════════════════════════╗
134
- ║ ITERATION {current_iteration} / {max_iterations}
331
+ ║ ITERATION {current_iteration} / {max_iterations}
135
332
  ╠══════════════════════════════════════════════════════════════════╣
136
- ║ Progress: {tasks_completed} / {tasks_total} tasks complete
137
-
138
- Current Task:
139
- [{current_task_id}] {current_task_description}
333
+ ║ Progress: {tasks_completed} / {tasks_total} tasks complete
334
+ Blocked: {tasks_blocked}
335
+
336
+ Current Task:
337
+ ║ [{current_task_id}] {current_task_description} ║
338
+ ║ Category: {current_task_category} ║
339
+ ║ Criteria: {current_task_criteria} ║
140
340
  ╠══════════════════════════════════════════════════════════════════╣
141
- ║ Previous Learnings:
142
- ║ {summary from progress.txt}
341
+ ║ Previous Learnings:
342
+ ║ {summary from progress.txt}
143
343
  ╚══════════════════════════════════════════════════════════════════╝
144
344
 
145
345
  -> Executing task...
@@ -157,7 +357,10 @@ Task Loaded:
157
357
  | Iteration | {current_iteration} / {max_iterations} |
158
358
  | Task ID | {current_task_id} |
159
359
  | Task | {current_task_description} |
360
+ | Category | {current_task_category} |
361
+ | Criteria | {current_task_criteria} |
160
362
  | Progress | {tasks_completed} / {tasks_total} |
363
+ | Blocked | {tasks_blocked} |
161
364
 
162
365
  -> Executing...
163
366
  ```