---
id: S04
parent: M013
milestone: M013
provides:
  - Multi-stage optimize CLI: `python -m pipeline.quality optimize --stage N` for N in {2,3,4,5}
  - STAGE_CONFIGS registry for per-stage scoring rubrics and config
  - Stage 2-4 fixture files for testing
requires:
  []
affects:
  []
key_files:
  - backend/pipeline/quality/scorer.py
  - backend/pipeline/quality/variant_generator.py
  - backend/pipeline/quality/optimizer.py
  - backend/pipeline/quality/__main__.py
  - backend/pipeline/quality/fixtures/sample_segments.json
  - backend/pipeline/quality/fixtures/sample_topic_group.json
  - backend/pipeline/quality/fixtures/sample_classifications.json
key_decisions:
  - Used backward-compat properties on ScoreResult instead of migrating all callers
  - Stage-specific user prompt building via _build_user_prompt() dispatch in optimizer
patterns_established:
  - STAGE_CONFIGS registry pattern: centralized config objects per pipeline stage with rubric, dimensions, format markers, fixture keys, prompt file, and schema class
  - Templatized meta-prompt with {dimension_descriptions} placeholder for stage-agnostic variant generation
observability_surfaces:
  - none
drill_down_paths:
  - .gsd/milestones/M013/slices/S04/tasks/T01-SUMMARY.md
  - .gsd/milestones/M013/slices/S04/tasks/T02-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-04-01T09:26:23.089Z
blocker_discovered: false
---

# S04: Expand to Pipeline Stages 2-4

**Extended the prompt optimization loop from stage-5-only to stages 2-5 with per-stage scoring rubrics, fixtures, schema dispatch, and user prompt building.**

## What Happened

This slice generalized the quality optimization infrastructure from a stage-5-only system to a multi-stage system covering pipeline stages 2-5.

**T01 — STAGE_CONFIGS registry and generalized scoring:** Built a `STAGE_CONFIGS` registry mapping stages 2-5 to `StageConfig` objects containing per-stage rubrics, dimension lists, format markers, fixture key requirements, prompt file names, and schema class references. Generalized `ScoreResult` from named float fields to a `scores: dict[str, float]` with backward-compatible properties for stage 5 callers. Added `score_stage_output()` to `ScoreRunner` for arbitrary stage scoring. Updated `PromptVariantGenerator` with a templatized meta-prompt that accepts `{dimension_descriptions}` per stage and accepts `format_markers`/`stage` parameters.

**T02 — Stage-aware optimizer and CLI:** Rewrote `OptimizationLoop` to be fully stage-aware: constructor validates stage against `STAGE_CONFIGS`, `_load_fixture()` validates against per-stage fixture keys, `_score_variant()` dispatches per-stage with stage-appropriate user prompts and schema parsing via `_build_user_prompt()`. Created fixture files for stages 2-4 (`sample_segments.json`, `sample_topic_group.json`, `sample_classifications.json`). Removed the stage-5 gate from the CLI — `optimize --stage N` now works for N in {2, 3, 4, 5} with proper validation rejecting other values. Fixed a T01 mismatch where stage 5 `fixture_keys` used `key_moments` instead of `moments`.

## Verification

All slice verification checks pass:

1. **STAGE_CONFIGS registry**: Stages 2-5 all present with correct dimensions, prompt files, and schema classes
2. **ScoreResult generalization**: `scores` dict works; backward-compat `.structural` property resolves correctly
3. **Variant generator**: Imports clean with templatized meta-prompt
4. **Optimizer**: Imports clean, constructs for all stages 2-5 with mock client
5. **CLI**: `--help` shows stage parameter; stage 6 rejected with clear error message
6. **Fixture loading**: All 4 stage fixtures load and validate against their stage's `fixture_keys`

## Requirements Advanced

None.

## Requirements Validated

None.

## New Requirements Surfaced

None.

## Requirements Invalidated or Re-scoped

None.

## Deviations

T01 added SCORING_RUBRIC backward-compat alias and templatized VARIANT_META_PROMPT (not in original plan). T02 fixed stage 5 fixture_keys mismatch from T01 (moments vs key_moments).

## Known Limitations

None.

## Follow-ups

None.

## Files Created/Modified

- `backend/pipeline/quality/scorer.py` — Added STAGE_CONFIGS registry with StageConfig dataclass, generalized ScoreResult to scores dict, added score_stage_output() method
- `backend/pipeline/quality/variant_generator.py` — Templatized meta-prompt with {dimension_descriptions}, added format_markers/stage params to generate()
- `backend/pipeline/quality/optimizer.py` — Rewrote to be stage-aware: validates stage, dispatches fixture loading/scoring/prompts per stage config
- `backend/pipeline/quality/__main__.py` — Removed stage-5 gate, validates stages 2-5, uses per-stage dimensions in leaderboard output
- `backend/pipeline/quality/fixtures/sample_segments.json` — New stage 2 fixture with transcript segments
- `backend/pipeline/quality/fixtures/sample_topic_group.json` — New stage 3 fixture with topic group segments
- `backend/pipeline/quality/fixtures/sample_classifications.json` — New stage 4 fixture with moments and taxonomy
