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).

Lesson hero for OBS post-fest Whisper clips_index handoff receipt

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


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.