AI Voice QA Reason-Codes - When Models Generate Wrong WAV Tags Gate and Escalate 2026
The AI voice tool exported facilitator_vo_07.wav. It sounds fine. ffprobe duration matches the script. Legal still blocked the reel because consent_scope reads public_marketing—not in your consent schema registry. Audio re-ran ffmpeg three times. Nothing changed. The tag was wrong at generation, not at mux.
June–July 2026 micro-studios route more facilitator lines through ElevenLabs-style generators, local TTS, and batch cloud APIs before Audacity handoff. Without reason-code governance, every failure looks like “metadata broke again”—teams burn nights on mux challenge when they should re-prompt or re-embed once.
This AI Integration / Workflow article defines AI voice QA reason-codes: a triage ladder that separates generation, conversion, mux survival, and registry mismatch—then maps each code to owner, fix, and receipt fields in ai_voice_qa_reason_codes_receipt_v1.json.
Non-repetition note: Local Whisper VOD triage owns playtest clip transcription. Metadata-as-artifact opinion owns culture. ffprobe matrix owns duration drift codes (D1–D6). This URL owns WAV tag QA taxonomy for AI-generated facilitator VO.
Who this workflow is for
| Audience | Outcome |
|---|---|
| Audio lead | Assign one primary reason-code per failed line |
| ML / tools engineer | Wire generator output against registry enums |
| Producer | Escalate to correct owner in standup |
| Beginner PM | Stop blaming ffmpeg when tags were never valid |
Time: 50 minutes read; 2 hours to wire first reason-code sheet + receipt template.
Prerequisites: consent_schema_registry_v1.json, at least one AI VO export in art/voice/.
Why this matters now (June–July 2026)
- AI VO in highlight reels — July trend playbook makes waveform proof default; generators do not read your registry.
- Plausible wrong strings — Models emit
consent_scope: promotionalthat pass casual human skim. - Mis-routed fixes — Three ffmpeg retries on a G1_GENERATION failure waste a sprint.
- Receipt sprawl — Top 20 hub receipt #5 needs a failure class column.
- Escalation gaps — No owner when legal, audio, and AI vendor each assume the other fixed tags.
Direct answer: Run gates Q1–Q6 on every AI-sourced WAV → assign exactly one primary reason-code → execute the fix lane → file ai_voice_qa_reason_codes_receipt_v1.json before mux night.
Two-lane mental model
| Lane | Question | Tooling |
|---|---|---|
| Audio quality | Intelligible? Clipped? | Ears, LUFS meters |
| Compliance tags | Registry-valid embedded fields? | RIFF/iXML read, registry JSON |
This article is compliance tags only. Do not merge “robot voice” tickets with G1_GENERATION unless tags are also wrong.
Reason-code catalog (primary)
Assign one primary code per asset_id; add secondary only when migration logs require it.
| Code | Meaning | Owner | First fix |
|---|---|---|---|
| G1_GENERATION | Model output wrong/missing tag keys or values | AI pipeline | Re-prompt with registry enum injection |
| G2_EMBED_FAIL | Tags in sidecar JSON but not in WAV bytes | Audio lead | Re-embed via Audacity V2 |
| G3_CONVERSION_STRIP | Tags lost in format convert (not mux) | Audio lead | Fix export preset; see iXML case study |
| G4_MUX_SURVIVAL | Tags present pre-mux, gone post-mux | Reel lead | Mux challenge M5 |
| G5_REGISTRY_MISMATCH | Tag present but not in consent_scope_enum |
Legal + PM | Registry bump or scope correction |
| G6_LOG_DRIFT | WAV tags disagree with consent_log.csv |
Producer | Migrate log or re-export WAV |
| G7_DURATION_ONLY | Tags OK; ffprobe matrix FAIL | Audio lead | Duration lane—not this article’s codes |
| G8_HUMAN_OVERRIDE | Documented legal waiver | Legal | Receipt waiver_ticket |
G7 routes out—prevents mis-labeling clock issues as AI failures.
Gates Q1–Q6 (triage workflow)
| Gate | Minutes | Pass when |
|---|---|---|
| Q1 Ingest lock | 5 | asset_id, generator, model version recorded |
| Q2 Sidecar vs bytes | 10 | Sidecar JSON matches embedded read |
| Q3 Registry enum | 10 | All keys in registry; values ∈ enums |
| Q4 consent_log join | 10 | WAV matches CSV row for consent_record_id |
| Q5 Pre-mux survival spot | 15 | Optional dry-run if chain includes AI→ffmpeg |
| Q6 Receipt + escalation | 10 | Reason-code filed; owner tagged |
Q1 — Ingest lock (beginner)
Create release-evidence/audio/ai-voice/INGEST_LOG.csv:
| column | example |
|---|---|
asset_id |
facilitator_vo_07 |
generator |
vendor_x_tts_v3 |
model_version |
2026-05-26 |
prompt_hash |
sha256:abc… |
registry_version |
2026-05-playtest-july-v2 |
Beginner mistake: Renaming file without updating asset_id—breaks join to clip_plan.
Q2 — Sidecar vs bytes (developer)
Many AI tools write facilitator_vo_07.meta.json beside WAV:
{
"consent_record_id": "a1b2c3d4-0001-4000-8000-000000000001",
"consent_scope": "highlight_reel",
"consent_expires": "2027-12-31",
"opt_out": false
}
Q2 FAIL patterns:
| Observation | Code |
|---|---|
| Sidecar OK, WAV empty | G2_EMBED_FAIL |
| Sidecar wrong enum | G1_GENERATION |
| Both wrong same way | G1_GENERATION |
| Sidecar OK, WAV wrong different | G3_CONVERSION_STRIP |
def q2_compare(sidecar: dict, wav_fields: dict) -> str | None:
if sidecar == wav_fields:
return None
if not wav_fields.get("consent_record_id"):
return "G2_EMBED_FAIL"
if sidecar.get("consent_scope") != wav_fields.get("consent_scope"):
return "G3_CONVERSION_STRIP"
return "G1_GENERATION"
Q3 — Registry enum check
Load registry from governance #20:
REG=release-evidence/governance/consent_schema_registry_v1.json
SCOPE=$(extract_scope_from_wav vo_line_07.wav) # your inspector
jq -e --arg s "$SCOPE" '.consent_scope_enum | index($s)' "$REG" || echo G5_REGISTRY_MISMATCH
| Symptom | Code |
|---|---|
public_marketing not in enum |
G5_REGISTRY_MISMATCH |
Typo highlight_reels |
G5 or G1 if model invented plural |
Q4 — consent_log join
| Symptom | Code |
|---|---|
| UUID not in log | G6_LOG_DRIFT |
| Scope differs log vs WAV | G6_LOG_DRIFT |
| Expiry differs | G6_LOG_DRIFT |
Not G4 until post-mux read fails.
Escalation ladder (who gets the ticket)
Q2/Q3/Q4 FAIL
→ assign primary code
→ G1 → AI pipeline owner (re-prompt + regenerate)
→ G2/G3 → Audio lead (embed/export)
→ G4 → Reel lead (mux challenge)
→ G5 → Legal + PM (registry)
→ G6 → Producer (log migration)
→ re-run Q1–Q6
→ PASS → proceed to [artifact opinion](/blog/stop-treating-metadata-copy-as-done-make-receipts-build-artifacts-opinion-2026) triad
SLA opinion (studio policy): G1 blocks public reel until new WAV filed—do not “fix in ffmpeg.”
ai_voice_qa_reason_codes_receipt_v1.json
{
"schema": "ai_voice_qa_reason_codes_receipt_v1",
"build_label": "playtest-july-2027-rc1",
"registry_version": "2026-05-playtest-july-v2",
"lines_total": 7,
"lines_pass": 6,
"lines_fail": 1,
"failures": [
{
"asset_id": "facilitator_vo_07",
"primary_reason_code": "G1_GENERATION",
"secondary_reason_code": null,
"generator": "vendor_x_tts_v3",
"observed_scope": "public_marketing",
"expected_scope": "highlight_reel",
"fix_owner": "ai_pipeline",
"fix_status": "regenerate_scheduled"
}
],
"gates": {
"Q1_ingest": "pass",
"Q2_sidecar_bytes": "fail",
"Q3_registry": "fail",
"Q4_log_join": "pass",
"Q5_pre_mux": "skip",
"Q6_filed": "pass"
},
"ai_voice_qa_ok": false,
"public_vo_mux_allowed": false,
"cousin_receipts": {
"vo_consent_metadata": "release-evidence/audio/VO_CONSENT_METADATA_RECEIPT.json"
}
}
Pass when lines_fail=0 and all Q gates pass.
Generator prompt injection (G1 fix pattern)
Working dev pattern: Pass registry snippet in system prompt—not prose instructions:
consent_scope MUST be one of: highlight_reel, internal_only, press_review, facilitator_raw_archive
consent_expires format: YYYY-MM-DD
Never invent: public_marketing, fest_public_vo, promotional
Version prompt_hash in INGEST_LOG when prompt changes.
Vendor handoff README (paste to AI vendor ticket)
We validate embedded WAV LIST/iXML tags against consent_schema_registry_v1.json.
Invalid enum → G1_GENERATION — we need re-export with exact keys:
consent_record_id, consent_scope, consent_expires, opt_out
Sidecar JSON alone is insufficient (G2_EMBED_FAIL if bytes empty).
Three scenarios (walkthrough)
Scenario A — Model invented scope
Observed: promotional in WAV.
Code: G5_REGISTRY_MISMATCH if not in registry; root cause G1_GENERATION.
Fix: Re-prompt; regenerate; Q3 re-run.
Scenario B — Sidecar perfect, WAV bare
Observed: JSON correct; ffprobe shows PCM with no custom chunks.
Code: G2_EMBED_FAIL.
Fix: Audacity embed V2–V3—do not re-buy TTS credits first.
Scenario C — Pre-mux OK, post-mux stripped
Observed: Q2–Q4 pass; M5 fails.
Code: G4_MUX_SURVIVAL (not G1).
Fix: Mux challenge—stop re-running generator.
Integration with BUILD_RECEIPT
Suggest column:
"ai_voice_qa_ok": false,
"ai_voice_qa_receipt": "release-evidence/audio/ai-voice/ai_voice_qa_reason_codes_receipt_v1.json"
Thursday row review includes column when any manifest line has generator != manual_audacity.
CI sketch
- name: AI voice QA reason codes
run: |
python scripts/ai_voice_qa_triage.py release-evidence/audio/ai-voice/INGEST_LOG.csv
test $(jq '.lines_fail' release-evidence/audio/ai-voice/ai_voice_qa_reason_codes_receipt_v1.json) -eq 0
Keep triage script under 200 lines—reason-codes are policy, not a framework.
Decision tree (paste in QA runbook)
AI-sourced WAV arrived?
├─ No → manual VO tutorial path only
└─ Yes → Q1 ingest logged?
├─ No → block; complete INGEST_LOG
└─ Yes → Q2 sidecar == bytes?
├─ No → G2 or G3 or G1 (see Q2 table)
└─ Yes → Q3 in registry enum?
├─ No → G5 (+ root G1 if model invented)
└─ Yes → Q4 matches consent_log?
├─ No → G6
└─ Yes → optional Q5 pre-mux
└─ PASS → file receipt; proceed to mux night
Post-mux read fail after PASS?
└─ G4_MUX_SURVIVAL (reopen mux challenge)
Batch triage sheet (multi-line reels)
| asset_id | generator | Q2 | Q3 | Q4 | primary_code | owner | status |
|---|---|---|---|---|---|---|---|
| facilitator_vo_01 | manual | pass | pass | pass | — | — | mux_ok |
| facilitator_vo_07 | vendor_x | fail | fail | pass | G1 | ai_pipeline | regen |
Export CSV nightly—standup reads status column only.
PowerShell spot-check (Windows studios)
$sidecar = Get-Content facilitator_vo_07.meta.json | ConvertFrom-Json
# $wavFields from your inspector script
if ($sidecar.consent_scope -ne $wavFields.consent_scope) {
Write-Error "Q2_FAIL: $($sidecar.consent_scope) vs $($wavFields.consent_scope)"
}
Pair with ffprobe matrix PowerShell export on same manifest.
Standup escalation phrases (replace vague blame)
| Avoid | Use |
|---|---|
| “AI messed up metadata” | “facilitator_vo_07 G1_GENERATION—regen scheduled” |
| “ffmpeg broke consent” | “G4 on vo_03—mux challenge ticket 441” |
| “Legal blocked again” | “G6 log drift—producer migrating form_version” |
Aligns with metadata-as-artifact opinion ban on “metadata done.”
Secondary reason-codes (when to add)
| Primary | Allowed secondary | Why |
|---|---|---|
| G1 | G5 | Model invented non-enum |
| G3 | G2 | Strip then failed re-embed |
| G4 | none | Mux owns post-mux |
| G6 | G1 | Log fixed but WAV still stale |
Rule: Secondary documents root cause for post-mortem—does not split ownership.
AI pipeline architecture sketch
consent_log.csv row
→ prompt builder (registry injection)
→ TTS / voice model API
→ WAV + sidecar JSON
→ Q1–Q6 triage (this article)
→ Audacity polish (optional, re-run Q2)
→ vo_consent_metadata_receipt
→ mux challenge
→ artifact receipt
Failure injection point determines code—log prompt_hash at API boundary.
Vendor scorecard (quarterly, qualitative)
| Question | Pass signal |
|---|---|
| Returns embeddable WAV chunks? | Q2 pass rate >95% |
| Accepts enum injection in API metadata? | G1 rate drops |
| Documents tag key names? | Matches registry wav_embed_keys |
| Re-export SLA after G1? | <48h for public reel blockers |
No invented scores—track lines_fail / lines_total from receipt JSON.
Human QA vs automated QA
| Check | Human | Automated |
|---|---|---|
| Acting / emotion | yes | no |
| Pronunciation | yes | no |
| Registry enum | spot-check | Q3 jq |
| Sidecar vs bytes | spot-check | Q2 script |
| consent_log join | no | Q4 |
| Duration | ears optional | ffprobe matrix |
Beginner path: Automate Q3–Q4 first; keep acting review separate.
Incident post-mortem (reason-code section)
## AI VO QA incident
- build_label:
- asset_id:
- primary_code:
- generator + model_version:
- observed vs expected scope:
- fix applied:
- recurrence prevention: (prompt_hash bump / registry / mux)
Store in release-evidence/audio/ai-voice/QA_INCIDENTS/—link from receipt failures[].
Pairing with reel design
Design R4 disclaimer timing assumes consent_scope correct on VO line.
G1 with wrong scope can pass waveform strip layout while legal fails—run QA before design final export.
Multi-vendor manifest (two generators)
| asset_id | generator | notes |
|---|---|---|
| vo_01–04 | manual_audacity | Q1 still logs ingest |
| vo_05–07 | vendor_x | full Q1–Q6 |
| vo_08 | vendor_y_experimental | flag experimental: true in receipt |
Do not merge vendors in one receipt without per-line generator column—G1 rates differ.
Workshop — 90 minutes (first AI VO line)
| Block | Activity |
|---|---|
| 0–15 | Pin registry JSON |
| 15–30 | Generate one line with intentional wrong enum (test) |
| 30–50 | Run Q2–Q4; assign G1 or G5 |
| 50–70 | Fix via re-prompt + embed |
| 70–85 | File passing receipt |
| 85–90 | Dry-run mux; confirm not G4 |
Expanded code reference — symptoms to fixes
G1_GENERATION (deep dive)
| Observed tag | Likely cause | Fix |
|---|---|---|
promotional |
Marketing vocabulary in prompt | Inject registry enum list |
fest_public_vo |
Deprecated term in training data | Map via registry deprecated_scopes then regen |
Missing opt_out |
Model omitted boolean | Add required-keys block in API |
| UUID format invalid | Hallucinated id | Pass consent_record_id from log, forbid model invention |
| Keys in camelCase | Wrong metadata_key_policy |
Enforce snake_case in export script |
Escalation: If vendor cannot embed, stop public reel AI path—manual Audacity preflight.
G2_EMBED_FAIL (deep dive)
Common when API returns PCM WAV + JSON metadata file. Teams assume vendor “handled compliance.”
Proof: Q2 script shows empty LIST/iXML.
Fix: Embed before any ffmpeg—embedding after broken chain wastes time.
G3_CONVERSION_STRIP (deep dive)
Occurs in batch normalize steps (ffmpeg -ar 48000 without metadata copy flags).
Distinct from G4 which is mux to MP4 or AAC handoff.
Fix: Document ffmpeg flags in INGEST_LOG conversion_command column.
G4_MUX_SURVIVAL (deep dive)
Only assign when pre-mux proof attached in artifact receipt.
If pre-mux never passed Q3, do not label G4—fix upstream first.
G5_REGISTRY_MISMATCH (deep dive)
Legal may approve new scope string—response is registry version bump per governance #20, not silent acceptance in WAV.
G6_LOG_DRIFT (deep dive)
Often follows spreadsheet paste culture—pair with opinion #21.
Fix: Migration script + re-export all affected lines—do not edit WAV hex by hand.
Cloud vs local TTS (June 2026 notes)
| Path | QA implication |
|---|---|
| Cloud API | Log retention policy; Q1 records generator + API version |
| Local TTS | You own embed step—higher G2 rate if script skips embed |
| Hybrid (cloud audio, local embed) | Two entries in INGEST_LOG |
Privacy: Cloud upload ≠ WAV tag compliance—reason-codes apply to returned files you mux.
Prompt versioning discipline
prompts/facilitator_vo_v1.txt → prompt_hash A → 2x G1 failures
prompts/facilitator_vo_v2.txt → prompt_hash B → 0 failures
Keep prompts in git; never “hot fix in portal only” without hash update.
Relationship to 16-tool concat listicle
That listicle supports VOD triage—not facilitator VO tag QA.
If Discord clip mentions “AI voice sounds wrong,” route audio quality to human ears; route reel legal block to this reason-code sheet.
BUILD_RECEIPT promotion ladder (with AI column)
ai_voice_qa_ok == true
AND vo_consent_metadata_ok == true
AND metadata_survives_mux_ok == true
AND ffprobe_duration_matrix_ok == true
AND consent_scope_governance_ok == true
AND metadata_as_build_artifact_ok == true
→ public reel mux allowed
Remove ai_voice_qa_ok when manifest has zero AI lines—document ai_voice_qa_ok: "not_applicable" in receipt.
Facilitator contract addendum (one paragraph)
Add to multi-channel facilitator contract:
AI-generated facilitator lines require ai_voice_qa_reason_codes_receipt_v1.json
with lines_fail=0 before public highlight reel inclusion.
Thursday row review column
Extend row catalog:
| Column | Pass |
|---|---|
ai_voice_qa_ok |
true or not_applicable |
ai_voice_qa_receipt |
path exists |
Catches stale true after regen without receipt update.
False positive avoidance
| Looks like G1 | Actually |
|---|---|
| Wrong language in VO | Not tag QA—regenerate for casting |
| Noisy audio | Not tag QA—LUFS / denoise |
| Clip too long | G7 duration matrix |
| Wrong script text | Content QA—not compliance codes |
Train standup to ask “is the tag wrong or the performance wrong?”
Metrics dashboard (spreadsheet)
| Week | lines_total | G1 | G2 | G3 | G4 | G5 | G6 |
|---|---|---|---|---|---|---|---|
| W1 | 7 | 2 | 1 | 0 | 0 | 1 | 0 |
Goal: G1 trends down after prompt_hash bumps—not zero (models drift).
Evidence folder layout
release-evidence/audio/ai-voice/
INGEST_LOG.csv
ai_voice_qa_reason_codes_receipt_v1.json
QA_INCIDENTS/
prompts/
facilitator_vo_v2.txt
Legal readout (redacted)
Provide auditors:
- Reason-code catalog (this article table)
- Receipt JSON with
failures[] - INGEST_LOG
prompt_hashonly—no raw prompts if NDAs require
Proves triage discipline, not model vendor name.
Comparison — reason-codes vs cousin failures
| Symptom | Wrong code | Right code |
|---|---|---|
| ffmpeg stripped tags | G1 | G4 |
| Wrong plural in model output | G4 | G1 or G5 |
| Sheet ≠ WAV | G1 | G6 |
| 0.2s short | G1 | G7 |
| Missing iXML after Audacity macro | G4 | G3 |
Solo dev minimum path (one evening)
- Pin registry.
- Generate or receive one AI WAV + sidecar.
- Run Q2 compare script (Python or PowerShell above).
- If FAIL, assign G1–G6 from catalog—do not mux.
- Fix in correct lane; re-run Q gates.
- File
ai_voice_qa_reason_codes_receipt_v1.jsonwithlines_fail: 0. - Continue to VO tutorial mux steps.
Time: ~2 hours first line including one intentional failure drill.
Team RACI for reason-code culture
| Code | Accountable | Responsible |
|---|---|---|
| G1 | AI pipeline lead | Prompt + regen |
| G2–G3 | Audio lead | Embed / export |
| G4 | Reel lead | Mux challenge |
| G5 | Legal | Registry enum |
| G6 | Producer | consent_log |
| G7 | Audio lead | ffprobe matrix |
| G8 | Legal | waiver ticket |
Producer coordinates—does not reassign G4 to AI vendor.
Trend tie-in — why models fail tags now
July 2026 teams compress playtest → reel turnaround. Vendors optimize latency and naturalness, not your BUILD_RECEIPT columns. Reason-codes are how ops catches up without banning AI VO outright.
Cross-link index (internal)
| Need | Article |
|---|---|
| Export + mux survival | VO tutorial |
| Enum registry | Governance #20 |
| Post-mux proof culture | Opinion #21 |
| Duration drift | Matrix #19 |
| Strip recovery narrative | Case study #16 |
| Why July | Trend #17 |
| Receipt map | Top 20 hub |
This article sits between AI generation and manual mux receipts—skipping it sends G1 failures to ffmpeg by default.
Key takeaways
- Assign one primary reason-code per failed AI VO line—no multi-owner limbo.
- G1_GENERATION means re-prompt/regenerate—not mux iteration.
- Sidecar ≠ WAV — G2_EMBED_FAIL is common on AI exports.
- Registry check is Q3—pair with governance #20.
- G4_MUX_SURVIVAL only after Q2–Q4 pass on pre-mux bytes.
- File
ai_voice_qa_reason_codes_receipt_v1.jsonbefore mux night. - Artifact opinion still required after QA pass.
- Forward #23 ten-minute ritual immediately after
ai_voice_qa_okflips true (and before mux), so BUILD_RECEIPT can safely setwav_consent_metadata_ok. - Lesson 250 remains manual path milestone.
- Log
generator+prompt_hash—repro without vendor black box. ai_voice_qa_okis a first-class BUILD_RECEIPT column when INGEST_LOG lists any AI generator.- Re-run Q1–Q6 after every regen—hashes and bytes change together.
- Print the G1–G8 table near the AI export button—visibility beats post-mortem regret.
- Treat
prompt_hashchanges like compiler upgrades—re-QA every line in the manifest, not only the line that failed last time.
FAQ
Do reason-codes apply to human-recorded VO
Yes when tags fail—set generator: manual_audacity; codes G2–G6 still apply; G1 rare.
Is G1 always the vendor’s fault
Often prompt/registry injection failure on your side—code means “fix upstream of mux,” not “blame vendor.”
Can we auto-fix G5 by mapping synonyms
Only if registry documents deprecated_scopes—undocumented mapping recreates drift.
How does this relate to Whisper
Whisper transcripts do not set WAV consent tags—separate pipeline.
What if model refuses to emit legal fields
Block AI path for public reels; use manual VO tutorial.
Should G8 be common
No—waivers are exceptional; overuse triggers audit scrutiny.
Can one line have two primary codes
No—pick primary; log secondary in migration notes only.
Where to store INGEST_LOG
release-evidence/audio/ai-voice/ beside QA receipt.
Does QA replace mux challenge
No—run after Q pass; mux still required for G4 detection.
ElevenLabs / cloud API retention
Follow vendor DPA; reason-codes do not replace consent for uploading audio to cloud—only tag proof on returned WAV.
What if we do not use AI for VO at all
Set ai_voice_qa_ok: not_applicable in BUILD_RECEIPT; skip Q workflow—still run manual VO receipts.
Can G2 be automated in CI
Yes—script sidecar vs bytes; human only on FAIL.
How long to keep INGEST_LOG
Until build_label archived per Friday Block 5.
Does G1 require vendor ticket
Only when your prompt injection is correct and bytes still wrong—else fix prompt first.
Relationship to ritual #23
Ten-minute ritual runs after ai_voice_qa_ok when AI lines exist, and before you flip wav_consent_metadata_ok in BUILD_RECEIPT.
Can reason-codes apply to NPC bark lines
Only if those lines use same consent schema for public playtest reels—in-game NPC barks often out of scope; legal decides.
What JSON schema validates receipt
Use schema: ai_voice_qa_reason_codes_receipt_v1 string; jq assert lines_fail integer.
How do reason-codes interact with opt_out true
Block public reel regardless of code—log opt_out in Q4; do not assign G1–G6 for promotion path.
Should we train facilitators on codes
Yes—facilitators should recognize “G1 regen” means wait, not upload temp reel to Steam.
Wrong WAV tags need a reason-code, not another ffmpeg pass—assign G1–G8, fix in the owning lane, file ai_voice_qa_reason_codes_receipt_v1.json, then join the July VO proof cluster for mux. When lines_fail is zero, you have earned the right to argue about loudness—not before. File the receipt nightly during July reel weeks.—triage generation, embed, registry, and mux lanes, then file ai_voice_qa_reason_codes_receipt_v1.json before July highlight reel mux.