---
id: S02
parent: M014
milestone: M014
provides:
  - stage5_compose.txt prompt for S04 pipeline compose-or-create logic
  - build_compose_prompt() function for S04 to call from pipeline stages
  - compose CLI subcommand for offline testing of composition before pipeline integration
requires:
  - slice: S01
    provides: v2 SynthesisResult schema and body_sections format used by composition output
affects:
  - S04
key_files:
  - prompts/stage5_compose.txt
  - backend/pipeline/test_harness.py
  - backend/pipeline/test_harness_compose.py
  - conftest.py
key_decisions:
  - Composition prompt is self-contained — carries its own writing standards rather than importing from synthesis prompt at runtime
  - Offset-based citation scheme: existing keep [0]-[N-1], new get [N]-[N+M-1], no renumbering of existing citations
  - Compose accepts both harness output (with .pages[]) and raw SynthesizedPage JSON
  - Root conftest.py bootstraps backend/ onto sys.path for project-root test discovery via pipeline symlink
patterns_established:
  - Compose prompt pattern: XML-tagged inputs with offset-based citation indexing for multi-source content merging
  - Test harness subcommand pattern: build_*_prompt() pure function + run_*() orchestrator + CLI wiring
observability_surfaces:
  - none
drill_down_paths:
  - .gsd/milestones/M014/slices/S02/tasks/T01-SUMMARY.md
  - .gsd/milestones/M014/slices/S02/tasks/T02-SUMMARY.md
  - .gsd/milestones/M014/slices/S02/tasks/T03-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-04-03T01:10:16.667Z
blocker_discovered: false
---

# S02: Composition Prompt + Test Harness Compose Mode

**Composition prompt, test harness compose subcommand, and 16 unit tests enable offline testing of merging new video moments into existing technique pages with correct citation re-indexing.**

## What Happened

Three tasks delivered the composition pipeline's offline testing surface:

T01 wrote `prompts/stage5_compose.txt` — a self-contained LLM prompt for merging new video moments into existing technique pages. It defines four XML input tags (`<existing_page>`, `<existing_moments>`, `<new_moments>`, `<creator>`), offset-based citation re-indexing (existing moments keep [0]-[N-1], new moments get [N]-[N+M-1]), merge/enrich/dedup rules with concrete examples, workflow-ordered section placement, and v2 SynthesisResult output format with two validated JSON examples.

T02 added `build_compose_prompt()` and `run_compose()` to the test harness, plus a `compose` CLI subcommand. The prompt builder constructs the XML-tagged user prompt with correct citation index offsets. `run_compose()` loads an existing page JSON + two fixture files (original moments and new moments), filters new moments by category, calls the LLM with the compose system prompt, validates the output as SynthesisResult, and logs compose-specific metrics (word count before/after, sections before/after).

T03 created 16 unit tests in `test_harness_compose.py` covering prompt XML structure (6 tests), citation offset arithmetic (4 tests), category filtering (2 tests), and edge cases (4 tests including empty moments, single moment, no subsections, large offsets). All pass in 0.4s.

A root-level `conftest.py` was added to bootstrap `backend/` onto `sys.path`, fixing test discovery when running from the project root via the `pipeline` symlink.

## Verification

All three verification gates pass:
1. `python -m pytest pipeline/test_harness_compose.py -v` — 16/16 passed (0.40s) from project root
2. `cd backend && python -m pipeline.test_harness compose --help` — exits 0, correct arg listing
3. Structural validation of `prompts/stage5_compose.txt` — 13053 chars, all required sections present, JSON examples parse valid

## Requirements Advanced

- R012 — Composition prompt and harness provide the offline-testable merge mechanism for updating existing technique pages with new video content

## Requirements Validated

None.

## New Requirements Surfaced

None.

## Requirements Invalidated or Re-scoped

None.

## Deviations

Added root-level conftest.py to fix sys.path for project-root test execution — not in original plan but required for the verification command to work without cd backend prefix.

## Known Limitations

run_compose() requires an LLM endpoint to actually test composition end-to-end. The unit tests validate prompt construction and plumbing only.

## Follow-ups

None.

## Files Created/Modified

- `prompts/stage5_compose.txt` — New composition prompt with merge rules, citation re-indexing, dedup guidance, two v2 JSON examples
- `backend/pipeline/test_harness.py` — Added build_compose_prompt(), run_compose(), and compose CLI subcommand
- `backend/pipeline/test_harness_compose.py` — 16 unit tests for compose prompt construction, citation math, category filtering, edge cases
- `conftest.py` — Root-level sys.path bootstrap for project-root test discovery via pipeline symlink
