Two Gates, No Legal Move

← hexisteme · notes · 2026-08-31

Two publish-time gates on a video pipeline turned out to be jointly unsatisfiable for one beat — proved by arithmetic, not guesswork — and the honest fix was a recorded, attributable waiver that only covers what is provably unfixable.

I run a small fleet of AI agents. One of them assembles and publishes short data-animation videos — narrated bar-chart and counter animations — and before an episode ships, it runs a publish-pass gate that checks the episode against a rulebook of pacing and sourcing rules. It's the same shape of thing as a CI pipeline with content or compliance checks, just applied to video beats instead of code. On the pass for one episode, that gate logged six findings. This is about one of them: the one where the gate had no correct answer, and the arithmetic proves it.

The two gates

The episode is built from eight narrated segments, or "beats." Each beat carries a source label describing how it was produced — a deterministically rendered chart animation, stock B-roll, a mood-metaphor shot, a real-world anchor image, and so on. Two rules in the rulebook key off that label.

IR2 (duration_over_max) caps how long a single beat can run, and the cap depends on the label. The "nondeterministic" labels are the tightest: a beat labeled first_reveal may run at most 6 seconds, real_world_anchor at most 5, mood_metaphor at most 7.

IR4 (same_source_run_over_10s) caps how long beats sharing a label can run back to back before something else has to break it up. _check_ir4 counts a run of length one as a run — a single beat, alone, can trip it if it's long enough.

Both rules are reasonable in isolation. IR2 keeps a clip from overstaying a label that's supposed to be short-lived. IR4 keeps the video from sitting on one sourcing pipeline long enough to stop feeling assembled. Neither looks like a bug by itself.

The beat with no legal label

Here are the eight beats, measured:

BeatLength
B013.002s
B026.981s
B035.636s
B047.428s
B055.510s
B0610.245s
B075.080s
B084.523s
Total48.405s

B06 is 10.245 seconds. As a single beat, it's already a run of length one over IR4's 10.0-second threshold — no neighbor required. To silence IR4, B06 needs a label the rulebook treats as nondeterministic, since only nondeterministic labels break up a same-source run.

So the agent went looking for one. This channel's effective map has exactly three nondeterministic labels: first_reveal, real_world_anchor, mood_metaphor, capped at 6, 5, and 7 seconds respectively. B06 is 10.245 seconds. Every cap is smaller than the beat that would have to carry it — not close, not a rounding error, just smaller across all three. Relabel B06 to satisfy IR4, and IR2 fires on the same beat immediately, for the same reason: it's too long for any label except the one it already has.

That's not a gap a fourth label would have closed — there are only three nondeterministic labels in this channel's map, and all three were checked. IR4 turns off exactly where IR2 turns on. A beat either carries a label capped under 10.245 seconds, and trips IR2, or it doesn't, and trips IR4.

It doesn't get better by relabeling around it

Maybe the fix wasn't B06 itself but the beats around it — spread the run out instead of moving the one beat causing trouble. The agent tried the most generous honest relabeling available: B03 to stock_broll, B08 to flow_mood. Applied together, that should break up more of the run.

It doesn't. B04 through B07 — 7.428 + 5.510 + 10.245 + 5.080 — still sum to 28.263 seconds on a shared label, still well over IR4's 10-second ceiling. Relabeling the beats at the edges doesn't touch the block B06 sits inside.

At that point there was no labeling left to try, because none exists. That's not a fact about this episode's specific footage choices; it's a fact about the numbers. Every nondeterministic label available caps below the beat that needs to escape IR4, and the deterministic block that beat sits in is long enough to fail IR4 on its own regardless of what happens at the edges. The defect isn't in the episode. It's a mismatch between a data-animation format — long, dense, deterministically rendered chart sequences with few natural cutaway points — and a hybrid rulebook built assuming footage breaks up more often than this format allows.

Prove it with arithmetic before you touch the work

The instinct when a gate fails is to fix whatever it's pointing at. That's usually right. But it's worth asking a cheaper question first: does any labeling of these beats pass both rules? That's not a judgment call — it's eight numbers, three caps, one threshold, checked exhaustively. Once the answer is no, editing the episode to chase compliance stops being useful work, because there's no target left to hit. The claim shifts from "this episode is wrong" to "these two rules can't both be satisfied by this format," and that's a claim you can actually check instead of just asserting.

A waiver you can point to

Once compliance is proven impossible, something still has to happen to the episode. Silently skipping the check, or quietly loosening a threshold to let it through, would erase the fact that anything unusual happened at all. Instead the agent wrote it to interleave_waiver.json: the two structural violations, the arithmetic behind them, and waived_by: "claude" — its own name, in the record, next to the reason. Anyone looking at this episode later — including me — can see exactly what was waived, why, and who signed it. That's the difference between a waiver and a bypass: a bypass hides that a rule didn't apply; a waiver says so, in a place someone will look.

Waivers rot when they absorb what's fixable

The part I'd trust least about a waiver file is if it became a place to dump anything inconvenient. So the same pass drew a hard line: fix what's fixable, waive only what genuinely isn't. The same episode had a separate, ordinary IR2 violation — B03 at 6.404 seconds against a 6-second cap — and there was nothing structural about it. The narration was just wordier than it needed to be. The agent cut it from 16 words to 13, re-timed the beat, and it came in at 5.636 seconds, under the cap. That fix never went into the waiver file. It didn't need to; it wasn't a structural conflict, it was a sentence that could be shorter.

That distinction is the whole discipline. A waiver that quietly absorbs violations that were actually fixable stops meaning "the rulebook and the format disagree" and starts meaning "nobody felt like fixing this." The same exhaustive check that proved B06 has no legal label is what earns it a place in interleave_waiver.json instead of a rewrite. Anything that does have a legal move — a shorter sentence, a different word count — doesn't get in, no matter how convenient the waiver file would be.

Not the same failure as the others

This wasn't a gate whose own error rate was worse than what it was checking for (Our Quality Gate Was 24x Noisier Than What It Guarded), or a rule that fired on text the agent itself had just written (The Rule That Triggered on Its Own Advice), or a check that cleared because it matched a keyword instead of confirming the underlying fact (My Verification Gate Cleared on a Keyword, Not Evidence). IR2 and IR4 both did exactly what they were built to do, correctly, on real numbers. The failure was that satisfying one guarantees failing the other, for this beat, in this format — and no amount of retrying makes that arithmetic come out differently.

FAQ

What are IR2 and IR4?

Two automated checks in a video-publishing rulebook. IR2 (duration_over_max) caps how long a single beat can run based on its source label, with nondeterministic labels capped lowest. IR4 (same_source_run_over_10s) caps how long beats sharing a label can run back to back, counting even a single beat as a run of one.

Why couldn't relabeling the beat fix it?

The beat is 10.245 seconds. Escaping IR4 requires giving it a label the rulebook treats as nondeterministic, but every nondeterministic label available on this channel caps below 10.245 seconds — 6, 5, and 7 seconds respectively — so any label that clears IR4 immediately trips IR2 on the same beat.

Was this a bug in the episode?

No. Even the most generous honest relabeling of the surrounding beats still leaves a four-beat block summing to 28.263 seconds in violation of the run-length rule. The mismatch is between the data-animation format's long, deterministically rendered blocks and a rulebook built assuming more frequent cutaways.

What did handling it honestly look like?

A recorded waiver — interleave_waiver.json, with waived_by: "claude" and the arithmetic behind the decision — instead of silently disabling the check. It covered only the violations that were exhaustively proven unfixable; a separate, ordinary duration violation in the same batch was fixed in the script instead (16 words cut to 13, 6.404s down to 5.636s) rather than added to the waiver.

How do you keep a waiver file from becoming a dumping ground?

Require proof, not preference, before anything goes in it, and fix what is fixable first. Here, only the violation that survived an exhaustive check across every available label was waived; a fixable violation in the same pass got fixed in the script instead.

Related notes

← hexisteme · notes · CC-BY 4.0