# Phase 13 Summary: Campaign Orchestration and CLI Commands

## At a Glance

**One-sentence:** Phase 13 wires together the analysis pipeline, LLM layer, and database into a complete campaign lifecycle with functional CLI commands.

### Files Changed

| File | Change |
|------|--------|
| `src/unfamiliar/campaign/types.py` | NEW — Dataclasses for campaign results (CampaignInfo, PersistResult, CompletionResult, CategoryProgress, CampaignProgress) |
| `src/unfamiliar/campaign/discovery.py` | NEW — discover_campaigns() scans ~/.unfamiliar/campaigns/ with orphan detection |
| `src/unfamiliar/campaign/persister.py` | NEW — persist_briefing_data(), persist_pipeline_data() for LLM→DB mapping |
| `src/unfamiliar/campaign/missions.py` | NEW — complete_mission(), unlock_mission(), start_mission() lifecycle functions |
| `src/unfamiliar/campaign/progress.py` | NEW — get_campaign_progress() computes completion stats |
| `src/unfamiliar/campaign/orchestrator.py` | NEW — create_campaign(), resume_campaign() main entry points |
| `src/unfamiliar/campaign/__init__.py` | UPDATED — Public API exports |
| `src/unfamiliar/cli.py` | UPDATED — All placeholder stubs replaced with real implementations |
| `tests/test_cli.py` | UPDATED — Fixed imports for real implementation |

### Key Functions

| Function | Behavior |
|----------|----------|
| `create_campaign()` | Full pipeline: analyze → briefing → missions → persist → return Campaign |
| `resume_campaign()` | Find most recent active/initializing campaign by repo path |
| `discover_campaigns()` | Scan ~/.unfamiliar/campaigns/ for all saved campaigns |
| `complete_mission()` | Mark mission COMPLETED, cascade unlock dependents whose prerequisites are met |
| `unlock_mission()` | Force locked mission to AVAILABLE (escape hatch) |
| `start_mission()` | Transition AVAILABLE mission to IN_PROGRESS |
| `get_campaign_progress()` | Compute per-category and overall completion stats |

### Behavior Changes

- `unfamiliar investigate <repo>` now runs the full pipeline end-to-end (requires API key)
- `unfamiliar campaigns` lists all saved campaigns with status, progress, timestamps
- `unfamiliar resume` shows most recent campaign progress or "No active campaigns"
- Campaign lifecycle fully wired: INITIALIZING → ACTIVE on success

---

## Architecture

```
CLI (cli.py)
    │
    ▼
Orchestrator (campaign/orchestrator.py)
    │
    ├──► Analysis (analyze_repository)
    │
    ├──► LLM (generate_briefing, run_mission_pipeline)
    │
    └──► Database (CampaignDB with repositories)
              │
              ▼
         Persister (campaign/persister.py)
              │
              └──► Models (Mission, Module, Chain, etc.)
```

## Data Flow

1. **create_campaign()** orchestrates:
   - Repository analysis → `AnalysisResult`
   - LLM briefing → `BriefingResult`
   - Mission pipeline → `PipelineResult`
   - Persistence → database records

2. **Mission status state machine:**
   - Root missions (no prerequisites) → `AVAILABLE`
   - Non-root missions → `LOCKED`
   - On complete → check dependents, unlock if all prerequisites met
   - Escape hatch → `unlock_mission()` forces `AVAILABLE`

## Test Coverage

- **Overall:** 81%
- **Campaign module:** 33% (orchestration code requires integration tests with real LLM)
- **CLI tests:** 8 tests, all passing

## Known Issues

1. **Dead code in discovery.py** (lines 145-153): First SQL query uses wrong enum and result is discarded. Should be removed.

## Deferred to Future Phases

- TUI launch (Phase 14-15)
- `reconnect` command full implementation (needs campaign ID lookup)
- Integration tests for orchestrator (requires real LLM calls)
