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

# Step 1: Load Task

> **STATE RECOVERY (executable):** If context was compressed and you are unsure of your position:
```javascript
if (fileExists('.ralph/ralph-state.json')) {
  const state = readJSON('.ralph/ralph-state.json');
  if (state.currentStep && state.currentStep !== 'step-01-task') {
    console.warn(`RECOVERY: ralph-state.json says currentStep="${state.currentStep}" but we are in step-01.`);
    console.warn(`This may indicate context compression routed to the wrong step.`);
    console.warn(`Current module: ${state.currentModule}, iteration: ${state.iteration}`);
  }
  // Restore module context
  if (state.currentModule) { {current_module} = state.currentModule; }
  if (state.iteration) { {current_iteration} = state.iteration; }
}
```

> **MODULE TRANSITION CHECK:** Before "Only Read Once" rule, check for module transition:

```javascript
if (fileExists('.ralph/module-changed.json')) {
  const t = readJSON('.ralph/module-changed.json');
  console.log(`Module transition: ${t.fromModule} → ${t.toModule}`);
  deleteFile('.ralph/module-changed.json');
  // PROCEED (exception to "Only Read Once" rule)
}
```

> **CONTEXT OPTIMIZATION:** Read ONCE per module (first iteration).
> Iterations > 1 within same module → use COMPACT LOOP in step-04.
> Re-read ONLY on module transition (module-changed.json detected above).

## YOUR TASK:

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

---

## 0. Multi-Module Queue Check

See `references/multi-module-queue.md` for full module queue initialization, detection, and loading.

Quick: If `glob('.ralph/prd-*.json').length > 1` → create modules-queue.json and load first module's PRD.

---

## PrdJson → Ralph v2 Transformation (DEPRECATED)

See [references/task-transform-legacy.md](../references/task-transform-legacy.md) for the full `transformPrdJsonToRalphV2()` function including:
- Layer-ordered task generation (domain → infra → app → api → frontend → seedData → tests)
- Consolidated frontend + i18n tasks
- Guardrails 1d-1j (inject missing infrastructure, API, frontend, tests, seed data, migration)

---

## 1. Check for Existing prd.json

```javascript
// PRD PATH RESOLUTION (MANDATORY - runs before any PRD access)
const queuePath = '.ralph/modules-queue.json';
let currentPrdPath = '.ralph/prd.json';
if (fileExists(queuePath)) {
  const queue = readJSON(queuePath);
  currentPrdPath = queue.modules[queue.currentIndex].prdFile;
}
```

If `{currentPrdPath}` exists:
1. Read the PRD
2. **v3 FAST PATH:** If `$version === "3.0.0"` AND `tasks[]` exists:
   - Inject runtime fields if missing (status, config, feature, created, updated_at, history)
   - Write back to `{currentPrdPath}`
   - **Run CATEGORY COMPLETENESS CHECK (section 4b) before proceeding**
   - Skip directly to section 5 (find next task)
2b. **v3 filesToCreate PATH:** If `$version === "3.0.0"` AND `implementation.filesToCreate` exists AND NO `tasks[]`:
   → **Load** `references/prd-v3-transformation.md` for the filesToCreate → tasks transformation algorithm and deriveAcceptanceCriteria() function.
   → Run CATEGORY COMPLETENESS CHECK (section 4b) — will detect if seedData is missing
   → Skip to section 5 (find next task)
3. **v2 legacy:** If `$version === "2.0.0"` → find next eligible task (section 5)
4. **FORMAT A (deprecated):** If `.project && .requirements && !.$version` → run `transformPrdJsonToRalphV2()` → section 5

If `{currentPrdPath}` does not exist: continue to section 1b.

### 1b. BA Handoff Quality Gate (BLOCKING when BA artifacts present)

> **Load** `references/handoff-quality-gate.md` for full BA handoff validation checks.

Quick check:
- If no BA artifacts detected (`sourceFeatureJson` is null): skip gate, proceed in manual mode
- If BA artifacts present: verify `feature.handoff.status === "handed-off"` and `filesToCreate[]` has all categories

## 2. Analyze Task Description

Check for BA handoff source (priority):
1. Per-module PRD files (handled by section 0)
2. Single prd.json already present
3. Markdown handoff: `find . -path "*development-handoff*" -name "*.md"`
4. Direct task from `{task_description}`

Generate **3-30 subtasks** by category (domain → infrastructure → application → api → seedData → frontend → i18n → test → validation).

**seedData category is MANDATORY** — generates navigation entries, permissions, roles, and the IClientSeedDataProvider.
Without seedData tasks, modules are invisible in the UI (no menu, no permissions, no RBAC).

## 3. Create prd.json

Write `{currentPrdPath}` with all tasks (every task MUST have: id, description, status, category, dependencies, acceptance_criteria, started_at, completed_at, iteration, commit_hash, files_changed, validation, error).

Initialize `.ralph/progress.txt`:
```markdown
# Ralph Loop Progress
## Task: {task_description}
## Started: {timestamp}
## Schema: v3.0.0
```

## 4. Validate Task Integrity

- All tasks have required fields
- Dependency references are valid (exist, no forward/circular)
- Task count 3-30

### 4b. Category Completeness Check (BLOCKING)

See `references/category-completeness.md` for full implementation.

Quick: `checkCategoryCompleteness(prd)` → inject guardrails if needed

---

### 4c. Section Split Detection (Large Module)

```javascript
const domainTasks = prd.tasks.filter(t => t.category === 'domain');
const sections = prd.architecture?.sections ?? [];

if (domainTasks.length > 4 && sections.length > 1 && !prd._sectionSplit?.enabled) {
  console.log(`SECTION SPLIT: ${domainTasks.length} domain tasks, ${sections.length} sections → activating`);
  // LOAD references/section-splitting.md — execute sections 2-6
}
```

**Activation:** `> 4 domain tasks` AND `> 1 architecture section`

## 5. Find Current Task

```javascript
function findNextTask(tasks) {
  for (const task of tasks) {
    if (task.status !== 'pending') continue;
    const depsBlocked = task.dependencies.some(d => {
      const dep = tasks.find(t => t.id === d);
      return dep && (dep.status === 'failed' || dep.status === 'blocked');
    });
    if (depsBlocked) { task.status = 'blocked'; task.error = 'Blocked by failed dependency'; continue; }
    const depsOk = task.dependencies.every(d => tasks.find(t => t.id === d)?.status === 'completed');
    if (depsOk) return task;
  }
  return null;
}
```

If no eligible task: check if all completed → step-05, else STOP.

## 6. Show Task Status

```
[{iteration}/{max}] {completed}/{total} done | Task [{id}] {description} ({category})
-> Executing...
```

---

## NEXT STEP:

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