---
name: step-03-commit
description: Commit changes, update prd.json v2 with full tracking
next_step: steps/step-04-check.md
---

# Step 3: Commit Changes

## YOUR TASK:

Commit the changes from the executed task, finalize task tracking in prd.json, and append to history.

---

## EXECUTION SEQUENCE:

### 1. Stage Changes

**Add modified files:**

```bash
git add {files_created} {files_modified}

# Also stage prd.json (already updated in step-02)
git add .ralph/prd.json
```

**Verify staged changes:**

```bash
git status
git diff --cached --stat
```

### 2. Create Commit

**Commit with descriptive message:**

```bash
git commit -m "$(cat <<'EOF'
{PREFIX}({scope}): {current_task_description}

Task {current_task_id}/{tasks_total} - Iteration {current_iteration}
Category: {current_task_category}
{current_module ? "Module: " + current_module : ""}

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
EOF
)"
```

**Determine commit prefix and scope:**

| Category | Prefix | Scope |
|----------|--------|-------|
| `domain` | `feat` | entity name or module |
| `application` | `feat` | module name |
| `infrastructure` | `db` | migrations / config |
| `api` | `feat` | controller name |
| `frontend` | `feat` | component/page name |
| `i18n` | `chore` | i18n |
| `test` | `test` | module name |
| `validation` | `chore` | validation |
| `other` | `chore` | ralph |

**Multi-module scope:** When `{current_module}` is set (from modules-queue.json), prefix the scope with the module code: `{PREFIX}({module}/{scope})`. Example: `feat(orders/OrderController): Create REST endpoints`.

**Get commit hash:**
```bash
COMMIT_HASH=$(git rev-parse --short HEAD)
```

### 3. Finalize Task in prd.json

**Mark task as completed with all tracking data:**

```javascript
const prd = readJSON('.ralph/prd.json');
const task = prd.tasks.find(t => t.id === {current_task_id});
const now = new Date().toISOString();

// Only mark completed if not already failed in step-02
if (task.status !== 'failed') {
  task.status = 'completed';
}
task.completed_at = now;
task.iteration = prd.config.current_iteration;
task.commit_hash = COMMIT_HASH;

// files_changed already set in step-02, but verify
if (!task.files_changed || (!task.files_changed.created.length && !task.files_changed.modified.length)) {
  // Fallback: extract from git diff
  task.files_changed = {
    created: getGitNewFiles(),    // git diff --cached --name-only --diff-filter=A
    modified: getGitModifiedFiles() // git diff --cached --name-only --diff-filter=M
  };
}
```

### 4. Append to History

**Add structured iteration entry:**

```javascript
prd.history.push({
  iteration: prd.config.current_iteration,
  task_id: task.id,
  action: task.status,  // "completed" or "failed"
  timestamp: now,
  commit_hash: COMMIT_HASH,
  duration_seconds: Math.round(
    (new Date(now) - new Date(task.started_at)) / 1000
  ),
  notes: "{What was learned or accomplished during this task}"
});
```

### 5. Increment Iteration and Update Timestamps

**IMPORTANT: Increment AFTER recording the current iteration in task and history.**

```javascript
prd.config.current_iteration++;
prd.updated_at = now;

// Update top-level status
const allCompleted = prd.tasks.every(t =>
  t.status === 'completed' || t.status === 'skipped'
);
const anyFailed = prd.tasks.some(t => t.status === 'failed');
const anyBlocked = prd.tasks.some(t => t.status === 'blocked');

if (allCompleted) {
  prd.status = 'completed';
} else if (anyFailed || anyBlocked) {
  prd.status = 'partial';
} else {
  prd.status = 'in_progress';
}

writeJSON('.ralph/prd.json', prd);
```

### 6. Update progress.txt

**Append learnings to progress.txt:**

```markdown
---

## Iteration {current_iteration}

### Task Completed
[{current_task_id}] {current_task_description}
Category: {current_task_category}
Status: {task.status}
Commit: {COMMIT_HASH}

### Files Changed
- Created: {task.files_changed.created}
- Modified: {task.files_changed.modified}

### Acceptance Criteria
{current_task_criteria}
Result: ✅ Met / ❌ Not met

### Learnings
{What was learned during this task}
{Any issues encountered and how they were resolved}
{Patterns discovered that might help future tasks}

### Context for Next Task
{What the next iteration should know}
```

### 7. Commit prd.json and progress.txt Updates

**Stage and commit the tracking files separately:**

```bash
git add .ralph/prd.json .ralph/progress.txt
# Also stage modules-queue.json if it exists (multi-module tracking)
[ -f .ralph/modules-queue.json ] && git add .ralph/modules-queue.json

git commit -m "$(cat <<'EOF'
chore(ralph): update progress - task {current_task_id}/{tasks_total}

Iteration {current_iteration} complete
Status: {task.status}
{current_module ? "Module: " + current_module : ""}

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
EOF
)"
```

### 8. Verify Commit

**Check commit was created:**

```bash
git log -2 --oneline
```

**Expected output:**
```
def5678 chore(ralph): update progress - task {id}/{total}
abc1234 feat(scope): {current_task_description}
```

### 9. Log Activity (if verbose)

**If {verbose_mode} = true:**

Append to `.ralph/logs/{date}.log`:
```
[{timestamp}] TASK COMPLETED
  Task: [{current_task_id}] {current_task_description}
  Category: {current_task_category}
  Status: {task.status}
  Commit: {COMMIT_HASH}
  Files: {file_count} changed ({created_count} created, {modified_count} modified)
  Duration: {duration_seconds}s
  Iteration: {current_iteration}
  Validation: {validation_result}
```

---

## OUTPUT FORMAT:

```
Changes Committed:

| Field | Value |
|-------|-------|
| Commit | {COMMIT_HASH} |
| Task | [{current_task_id}] {current_task_description} |
| Category | {current_task_category} |
| Status | {task.status} |
| Iteration | {current_iteration} |
| Files | {file_count} changed |
| Duration | {duration_seconds}s |
| Validation | {validation_result} |

prd.json: Task {current_task_id} → {task.status}, history entry added
progress.txt: Iteration {current_iteration} learnings appended

-> Checking completion...
```

---

## ERROR HANDLING:

**If commit fails (pre-commit hook):**

1. Read hook error message
2. Fix the issue (lint, format, etc.)
3. Stage fixes
4. Create NEW commit (don't amend)
5. Proceed to step-04

**If prd.json write fails:**

1. Log error
2. Retry write
3. If still fails, output error and stop

**If task was failed in step-02:**

1. Still commit whatever was done (partial progress)
2. task.status remains "failed"
3. history entry records action: "failed"
4. step-04 will handle downstream blocking

---

## NEXT STEP:

After commit and updates complete, proceed to `./step-04-check.md`
