# Iteration 12 — Phase 0 (substrate / motivation / inventory) → Phase 1 lock

Opens 2026-05-14 after iter11 PARTIAL close. Combined Bug 4 + Bug 5 wire-byte search exhausted; both bugs share an architectural pattern (libva controls byte-equivalent to kdirect for fields rkvdec consumes, yet libva produces wrong output and kdirect produces correct output). The remaining unexamined surface is the **OUTPUT bitstream bytes**.

## Locked research question (iter12, 2026-05-14)

> *"For BBB H.264 frame 1 and BBB HEVC frame 1: do the bytes in libva's OUTPUT V4L2 buffer (source_data[0..slices_size]) byte-match the bytes in kdirect's OUTPUT V4L2 buffer for the same input frame? If yes, the cause is in non-ioctl state (kernel-state, hardware-state); if no, the cause is in the libva bitstream-write path."*

### Pass/fail (boolean)

- **PASS (full)**: libva H.264 == kdirect H.264 hash AND libva HEVC == kdirect HEVC hash, byte-identical on 3-frame sweep. Indicates the iter12 instrumentation surfaced and fixed a real bitstream-write bug.
- **PASS (PARTIAL/diagnostic)**: iter12's γ-output instrumentation produces a byte-by-byte diff log. If libva's source_data differs from kdirect's: localize the divergence to a specific position, narrow to the bitstream-write site, fix.
- **PASS (architectural)**: libva's OUTPUT bytes byte-match kdirect's. Then Bug 4 + Bug 5 are NOT in libva at all — they're in non-ioctl state outside our control. Document, defer.

## Substrate state at iter12 open

| Property | Value |
|---|---|
| Kernel | `linux-fresnel-fourier 7.0-1` |
| Fork tip | `8e2c04f` (iter11 close) |
| Backend SHA | `521c1474c51154373e2d27f99d715a5af73a5fd9f72a83d947f8b552f2755d1f` |
| Diagnostic surface | γ (CAPTURE dump) + IMP-1 (memset gate) preserved env-gated |
| α-13/α-14 in shipping state | Yes — wire hygiene improvements, zero regression |

## Phase 4 mechanism (predicted)

Extend the existing γ infrastructure:

1. **α-16 OUTPUT dump**: in `picture.c::RequestEndPicture`, after `codec_set_controls` builds the source_data, before OUTPUT QBUF, dump source_data[0..slices_size] to a per-frame file gated by `LIBVA_V4L2_DUMP_OUTPUT=1`. ~20 LOC.

2. **Reference**: for kdirect, modify ffmpeg-v4l2request's `ff_v4l2_request_append_output` (and the OUTPUT QBUF site) to dump the same content. OR — simpler — extract the input file's NAL-unit bytes via `ffmpeg -bsf:v ... -c:v copy` and compare against libva's dump (kdirect should also produce these same bytes, modulo start-code prefixing).

3. **Compare**: hash both dumps. If they match → Bug 4 + 5 are outside libva's control. If they diverge → narrow to first divergence offset, identify which code path produces the diff.

Quick test path: skip kdirect instrumentation. Just dump libva's source_data and inspect for sanity (start code present, NAL header looks right, frame bytes intact). If libva's bytes look correct AND kdirect's bytes (from a known-working sweep) ARE the same, then bug is elsewhere.

## Scope locks

In scope:
- `src/picture.c::RequestEndPicture` — add env-gated OUTPUT byte dump.
- Phase 7c-style byte-level comparison with a captured reference.

Out of scope (until iter12 Phase 7 demands them):
- Modifying ffmpeg-v4l2request to instrument kdirect (heavyweight; defer if unnecessary).
- Per-codec changes (HEVC fixes already shipped α-13/α-14).
- Kernel patches.

## Phase 5 review concerns to invite

- Per `feedback_wire_vs_behavior.md`: Phase 7 must verify against the actual YUV hash, not just byte-equivalence at one layer.
- Per `feedback_grep_callsites_before_no_change.md`: confirm the OUTPUT byte-write path is fully in libva's codec_store_buffer / EndPicture, no other call sites.
- Per `feedback_per_driver_kludge_gating.md`: any per-codec gating in α-16 if found.

## Predicted iter12 cadence

- Phase 0: this doc.
- Phase 4: small plan ~10 min.
- Phase 5: brief review ~15 min.
- Phase 6: implement α-16 + ~15 min.
- Phase 7: capture dump on fresnel, compare. ~20 min.
- Phase 8: close. ~10 min.

Total: ~1.5 hours.

## What iter12 outcomes mean

- **OUTPUT bytes match** → both bugs are non-libva. iter12 closes with a definitive narrowing: "all Phase-investigatable surfaces in libva backend are byte-clean; Bug 4 + 5 lie outside ioctl boundary." Likely requires kernel-side or hardware-side investigation, which would route via kernel-agent.
- **OUTPUT bytes differ at offset X** → narrow to where libva writes that byte differently from kdirect; fix in `codec_store_buffer` or upstream.

Either outcome is high-information value for the campaign's bug closure path.
