---
estimated_steps: 31
estimated_files: 2
skills_used: []
---

# T02: Wire optimize CLI subcommand with leaderboard and trajectory output

Add the `optimize` subcommand to `__main__.py` that connects PromptVariantGenerator + OptimizationLoop to the CLI, and add formatted reporting: a leaderboard table and an ASCII score trajectory chart. Write results to a JSON file.

## Context

T01 produced `PromptVariantGenerator` and `OptimizationLoop` with `OptimizationResult`. This task wires them into the existing CLI (which already has `fitness` and `score` subcommands) and adds human-readable output.

## Steps

1. Add `optimize` subparser to `__main__.py`:
   - `--stage` (int, default 5) — pipeline stage to optimize
   - `--iterations` (int, default 10) — number of optimization iterations
   - `--variants-per-iter` (int, default 2) — variants generated per iteration
   - `--file` (str, required) — path to moments JSON fixture
   - `--output-dir` (str, default `backend/pipeline/quality/results/`) — where to write result JSON
   - Validate --stage is 5 (others not yet supported, print message and exit 1 for other values)
   - Create output dir if it doesn't exist
   - Instantiate `OptimizationLoop` with parsed args, call `run()`, handle result

2. Add reporting functions (can be in `__main__.py` or a small `reporting.py`):
   - `print_leaderboard(result: OptimizationResult)` — formatted table showing top 5 variants by composite score, with per-dimension breakdown. Use the same visual style as `ScoreRunner.print_report()` (plain print with alignment, score bars).
   - `print_trajectory(result: OptimizationResult)` — ASCII line chart of composite score across iterations. ~20 rows height, iteration index on x-axis. Simple text rendering (no external deps).
   - Print both after the optimization loop completes.

3. Write results JSON:
   - Save `OptimizationResult` to `{output_dir}/optimize_stage{N}_{timestamp}.json` with: best_prompt, best_scores, full history, config (stage, iterations, variants_per_iter, fixture_path), elapsed_seconds.
   - Create `backend/pipeline/quality/results/.gitkeep` so the directory is tracked.

4. Verify the full CLI flow:
   - `python -m pipeline.quality optimize --help` shows all args
   - `python -m pipeline.quality optimize --stage 5 --iterations 1 --file backend/pipeline/quality/fixtures/sample_moments.json` runs and either produces output (if LLM reachable) or shows clean connectivity error
   - `python -m pipeline.quality optimize --stage 3` prints 'only stage 5 supported' and exits 1

## Must-Haves

- --stage, --iterations, --variants-per-iter, --file, --output-dir CLI args
- Stage validation (only 5 supported currently)
- Leaderboard table printed after loop
- ASCII trajectory chart printed after loop
- Results JSON written to output directory
- Clean error handling (no tracebacks on LLM connectivity failure)

## Inputs

- ``backend/pipeline/quality/variant_generator.py` — PromptVariantGenerator from T01`
- ``backend/pipeline/quality/optimizer.py` — OptimizationLoop and OptimizationResult from T01`
- ``backend/pipeline/quality/__main__.py` — existing CLI with fitness and score subcommands`
- ``backend/pipeline/quality/scorer.py` — ScoreRunner.print_report() style reference for formatting`

## Expected Output

- ``backend/pipeline/quality/__main__.py` — updated with optimize subcommand, leaderboard, trajectory chart, results JSON output`
- ``backend/pipeline/quality/results/.gitkeep` — tracked output directory`

## Verification

python -m pipeline.quality optimize --help && python -m pipeline.quality optimize --stage 3 --iterations 1 --file backend/pipeline/quality/fixtures/sample_moments.json 2>&1 | grep -q 'stage 5'
