Lesson 288: OBS Post-Fest Whisper Handoff clips_index Receipt on BUILD_RECEIPT (2026)
Direct answer: Before March 2027 GPU nights declare Whisper backlog GREEN, promote post_fest_whisper_handoff_receipt_v1.json with W1–W6—import February clips_index[] / deferred_to_post_fest_batch[], prove every OBS media_path still on disk, reject January capture_date sort, loudness-spot P1/P2 before batch, and fail-close post_fest_whisper_handoff_ok on BUILD_RECEIPT so holiday inbox folklore cannot replace fest-day order. Pair Guide #48, post-fest handoff strategy, and cousin Lesson 273 (loudness—not handoff schema).

Why this matters now (March Whisper drain after February live week)
March week three is when facilitators open Whisper and accidentally sort playtest-vod/inbox/holiday-2026/ while D4 soft-locks wait under february-live/deferred/. Lesson 287 owns weekly sprint jsonl; 288 owns the OBS clips_index handoff BUILD_RECEIPT latch that closes the February→March arc for the RPG track.
Guide #48 is the ninety-second OBS path gate; this lesson is the BUILD_RECEIPT milestone + verify script for the course project.
Beginner path (55-minute handoff latch)
| Step | Action | Success check |
|---|---|---|
| 1 | Open February triage receipt | deferred_to_post_fest_batch[] present |
| 2 | Import to clips_index_import.json |
Row count matches annex |
| 3 | Walk every OBS media_path |
No MISSING lines |
| 4 | Sort table P1→P2→P3 by fest_day | No January-only sort |
| 5 | Loudness-spot P1/P2 merges | loudness_spot_ok or skip note |
| 6 | File handoff receipt + run verify | Exit 0 |
| 7 | Latch BUILD_RECEIPT post_fest_whisper_handoff_ok |
Boolean after verify |
Time: ~55 minutes first post-fest Monday; ~15 minutes when paths already pinned.
Prerequisites: OBS 30+ Replay fragments under evidence root; February triage + Sunday/debrief annex; jq + Bash/Git Bash; Guide #48 bookmarked.
Developer path (gates W1–W6)
| Gate | Check | Fail when |
|---|---|---|
| W1 | Import February deferred / clips_index | Empty without waiver; January inbox used |
| W2 | Every row has OBS media_path on disk |
Orphan fragment |
| W3 | Drain order P1→P2→P3 + fest_day | capture_date-only holiday sort |
| W4 | P1/P2 loudness before Whisper | Silent merge into GPU batch |
| W5 | whisper_done ⇒ transcript file exists |
Boolean without path |
| W6 | Receipt + capstone pointer + verify | post_fest_whisper_handoff_ok without verify |
Cross-cutting: Do not mix january_whisper_batch_receipt_v1 with handoff schema. Do not open Whisper tag map before remaining count is 0 or waived.
Cousin receipt crosswalk
| Field | Lesson 273 loudness | February same-day triage | This lesson (288) |
|---|---|---|---|
| Schema | playtest_vod_loudness_spot_receipt_v1 |
february_live_whisper_triage_receipt_v1 |
post_fest_whisper_handoff_receipt_v1 |
| Window | Pre-Whisper audio | D1–D7 P0 + deferred | March post-fest drain |
| Pass field | loudness_spot_ok |
february_live_whisper_p0_ok |
post_fest_whisper_handoff_ok |
Reference cousins in cousin_receipts—do not flatten schemas.
W1–W2 — Import + OBS path walk (course project)
SRC="release-evidence/ai/FEBRUARY_LIVE_WHISPER_TRIAGE_RECEIPT.json"
jq -e '.deferred_to_post_fest_batch | length >= 0' "$SRC"
jq '.deferred_to_post_fest_batch' "$SRC" > playtest-vod/post-fest/clips_index_import.json
jq -r '.[].media_path // .[].path // empty' playtest-vod/post-fest/clips_index_import.json \
| while IFS= read -r p; do
test -f "$p" || { echo "MISSING: $p"; exit 3; }
done
W3 — Reject January sort
Build facilitator table (P1 first). Fail if the only sort key is holiday capture_date.
| fragment_id | fest_day | priority | build_label | media_path |
|---|---|---|---|---|
| fragment_p1_04 | D4 | P1 | …-hotfix1 | playtest-vod/february-live/deferred/… |
| fragment_p2_09 | D5 | P2 | …-hotfix1 | … |
W4 — Loudness before Whisper (Lesson 273 cousin)
After normalize/concat for batch_1, run Lesson 273 / Audacity #35. Set loudness_spot_ok: true on P1/P2 only when LUFS spot passes.
W5–W6 — Receipt + verify + BUILD_RECEIPT
{
"schema": "post_fest_whisper_handoff_receipt_v1",
"sprint_window": "2027-03-post-fest-sprint",
"february_live_whisper_source_path": "release-evidence/ai/FEBRUARY_LIVE_WHISPER_TRIAGE_RECEIPT.json",
"march_capstone_pointer": "release-evidence/post-fest/MARCH_CAPSTONE_CLOSEOUT_RECEIPT.json",
"clips_index": [
{
"fragment_id": "fragment_p1_04",
"fest_day": "D4",
"priority": "P1",
"build_label": "february-fest-2027-live-rc3-hotfix1",
"source": "february_live",
"media_path": "playtest-vod/february-live/deferred/fragment_p1_04.mkv",
"batch_night": "batch_1",
"loudness_spot_ok": true,
"whisper_done": false,
"transcript_path": null
}
],
"drain_order": ["P1", "P2", "P3"],
"cousin_receipts": {
"loudness": "release-evidence/audio/loudness/PLAYTEST_VOD_LOUDNESS_SPOT_RECEIPT.json",
"march_weekly": "release-evidence/post-fest/MARCH_SPRINT_RECEIPT_LATEST.json"
},
"clips_index_remaining_count": 1,
"post_fest_whisper_handoff_ok": false,
"notes": "inventory GREEN; Whisper nights still open"
}
Pin at release-evidence/ai/POST_FEST_WHISPER_HANDOFF_RECEIPT.json.
./scripts/verify_post_fest_whisper_handoff.sh \
release-evidence/ai/POST_FEST_WHISPER_HANDOFF_RECEIPT.json \
release-evidence/ai/FEBRUARY_LIVE_WHISPER_TRIAGE_RECEIPT.json
When drain completes (or producer waiver for leftover P3), set post_fest_whisper_handoff_ok: true and clips_index_remaining_count: 0 (or waived note), then latch BUILD_RECEIPT:
{
"post_fest_whisper_handoff_ok": true,
"post_fest_whisper_handoff_receipt": "release-evidence/ai/POST_FEST_WHISPER_HANDOFF_RECEIPT.json",
"clips_index_remaining_count": 0
}
Minimum verify sketch:
#!/usr/bin/env bash
set -euo pipefail
HAND="${1:-release-evidence/ai/POST_FEST_WHISPER_HANDOFF_RECEIPT.json}"
SRC="$(jq -r '.february_live_whisper_source_path' "$HAND")"
jq -e '.schema == "post_fest_whisper_handoff_receipt_v1"' "$HAND"
test -f "$SRC"
jq -e '.post_fest_whisper_handoff_ok == true' "$HAND"
jq -r '.clips_index[] | select(.whisper_done==true) | .transcript_path' "$HAND" \
| while IFS= read -r t; do test -f "$t" || exit 4; done
echo "post_fest_whisper_handoff verify: OK"
Relationship to Guide / strategy / loudness / weekly
| Artifact | Role |
|---|---|
| Guide #48 | Ninety-second OBS path gate |
| Handoff strategy blog | Drain policy + W1–W6 depth |
| This lesson | BUILD_RECEIPT milestone |
| Lesson 273 | Loudness cousin before GPU |
| Lesson 287 | Weekly sprint cousin (not Whisper) |
| Help #47 forward | Schema-drift recovery |
Order: February triage GREEN → Guide #48 W1–W6 → this lesson latch → Whisper tag map on transcripts only.
Common mistakes
- Restarting with January holiday inbox sort.
- Flipping handoff OK while OBS fragments are MISSING.
- Whisper before loudness on P1/P2.
- Opening GitHub issues from memory without transcripts.
- Treating Lesson 287 weekly GREEN as Whisper drain proof.
Troubleshooting
| Symptom | Fix |
|---|---|
| W2 MISSING after OneDrive move | Re-run KFM path proof; update relative paths |
| Empty deferred list | File receipt with clips_index: [] + note—still latch OK |
| Silent batch | Lesson 273 loudness before GPU |
| Tag map invents repro | Wait for W5 transcripts |
| Capstone pointer broken | Friday March closeout first |
Arc continuity (284–288)
| Lesson | Milestone |
|---|---|
| 284 | Post-fest debrief facilitator card |
| 285 | GameMaker October RC branch label |
| 286 | Construct post-fest wishlist velocity |
| 287 | Unity March weekly sprint jsonl |
| 288 (this) | OBS post-fest Whisper clips_index handoff |
Previous: Lesson 287 — Unity March weekly sprint jsonl
Next: Lesson 289 — Ren'Py localization string freeze
FAQ
Does 288 replace February same-day triage?
No—same-day owns D1–D7 P0; 288 imports deferred rows for March drain.
Can empty clips_index still pass?
Yes—with explicit note and clips_index_remaining_count: 0.
Is Help #47 required first?
Only when schema already drifted—prevention is Guide #48 + this lesson.
Related GamineAI reads
- Post-fest Whisper batch handoff strategy
- OBS clips_index handoff preflight (Guide #48)
- February same-day Whisper triage
- January holiday batch cousin
- Lesson 273 — Audacity loudness before Whisper
- Lesson 287 — March weekly sprint jsonl
- Whisper tag extraction without invented repro
- Sunday February closeout
- Official: OBS Studio · OpenAI Whisper
March Whisper lies when GPU nights sort January inboxes—import February clips_index[], prove OBS paths, drain P1→P2→P3, loudness then Whisper, verify, then latch post_fest_whisper_handoff_ok.