# Review-Plan Job Orchestration

> Implementation guide for the IDEA_REVIEW_PLAN job kind and multi-model iterative plan review.

---

## Overview

The review-plan job is an autonomous agent that performs iterative multi-model review of implementation plans (YAML frontmatter + markdown documents). It coordinates three review stages (structure, logic/patterns, risk assessment), detects convergence, and either approves the plan or returns it for manual refinement.

**Job Kind:** `IDEA_REVIEW_PLAN`
**Triggerable From:** `PLAN_READY`, `PLAN_REVIEWED` (re-review)
**Transitions To:** `PLAN_REVIEWED` (approved) or `PLAN_REVIEW_FAILED` (rejected/abandoned)

---

## System Design

### Data Flow

```
User clicks "Review Plan" on PLAN_READY idea
  ↓
startReviewPlanJobAction() queues IDEA_REVIEW_PLAN job
  ↓
Worker claims job via wait_for_job (MCP)
  ↓
Review-plan prompt orchestrates:
  - Ronde 1: Structure check (YAML parsing, format correctness)
  - Ronde 2: Logic & patterns (dependencies, architecture fit)
  - Ronde 3: Risk assessment (edge cases, refactoring, type-safety)
  ↓
Convergence detection: if stable, ask approval
  ↓
On approval: update_idea_plan_reviewed(approval_status='approved')
  → Idea transitions to PLAN_REVIEWED
  → IdeaLog entry created with PLAN_REVIEW_RESULT
  ↓
On rejection: return for manual edit (status → PLAN_REVIEW_FAILED)
```

### Review-Log JSON Schema

The orchestrator produces a detailed JSON log stored in `idea.plan_review_log`:

```typescript
interface ReviewLog {
  plan_file: string;           // Idea code (e.g., "I-042")
  created_at: ISO8601;         // Review start timestamp
  
  rounds: Array<{
    round: number;             // 0, 1, 2 (structure, logic, risk)
    model: string;             // claude-3-5-haiku | claude-3-5-sonnet | claude-opus-4-7
    role: string;              // "Structure Review" | "Logic & Patterns" | "Risk Assessment"
    focus: string;             // Review focus summary
    plan_before: string;       // Original plan_md at round start
    plan_after: string;        // Revised plan after feedback
    issues: Array<{
      category: 'structure' | 'logic' | 'risk' | 'pattern';
      severity: 'error' | 'warning' | 'info';
      suggestion: string;      // Concrete fix recommendation
    }>;
    score: number;             // 0-100 review score
    plan_diff_lines: number;   // Changed lines in this round
    converged: boolean;        // Did this round trigger convergence?
    timestamp: ISO8601;        // Round completion time
  }>;
  
  convergence?: {
    stable_at_round: number;   // Round where convergence was detected
    final_diff_pct: number;    // Percentage of changed lines at convergence
    convergence_metric: string; // "plan_stability" (constant for now)
  };
  
  approval: {
    status: 'pending' | 'approved' | 'rejected';
    timestamp?: ISO8601;       // When user made decision
  };
  
  summary: string;            // 1–2 sentence summary for IdeaLog
}
```

---

## Assumptions & Constraints

### Prompt Assumptions

1. **Plan Format:** Idea's `plan_md` field contains YAML frontmatter (parsed at PLAN_READY) + markdown body.
   - Frontmatter keys: `pbi`, `stories`, `tasks`, `priority`, `verify_required`.
   - If parse fails, orchestrator transitions idea to `PLAN_REVIEW_FAILED`.

2. **Context Availability:** The job payload includes:
   - `idea.plan_md`: The plan to review (required)
   - `idea.grill_md`: Context from grill phase (optional but recommended)
   - `product.definition_of_done`: Product-level acceptance criteria
   - `repo_url`: Local repository for pattern inspection

3. **User Availability:** At least one worker is active (server-side check via `countActiveWorkers`).

4. **No External APIs:** Orchestrator performs reviews entirely with information from job context. No external codex or multi-model APIs are called directly.
   - Future improvement: Codex-injection from `docs/patterns/**/*.md` and `docs/architecture/**/*.md`.

### Convergence Detection Assumptions

1. **Stability Metric:** Two consecutive rounds with < 5% line changes = convergence.
   - Threshold is hardcoded; future: make configurable per product.
   - Diff percentage = `(changed_lines / total_lines) * 100`.

2. **Max Iterations:** 3 initial rounds + 2 optional extra rounds (total max 5) before forced approval.

3. **No Infinite Loops:** If max iterations reached, approval gate enforces a decision.

### Validation Assumptions

1. **Plan is Mutable:** Orchestrator can revise `plan_md` between rounds without breaking downstream parsing.
   - If YAML structure is corrupted, `parsePlanMd` (server-side) will fail on approval.
   - Orchestrator should never corrupt YAML syntax.

2. **IdeaLog Persistence:** MCP tool `update_idea_plan_reviewed` atomically saves:
   - `idea.plan_review_log` (full JSON)
   - `idea.reviewed_at` (timestamp)
   - `idea.status` (transition)
   - `IdeaLog` entry (audit)

3. **User Decisions are Final:** Once approved, plan-review log is immutable (until next re-review).

---

## Implementation Details

### Prompt Location

- **Main Repo:** `lib/idea-prompts/review-plan-job.md`
- **MCP Server:** `scrum4me-mcp/src/prompts/idea/review-plan.md`
- **Synchronization:** Manual (for now); future: sync-schema.sh-like mechanism.

### Job Config Snapshot

Job created with config from `lib/job-config.ts`:

```typescript
IDEA_REVIEW_PLAN: {
  model: 'claude-opus-4-7',       // Opus for final orchestration
  thinking_budget: 6000,          // Extended for multi-round analysis
  permission_mode: 'acceptEdits',
  max_turns: 1,
  allowed_tools: [
    'Read', 'Write', 'Grep', 'Glob',
    'mcp__scrum4me__update_idea_plan_reviewed',
    'mcp__scrum4me__log_idea_decision',
    'mcp__scrum4me__update_job_status',
    'mcp__scrum4me__ask_user_question',
  ],
}
```

**Note:** Model is fixed to Opus for orchestration. Individual review rounds are simulated (not actual model switching) within Opus's analysis. Future: Direct multi-model support via Claude API.

### MCP Tool: update_idea_plan_reviewed

**Location:** `scrum4me-mcp/src/tools/update-idea-plan-reviewed.ts`

**Input:**
```typescript
{
  idea_id: string;
  review_log: object;  // Full ReviewLog JSON
  approval_status?: 'pending' | 'approved' | 'rejected';
}
```

**Behavior:**
1. Validates user owns idea.
2. Transitions idea status:
   - `approval_status='approved'` → `PLAN_REVIEWED`
   - `approval_status='rejected'` → `PLAN_REVIEW_FAILED`
   - Default → `PLAN_REVIEWED`
3. Saves `plan_review_log` and `reviewed_at` atomically.
4. Creates `IdeaLog` entry with type `PLAN_REVIEW_RESULT`.

---

## Dependencies

### Database

- **Idea Model:** Must have fields `plan_review_log` (Json), `reviewed_at` (DateTime).
- **IdeaStatus Enum:** Must include `REVIEWING_PLAN`, `PLAN_REVIEW_FAILED`, `PLAN_REVIEWED`.
- **IdeaLogType Enum:** Must include `PLAN_REVIEW_RESULT`.

### Server Actions

- `startReviewPlanJobAction()` — Queues job, enforces status transitions.
- `cancelIdeaJobAction()` — Allows user to cancel mid-review (reverts to `PLAN_READY`).

### MCP Tools

- `update_idea_plan_reviewed()` — Saves review-log and transitions status.
- `log_idea_decision()` — Logs convergence/approval decisions.
- `update_job_status()` — Marks job as done/failed.
- `ask_user_question()` — Approval gate interaction.

### Files

- `lib/idea-prompts/review-plan-job.md` — Orchestrator prompt.
- `scrum4me-mcp/src/prompts/idea/review-plan.md` — MCP server copy.
- `scrum4me-mcp/src/lib/kind-prompts.ts` — Prompt loader.
- `scrum4me-mcp/src/tools/wait-for-job.ts` — Job context builder.

---

## Error Handling

### Parse Failures

If `plan_md` cannot be parsed as valid YAML frontmatter:
1. Orchestrator logs error in review_log.
2. Calls `update_job_status('failed', error: 'plan_parse_failed')`.
3. Idea remains in `REVIEWING_PLAN` (no transition).
4. User can manually edit `plan_md` and retry.

### User Cancellation

If user cancels job via UI:
1. Server sets job status → `CANCELLED`.
2. Worker receives no further answer from `ask_user_question`.
3. Orchestrator gracefully saves partial review_log.
4. Calls `update_job_status('skipped', ...)`.
5. Idea reverts to `PLAN_READY`.

### Question Timeout

If approval question expires (24h):
1. Orchestrator logs timeout in review_log.
2. Calls `update_job_status('failed', error: 'approval_timeout')`.
3. Idea reverts to `PLAN_READY`.

---

## Testing Strategy

### Unit Tests

- **Mock ReviewLog Generation:** Verify review-log JSON structure matches schema.
- **Convergence Calculation:** Diff percentage computation, stability threshold.
- **Status Transitions:** Valid state machine paths (PLAN_READY → REVIEWING_PLAN → PLAN_REVIEWED).

### Integration Tests

- **End-to-End:** Draft idea → Grill → Plan → Review → PLAN_REVIEWED.
- **Re-Review:** PLAN_REVIEWED → REVIEWING_PLAN → PLAN_REVIEWED (no data loss).
- **Cancellation:** Mid-review cancellation → revert to PLAN_READY.
- **Parse Errors:** Malformed plan_md → PLAN_REVIEW_FAILED.

### Manual Testing

1. Create test idea with PLAN_READY status.
2. Click "Review Plan".
3. Monitor job in Jobs dashboard.
4. Verify review-log in idea detail page.
5. Accept/reject approval.
6. Confirm status transition and IdeaLog entry.

---

## Future Enhancements

1. **Direct Multi-Model Calls:** Use Claude API to invoke Haiku, Sonnet, Opus separately with model switching.
2. **Codex Injection:** Auto-load and inject `docs/patterns/**/*.md` and `docs/architecture/**/*.md` as context.
3. **Configurable Thresholds:** Allow product-level convergence percentage and max-rounds settings.
4. **Review History:** Preserve all review-logs for audit trail and re-review diffs.
5. **Feedback Loop:** Log user edits between review rounds and suggest re-run based on delta.
6. **Scheduled Re-Review:** Auto-trigger review after N days (staleness check).

---

## References

- `docs/architecture/jobs.md` — Job system architecture.
- `docs/patterns/server-action.md` — Server action pattern (startReviewPlanJobAction).
- `docs/api/rest-contract.md` — API surface for plan-review.
- `lib/idea-status.ts` — Status transition graph and state machine.
- `lib/idea-plan-parser.ts` — Plan YAML parsing (validator for approved plans).
