Road to 10 — Wave 2 · PR-T4

Handoff bundle schema validator

7 fixture assertions · guards the #1400 agent schema rewrite

What it locks

#1400 rewrote the orchestrator agent's expected schema from a speculative JSON manifest to the real gzipped-tarball layout observed during the #1399 dogfood. Nothing enforced that contract. PR-T4 adds a validator script + 7 fixture tests so a future refactor can't silently break bundle parsing.

Observed schema (from #1400)

<project-name>/
├── README.md           required
├── chats/
│   └── chat*.md        required — ≥ 1
└── project/
    └── *.html          optional — absent = incomplete bundle

Fixture matrix

#FixtureExpected exitWhy
1complete (README + chats + project/*.html)0happy path
2incomplete (README + chats, no project/)0assistant waiting for clarification — still valid
3no README.md1structural violation
4no chats/ dir1transcript is load-bearing (per README)
5empty chats/ dir1no .md files = no transcript
6non-tarball input (plain text)1 or 2not a real bundle
7missing input path2tool/IO error, not a schema issue

Local run output

$ bash tests/unit/test-handoff-bundle-schema.sh

   complete bundle validates (exit 0)
   incomplete bundle validates (exit 0 — expected)
   missing README.md → exit 1
   missing chats/ → exit 1
   empty chats/ → exit 1
   non-tarball rejected (exit 1)
   missing input → exit 2 (tool/IO error)

════════════════════════════════════════════════════════════════
  Total: 7  |  Passed: 7  |  Failed: 0
════════════════════════════════════════════════════════════════

Design choices

Wave 2 progress (4 of 5)

PR-T1   formatStars unit test                ✓ merged (#1412)
PR-T2   sync_versions round-trip             ✓ merged (#1414)
PR-T3   Playwright E2E for landing           #1415 (open, CI running)
PR-T4   handoff bundle schema validator      ← THIS PR
PR-T5   stub-fallback integration test       last