---
id: S01
parent: M014
milestone: M014
provides:
  - BodySection/BodySubSection Pydantic models for downstream rendering (S05) and DB storage (S03)
  - citation_utils.extract_citations() and validate_citations() for pipeline quality checks
  - stage5_synthesis.txt v5 prompt with v2 output format for pipeline execution (S04)
  - test_harness v2 format support for composition testing (S02)
requires:
  []
affects:
  - S02 — uses updated test harness and prompt for compose mode testing
  - S04 — pipeline uses the v2 prompt and parses v2 output via BodySection models
  - S05 — frontend renders list[BodySection] with TOC and citation links
key_files:
  - backend/pipeline/schemas.py
  - backend/pipeline/citation_utils.py
  - backend/pipeline/test_citation_utils.py
  - backend/pipeline/test_harness.py
  - backend/pipeline/test_harness_v2_format.py
  - prompts/stage5_synthesis.txt
key_decisions:
  - D024: Citations use 0-based indices matching moment list position
  - D024: Sections with subsections use empty-string content; substance lives in subsections
  - Word count includes section.content + subsection.content; heading text excluded
  - Citation report uses CITE log tag for grep-friendly structured output
patterns_established:
  - body_sections v2 format: list[BodySection] with heading/content/subsections, discriminated by body_sections_format='v2'
  - Citation validation as reusable utility — validate_citations() returns a dict with coverage_pct, invalid_indices, uncited_moments for any consumer
  - Prompt backup convention: .bak with timestamp suffix before destructive edits
observability_surfaces:
  - CITE log tag in test harness output for per-page citation coverage reporting
drill_down_paths:
  - .gsd/milestones/M014/slices/S01/tasks/T01-SUMMARY.md
  - .gsd/milestones/M014/slices/S01/tasks/T02-SUMMARY.md
  - .gsd/milestones/M014/slices/S01/tasks/T03-SUMMARY.md
duration: ""
verification_result: passed
completed_at: 2026-04-03T00:55:48.823Z
blocker_discovered: false
---

# S01: Synthesis Prompt v5 — Nested Sections + Citations

**Introduced body_sections v2 format (list-of-objects with H2/H3 nesting and inline [N] citation markers), backed by Pydantic schema, citation validation utility, updated synthesis prompt, and v2-aware test harness — all verified with 28 passing tests.**

## What Happened

This slice replaced the flat dict-based body_sections format with a structured list-of-objects format supporting H2/H3 nesting and inline citation markers.

**T01 — Schema & Citation Utils:** Added BodySection and BodySubSection Pydantic models to schemas.py. BodySection has heading, content, and optional subsections list. Changed SynthesizedPage.body_sections from dict to list[BodySection] and added body_sections_format='v2' discriminator field. Created citation_utils.py with extract_citations() (regex parser for [N] and [N,M] markers) and validate_citations() (returns coverage stats, invalid indices, uncited moments). 15 unit tests cover all edge cases including multi-citation markers, out-of-range indices, subsection citations, and zero-moment edge case.

**T02 — Prompt Rewrite:** Backed up the existing prompt, then made four targeted edits to stage5_synthesis.txt: (1) H3 subsection guidance in the body sections structure section, (2) new Citation rules section defining [N] and [N,M] format with placement conventions, (3) rewrote the Output format JSON example with v2 structure showing both flat and nested sections with inline citations, (4) updated Field rules to describe the new format. All non-output sections (voice, tone, synthesis philosophy) preserved unchanged.

**T03 — Test Harness Update:** Updated two locations in test_harness.py where body_sections was iterated as a dict — now walks BodySection objects for word counting and metadata. Added subsection count reporting and per-page citation coverage logging with a CITE log tag for grep-friendly output. Created test_harness_v2_format.py with 13 tests covering word counting (flat and nested), section counting, citation integration, and SynthesisResult round-trip serialization.

## Verification

All three task verification commands pass:
- `python -m pytest backend/pipeline/test_citation_utils.py -v` — 15/15 passed (0.08s)
- `python -m pytest backend/pipeline/test_harness_v2_format.py -v` — 13/13 passed (0.08s)
- Prompt structure assertion (body_sections_format, Citation rules, subsections present) — passed

Total: 28 tests passing, prompt validates structurally.

## Requirements Advanced

None.

## Requirements Validated

None.

## New Requirements Surfaced

None.

## Requirements Invalidated or Re-scoped

None.

## Deviations

None.

## Known Limitations

The v2 format is schema-validated and test-harnessed but has not been run against a live LLM yet — that happens when the pipeline compose logic (S04) exercises the prompt end-to-end.

## Follow-ups

None.

## Files Created/Modified

- `backend/pipeline/schemas.py` — Added BodySubSection, BodySection models; changed SynthesizedPage.body_sections to list[BodySection]; added body_sections_format='v2'
- `backend/pipeline/citation_utils.py` — New file: extract_citations() and validate_citations() functions
- `backend/pipeline/test_citation_utils.py` — New file: 15 unit tests for citation utilities
- `backend/pipeline/test_harness.py` — Updated word-count and metadata logic from dict iteration to BodySection object walking; added citation coverage reporting
- `backend/pipeline/test_harness_v2_format.py` — New file: 13 tests for v2 format word counting, section counting, citation integration, round-trip
- `prompts/stage5_synthesis.txt` — Added Citation rules section, H3 subsection guidance, rewrote Output format to v2 list-of-objects with citations, updated Field rules
