Skip to content

Refuse an explicit window_s a clip cannot hold (#43) - #51

Merged
thorwhalen merged 3 commits into
mainfrom
claude/refuse-window-wider-than-clip-43
Sep 8, 2026
Merged

thorwhalen merged 3 commits into
mainfrom
claude/refuse-window-wider-than-clip-43

Conversation

@thorwhalen

@thorwhalen thorwhalen commented Sep 8, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #43.

What changed

align_clips_to_reference(..., window_s=45) on a 50 s clip was accepted, produced one window, and returned support=None. The caller asked for a windowed vote and got a single whole-clip correlation — and the only signal was the absence of a support number, which is indistinguishable from a clip genuinely too short to support at any window.

Above clip_duration / (1 + MAX_SUPPORT_OVERLAP) the clip holds no second independent window, so the vote asked for cannot be held. _clip_window_and_hop now refuses that case with a typed error.

  • mixing/errors.py (new, pure stdlib) — MixingError base + WindowTooWideForClip. This is the first typed error mixing raises on its own behalf, so the module is also the home for the next one. Reachable as mixing.WindowTooWideForClip through the lazy facade (no backend pulled), and re-exported from mixing.audio.
  • The error carries clip_index, clip_duration_s, window_s, hop_s and max_window_s — the largest window that still leaves a second, independent look — so a caller putting a mixed-length set on one scale can retry at a window every clip holds. max_window_s is always positive.

The bound does not involve hop_s (fixed in review, commit c9a206b)

The first version of this PR used window_s > clip_duration - hop_s, which is the intuitive rule and is wrong in both directions. cn-video-gen-2's reviewer measured 18/64 disagreements against the support _consensus_alignment actually returns; both counterexamples are now pinned as tests:

call, 15 s clip duration - hop bound reality
window_s=11, hop_s=1 accepted support=None — #43 surviving the fix
window_s=6, hop_s=12 refused support=1.0 — a false refusal

The hop drops out because _window_offsets appends a tail window at len(clip) - n_win whenever the regular grid stops short, so the last window always begins exactly one window's length from the clip's end, whatever the hop. _independent_windows keeps a second window once it has moved on by 1 - MAX_SUPPORT_OVERLAP of a window, so a quorum exists iff clip_duration - window >= MAX_SUPPORT_OVERLAP * window. The hop decides how many looks there are and how finely a boundary is placed — never whether a second independent one can exist.

That rule is _holds_a_second_look; the ceiling is _max_supportable_window_s. Both compute in samples, mirroring _window_offsets' own rounding: in seconds the ceiling is inadmissible at some durations (on a 10 s clip at 16 kHz, 10 / 1.5 rounds up to 106667 samples where 106666 is the most that fits), so a caller retrying at the window the error named would land straight back in the exception. The message rounds its advice down for the same reason.

  • It subclasses ValueError, so except ValueError around alignment keeps working.
  • Docstrings updated (_clip_window_and_hop, align_clips_to_reference's window_s) and a paragraph added to the mixing-audio skill.

⚠️ Breaking change

A call passing an explicit window_s wider than clip_duration / (1 + MAX_SUPPORT_OVERLAP) — i.e. clip_duration / 1.5, the widest window that still leaves a second independent look — now raises where it previously returned an answer. The bound does not involve hop_s; see the section above. That answer was the uncorroborated single-window one, but it was an answer, and code depending on it will now see an exception. Fleet policy here is typed refusal over silent degradation, as in #45/#47 and muvid#59.

The default path is deliberately untouched: with window_s=None the window is still fitted per clip and every clip is answered, including one that lands on a single window at the floor — that is the estimator doing its best for a short clip, not a caller's mistake. A new test (test_the_default_window_path_is_untouched_by_the_refusal) pins that boundary across a long / fitted / floor-window trio rather than leaving it to be inferred.

aligned_spans is unchanged — it does not route through _clip_window_and_hop, and there window_s means boundary resolution rather than vote size (the open half of #43's last bullet).

Tests

The issue named two tests pinning the silent contract; there were six in practice — the four in test_adaptive_window.py used the wide-window call as their baseline for what issue #41 fixed. All six now assert the refusal, and each keeps the measurement it was pinning:

  • test_aligned_spans.py: test_an_explicit_window_wider_than_the_clip_is_refused (was …takes_the_whole_clip_answer), test_the_one_window_reproduction_is_now_a_refusal (was test_support_is_None_where_no_second_opinion_exists; the consensus=False half is kept as the contrast — asked for explicitly, the single correlation is an answer, not a degradation).
  • test_adaptive_window.py: test_an_explicit_window_is_never_overridden restated on a clip the window fits, plus a new test_an_explicit_window_the_clip_cannot_hold_is_refused pinning the inclusive bound, both ceiling formulas, and the max_window_s <= 0 message; the two #41 acceptance tests now pytest.raises on their baseline call; test_the_reported_window_is_the_one_asked_for_when_one_is_asked_for given a clip long enough to hold the window it pins.

Added in review:

  • test_the_refused_window_is_exactly_the_one_that_would_have_no_support — the guard's verdict checked against _window_offsets + _independent_windows directly over a grid of durations × windows × hops, rather than against the formula restated.
  • test_the_ceiling_the_error_names_is_one_the_call_accepts — across eight durations: the ceiling is accepted, one sample past it is refused, and the number the message names is admissible too.
  • test_the_bound_is_the_clips_length_and_the_overlap_rule_not_the_hop — both counterexamples on real support, so the guard cannot drift back onto the intuitive rule silently.
  • The remedy assertion now checks ok.support is not None, not merely that the retry is accepted — an accepted-but-still-unmeasured ceiling would be the original bug wearing an exception.

One further test converted in review: test_windows_that_are_the_same_look_twice_do_not_count_as_support passes window_s=9.5, hop_s=0.5 on a 10 s clip — the muvid#59 shared-bias case — which is above the corrected bound. That call returning an unexplained support=None is exactly what the refusal is for, so it now asserts the refusal and retries at the ceiling to show the offset still measures.

Out-of-suite verification: a 616-cell grid (7 durations × 11 windows × 8 hops, hop_s=None included) comparing the guard's verdict against the support align_clips_to_reference actually returns — 0 misses, 0 false refusals, 0 inadmissible ceilings.

611 passed, 1 skipped. ruff check / ruff format clean.

muvid consumer

Checked read-only. muvid does not need a code change: muvid.footage.align.align_footage already refuses to forward window_s/hop_s to mixing at its own entry point (WINDOW_PARAMETERS, muvid#59), so no muvid call path can reach this refusal. Its own test asserts a TypeError from muvid, which still holds.

What is now stale is muvid's rationale prose: the WINDOW_PARAMETERS comment and test_a_wider_window_is_refused_because_it_would_turn_the_gate_off justify muvid's refusal partly by "window_s=45 on a 50 s clip gives support=None, i.e. the gate switches off silently" — which mixing no longer does. muvid's refusal still stands on its other leg (narrowing the window deflates every support), so this is a docs-accuracy follow-up, not a break. Filed as a discovered issue: reeleehq/muvid#98.

https://claude.ai/code/session_01XY8uj3B4XKHKCqbfBRxgeX

`align_clips_to_reference(..., window_s=45)` on a 50 s clip was accepted, produced
one window, and returned `support=None`. The caller asked for a windowed vote and
got a single whole-clip correlation; the only signal was the ABSENCE of a number,
which is indistinguishable from a clip too short to support at any window.

Above `clip_duration - hop_s` the clip holds one window, so the vote cannot be
held. That is now `WindowTooWideForClip` — a new typed error carrying `clip_index`,
`clip_duration_s`, `window_s`, `hop_s` and `max_window_s` (the largest window that
still leaves a second, independent look), subclassing `ValueError` so existing
handlers around alignment keep working. `mixing/errors.py` is a new pure module, the
home for typed errors, reachable through the lazy facade without pulling a backend.

BREAKING: calls passing an explicit `window_s` wider than the clip now raise where
they returned an uncorroborated answer. Only the EXPLICIT path is refused — with
`window_s=None` the window is still fitted per clip and every clip is answered,
including one that lands on a single window at the floor. Six tests that pinned the
silent behaviour now pin the refusal; a new test pins the default path unchanged.

Claude-Session: https://claude.ai/code/session_01XY8uj3B4XKHKCqbfBRxgeX
The predicate `window_s > clip_duration - hop_s` was a function of `hop_s`, and
support-computability is not. Measured against the support `_consensus_alignment`
actually returns, it was wrong in both directions: `window_s=11, hop_s=1` on a 15 s
clip satisfied it and still returned `support=None` — #43 surviving the fix — while
`window_s=6, hop_s=12` was refused although it measures `support=1.0`.

The hop drops out because `_window_offsets` appends a tail window at
`len(clip) - n_win` whenever the regular grid stops short, so the last window always
begins one window's length from the clip's end whatever the hop. A second independent
window therefore exists iff `clip_duration - window >= MAX_SUPPORT_OVERLAP * window`.
That rule is now `_holds_a_second_look`, and the ceiling `_max_supportable_window_s`.

Both compute in SAMPLES, mirroring the rounding the grid is built from. In seconds the
ceiling is inadmissible at some durations: on a 10 s clip at 16 kHz `10 / 1.5` rounds
up to 106667 samples where 106666 is the most that fits, so a caller retrying at the
window the error named would land straight back in the exception. The message rounds
its advice down for the same reason.

`max_window_s` is now always positive, so the impossible-ceiling branch is gone.

Tests: the guard's verdict is checked against `_window_offsets` + `_independent_windows`
over a grid of durations, windows and hops rather than against the formula restated;
both counterexamples are pinned at unit and support level; the ceiling is asserted
admissible (and one sample past it refused) across eight durations; the remedy test now
asserts `support is not None`, not merely that the retry is accepted. One further test
converted: `window_s=9.5, hop_s=0.5` on a 10 s clip — the muvid#59 shared-bias case —
is above the corrected bound, which is exactly what the refusal is for.

Claude-Session: https://claude.ai/code/session_01XY8uj3B4XKHKCqbfBRxgeX
Two documentation claims said the ceiling is always positive and measurable.
Measured: true from a 2-sample clip up, false for a 1-sample one, where no window
holds a second look at all and the value is floored at one sample. Reworded as a
lower bound in that degenerate case rather than a promise.

The guard/engine equivalence grid had no cell at the bound itself, which is the
only place an off-by-one in either direction shows. Added `duration / 1.5`.

Claude-Session: https://claude.ai/code/session_01XY8uj3B4XKHKCqbfBRxgeX
@thorwhalen
thorwhalen merged commit 3178600 into main Sep 8, 2026
12 checks passed
@thorwhalen
thorwhalen deleted the claude/refuse-window-wider-than-clip-43 branch September 8, 2026 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

align_clips_to_reference: an explicit window_s wider than the clip silently turns support off

1 participant