---
name: step-01-task
description: Load or create tasks from prd.json (v2 schema)
next_step: steps/step-02-execute.md
---

# Step 1: Load Task

## YOUR TASK:

Load the current task from prd.json or create initial task breakdown with categories, dependencies, and acceptance criteria.

**ULTRA THINK about task decomposition.**

---

## EXECUTION SEQUENCE:

### 1. Check for Existing prd.json

**If `.ralph/prd.json` exists:**
- Read and parse the file
- Verify `$version` is `"2.0.0"` (if not, STOP - run step-00 migration first)
- Find the next eligible task (see step 5)
- Skip to step 5

**If `.ralph/prd.json` does NOT exist:**
- Continue to step 2 (create tasks)

### 2. Analyze Task Description

**ULTRA THINK about the task:**

- What are the logical subtasks?
- What order should they be executed?
- What are the success criteria for each?
- What files will be modified?
- What layer does each task belong to?
- What dependencies exist between tasks?

**Check for BA handoff source:**

```bash
# If a handoff document exists, use it to derive tasks
HANDOFF=$(find . -path "*development-handoff*" -name "*.md" | head -1)
BA_OUTPUT=$(find . -path ".claude/output/ba/*" -name "4-*.md" | head -1)
SOURCE_PATH=${HANDOFF:-$BA_OUTPUT}
```

**If handoff found:**
- Read the handoff document
- Derive tasks from its specifications (per-layer breakdown)
- Set `source.type = "ba-handoff"` and `source.handoff_path`
- Look for feature.json in the same directory

**If no handoff:**
- Generate task breakdown from `{task_description}`
- Set `source = null`

**Generate task breakdown:**

For `{task_description}`, identify **3-30 subtasks** organized by category.

**Task categories (use SmartStack layer order):**

| Category | Description | Examples |
|----------|-------------|---------|
| `domain` | Domain entities and value objects | Create entities, enums, interfaces |
| `application` | CQRS handlers, DTOs, validators | Commands, Queries, DTOs, FluentValidation |
| `infrastructure` | EF Core, external services | DbContext configs, migrations, services |
| `api` | Controllers, middleware | REST endpoints, filters, middleware |
| `frontend` | React pages, components, hooks | Pages, API services, React Query hooks |
| `i18n` | Translations | Translation JSON files |
| `test` | Unit and integration tests | xUnit tests, React testing library |
| `validation` | Build, lint, MCP checks | dotnet build, pnpm build, MCP validate |
| `other` | Anything else | Documentation, configuration |

**Example for "implement user authentication":**
```json
{
  "tasks": [
    {
      "id": 1,
      "description": "Create User entity in SmartStack.Domain/Entities/Business/",
      "status": "pending",
      "category": "domain",
      "dependencies": [],
      "acceptance_criteria": "Entity compiles with all required properties per handoff spec"
    },
    {
      "id": 2,
      "description": "Add User DbSet to ApplicationDbContext and create EF Core configuration",
      "status": "pending",
      "category": "infrastructure",
      "dependencies": [1],
      "acceptance_criteria": "DbContext compiles, configuration maps all properties"
    },
    {
      "id": 3,
      "description": "Create EF Core migration for User table",
      "status": "pending",
      "category": "infrastructure",
      "dependencies": [2],
      "acceptance_criteria": "Migration applies without errors, 3 files present"
    },
    {
      "id": 4,
      "description": "Implement IPasswordService and IJwtService",
      "status": "pending",
      "category": "application",
      "dependencies": [1],
      "acceptance_criteria": "Services compile, follow existing patterns"
    },
    {
      "id": 5,
      "description": "Create CQRS Commands: LoginCommand + RegisterCommand with handlers",
      "status": "pending",
      "category": "application",
      "dependencies": [4],
      "acceptance_criteria": "Handlers compile, validators defined"
    },
    {
      "id": 6,
      "description": "Create AuthController with login/register endpoints",
      "status": "pending",
      "category": "api",
      "dependencies": [5],
      "acceptance_criteria": "Endpoints respond correctly, Swagger displays them"
    },
    {
      "id": 7,
      "description": "Write unit tests for User entity and validators",
      "status": "pending",
      "category": "test",
      "dependencies": [5],
      "acceptance_criteria": "All tests pass, >80% coverage on new code"
    },
    {
      "id": 8,
      "description": "Run dotnet build, dotnet test, MCP validate_conventions",
      "status": "pending",
      "category": "validation",
      "dependencies": [6, 7],
      "acceptance_criteria": "Build succeeds, all tests pass, MCP validation clean"
    }
  ]
}
```

**Task count validation:**
- MINIMUM: 3 tasks (anything less is too coarse)
- MAXIMUM: 30 tasks (anything more needs re-grouping)
- If over 30, merge related subtasks into larger units

### 3. Create prd.json (v2)

**Write `.ralph/prd.json`:**

```json
{
  "$version": "2.0.0",
  "feature": "{task_description}",
  "status": "in_progress",
  "created": "{ISO_TIMESTAMP}",
  "updated_at": "{ISO_TIMESTAMP}",
  "metadata": {metadata},
  "config": {
    "max_iterations": {max_iterations},
    "completion_promise": "{completion_promise}",
    "current_iteration": 1
  },
  "source": {source_object_or_null},
  "tasks": [{generated_tasks_with_all_fields}],
  "history": []
}
```

**IMPORTANT: Every task MUST have ALL fields:**
```json
{
  "id": 1,
  "description": "...",
  "status": "pending",
  "category": "domain|application|infrastructure|api|frontend|i18n|test|validation|other",
  "dependencies": [],
  "acceptance_criteria": "...",
  "started_at": null,
  "completed_at": null,
  "iteration": null,
  "commit_hash": null,
  "files_changed": { "created": [], "modified": [] },
  "validation": null,
  "error": null
}
```

**Initialize `.ralph/progress.txt`:**

```markdown
# Ralph Loop Progress

## Task: {task_description}
## Started: {timestamp}
## Schema: v2.0.0
## Source: {source_type or "direct"}

---

## Iteration 1

### Context
Starting fresh implementation.

### Learnings
(To be updated after each iteration)
```

### 4. Validate Task Integrity

**After creation, verify:**

```javascript
// Check all tasks have required fields
const requiredFields = ['id', 'description', 'status', 'category',
  'dependencies', 'acceptance_criteria', 'started_at', 'completed_at',
  'iteration', 'commit_hash', 'files_changed', 'validation', 'error'];

for (const task of prd.tasks) {
  for (const field of requiredFields) {
    if (!(field in task)) {
      ERROR: "Task ${task.id} missing field: ${field}";
    }
  }
}

// Check dependency references are valid
const taskIds = prd.tasks.map(t => t.id);
for (const task of prd.tasks) {
  for (const dep of task.dependencies) {
    if (!taskIds.includes(dep)) {
      ERROR: "Task ${task.id} depends on non-existent task ${dep}";
    }
  }
}

// Check no circular dependencies
// (simple: a task cannot depend on a task with higher or equal id)
for (const task of prd.tasks) {
  for (const dep of task.dependencies) {
    if (dep >= task.id) {
      ERROR: "Task ${task.id} has forward/circular dependency on task ${dep}";
    }
  }
}

// Check task count
if (prd.tasks.length < 3 || prd.tasks.length > 30) {
  WARNING: "Task count ${prd.tasks.length} outside recommended range (3-30)";
}
```

### 5. Find Current Task

**Find the next eligible task:**

```javascript
function findNextTask(tasks) {
  for (const task of tasks) {
    if (task.status !== 'pending') continue;

    // Check all dependencies are completed
    const depsOk = task.dependencies.every(depId => {
      const dep = tasks.find(t => t.id === depId);
      return dep && dep.status === 'completed';
    });

    // Check if any dependency failed (→ block this task)
    const depsBlocked = task.dependencies.some(depId => {
      const dep = tasks.find(t => t.id === depId);
      return dep && (dep.status === 'failed' || dep.status === 'blocked');
    });

    if (depsBlocked) {
      task.status = 'blocked';
      task.error = `Blocked by failed dependency`;
      continue;
    }

    if (depsOk) return task;
  }
  return null; // No eligible tasks
}

const currentTask = findNextTask(prd.tasks);
```

**If no eligible task found:**
- Check if all tasks are completed → skip to step-05 (report)
- Check if remaining tasks are all blocked → report as partial, step-05
- Otherwise → unexpected state, STOP

**Store in state:**
```
{current_task_id}          = currentTask.id
{current_task_description} = currentTask.description
{current_task_category}    = currentTask.category
{current_task_criteria}    = currentTask.acceptance_criteria
{tasks_completed}          = tasks.filter(t => t.status === 'completed').length
{tasks_total}              = tasks.length
{tasks_blocked}            = tasks.filter(t => t.status === 'blocked').length
```

### 6. Read Previous Progress

**If iteration > 1:**

Read `.ralph/progress.txt` to understand:
- What was done in previous iterations
- Key learnings and context
- Files that were modified
- Issues encountered

**Also read `history[]` from prd.json for structured context.**

### 7. Show Task Status

**Display current state:**

```
╔══════════════════════════════════════════════════════════════════╗
║  ITERATION {current_iteration} / {max_iterations}               ║
╠══════════════════════════════════════════════════════════════════╣
║  Progress: {tasks_completed} / {tasks_total} tasks complete     ║
║  Blocked:  {tasks_blocked}                                      ║
║                                                                  ║
║  Current Task:                                                   ║
║  [{current_task_id}] {current_task_description}                 ║
║  Category: {current_task_category}                               ║
║  Criteria: {current_task_criteria}                               ║
╠══════════════════════════════════════════════════════════════════╣
║  Previous Learnings:                                             ║
║  {summary from progress.txt}                                    ║
╚══════════════════════════════════════════════════════════════════╝

-> Executing task...
```

---

## OUTPUT FORMAT:

```
Task Loaded:

| Field | Value |
|-------|-------|
| Iteration | {current_iteration} / {max_iterations} |
| Task ID | {current_task_id} |
| Task | {current_task_description} |
| Category | {current_task_category} |
| Criteria | {current_task_criteria} |
| Progress | {tasks_completed} / {tasks_total} |
| Blocked | {tasks_blocked} |

-> Executing...
```

---

## NEXT STEP:

After task loaded, proceed to `./step-02-execute.md`
