Repository navigation
fix(video): fail fast when the duration tab probe misses an explicit --duration (#288) - #289
Conversation
…--duration (#288) _select_video_duration now raises UiSelectorDriftError (exit 23, #183 pattern) with a debug screenshot instead of warn-and-continue. The function only runs when the user passed --duration explicitly (the classic driver guards on request.duration is not None), so a probe miss means Flow's 8s default would silently replace the requested value — corrupting downstream timeline math (same contract principle as #281).
- tests/api/transports/drivers/test_classic.py: pin the classic-driver duration branch (explicit-duration guard, out_dir forwarding, drift error propagation) — the affected call site had no coverage (D4). - CHANGELOG [Unreleased] + KNOWN_ISSUES Open entry for the duration_tab probe miss, with the locale-label hypothesis for the selector rot (D5/D6). - Drop the pre-raise duration_not_set warning (old non-fatal event name firing on a fatal path — double signaling), drop the out_dir default to match sibling probe signatures, fix the 'aria-label' docstring (the selectors match visible tab text), soften the message to 'typically 8s' (D1/D2/D6). - Update the dev spike call site for the keyword-only out_dir.
Council review verdict (6 dimensions @ 868e8c8): YELLOW → findings applied in 02dcf01
Applied in 02dcf01: new Deferred (follow-up): wrap Remaining YELLOW (intrinsic): the live-surface box — one headed Classic-profile run with explicit |
…'s settings popover (live e2e 2026-07-11) Live run on denon82: --duration 4 fail-fast verified (exit 23, screenshot, aborted pre-submit). Screenshot refutes the locale hypothesis — the panel renders aspect/count/model rows but no duration row at all.
Live e2e result (2026-07-11, denon82, credit-free) — fail-fast verified on the affected surface ✅
Happy-path caveat: the 'duration tab found → clicked' path is unverifiable on this profile — the control doesn't exist on this cohort. If another profile/cohort still renders duration tabs, one credited run there would close it; otherwise the fail-fast IS the permanent correct behavior for affected cohorts. The PR's verification box can be considered satisfied for the reachable surface; evidence log in the session scratchpad ( |
…cleanups - tests/api/transports/drivers/test_classic.py: pin the classic-driver duration branch (explicit-duration guard, out_dir forwarding, drift error propagation) — the affected call site had no coverage (D4). - CHANGELOG [Unreleased] + KNOWN_ISSUES Open entry for the duration_tab probe miss, with the locale-label hypothesis for the selector rot (D5/D6). - Drop the pre-raise duration_not_set warning (old non-fatal event name firing on a fatal path — double signaling), drop the out_dir default to match sibling probe signatures, fix the 'aria-label' docstring (the selectors match visible tab text), soften the message to 'typically 8s' (D1/D2/D6). - Update the dev spike call site for the keyword-only out_dir.
…l-fast fix(video): fail fast when the duration tab probe misses an explicit --duration (ffroliva#288)
…reconcile CHANGELOG + KNOWN_ISSUES
…removed (#655) * docs(known-issues): record duration control as cohort-dependent, not removed The #288 row claimed `Status: Open` while #288, #451 and #634 are all closed on GitHub, and asserted the duration control had been removed from Flow -- a claim a third profile disproved on 2026-09-04. The truth is narrower and stranger than either previous framing: on the same `labs.google` frontend, some accounts render `4s/6s/8s` on every Veo 3.1 model and some render no duration row at all, with different credit prices. Both the 2026-07-11 and 2026-09-03 captures stay valid for their own cohort; so does the opposite capture. The cohort key is still unknown. So the row now says cohort-dependent, keeps the fail-fast as correct behaviour where the control is absent, and warns that stating either "Veo has no duration control" or "Veo supports 4/6/8s" unconditionally is wrong. The status moves to Mitigated -- the fail-fast shipped in #289 -- while the row stays because the Flow-side behaviour is unresolved. Also gives the workaround a real remediation: when filing is actually warranted, and what to attach. * docs(known-issues): correct the #288 row after council review Five reviewers ran on 618bf9f; four independently found the same false claim, and it was mine. "On an unaffected cohort it works" is wrong. gflow refuses `--duration` on every named Veo 3.1 model at the CLI edge -- `click.UsageError`, exit 2, before any browser launch -- from a static table that never consults the account. So the flag is unavailable on every cohort today, for two different reasons, and the row now says exactly that. The rest of the corrections follow from the same mistake: the exit-23 path and its `debug_no_duration_tab.png` are reachable only via `--model omni-flash` or a model-less `t2v`/`r2v`, not via a Veo model, so the reporting instruction was unobtainable for the very reporter it invited. It now asks for the invocation and the error text, and mentions the screenshot only where one exists. Two overclaims trimmed against the capture that backs them: "every Veo 3.1 model" becomes "all three selectable" (`lower_priority` missed its picker), and the composer-chip corroboration is dropped -- every per-model entry in that JSON has `composer_chip: null`; only the pre-loop baseline row carries one. Also reordered so the workaround comes before the history, cut the methodology and the note-to-maintainers about phrasing (that belongs in memory, where it already is), and pointed Status at #650 as the tracker for relaxing the gate, since #288/#451 are closed and nothing upstream is tracked.
Summary
_select_video_durationnow raisesUiSelectorDriftError(typed, exit code 23 — thegflow image t2ifails finding Flow aspect-ratio mode switch trigger #183 selector-drift pattern) with a debug screenshot (debug_no_duration_tab.png) instead of warn-and-continue when theduration_tabprobe misses.--durationis omitted: the function only runs for an explicit duration (classic.pyguards onrequest.duration is not None), so Flow's default path is untouched.UiSelectorDriftErrorthat sibling probes (_switch_video_sub_mode) already raise for the same failure mode.--durationto accept Flow's default) and the screenshot path, which doubles as the investigation artifact for the selector-drift question below.Why
Duration is a contract parameter: a silent 4s→8s substitution corrupts downstream timeline math while the JSON result reports success (issue #288, 3/3 repro on the 2026-07-11 chalkboard i2v pilot). Same design principle as the #281 wrong-media fixes: an unhonorable explicit parameter is a hard error, not a warning.
Verification status
test_missing_duration_tab_raises_drift_error), then the fix to greenScreenshot:clause, remediation hint in messageruff check+ruff format --checkclean repo-wide; pyright 0 errors; 1271 passed / 3 skipped (tests/api+tests/cli)--durationon a Classic profile to confirm the happy path still sets the tab, and to capture the new debug screenshot for the open selector-drift investigation (whyduration_tabmisses on the current Frames-submode DOM — possible cohort split, cf.gflow image t2ifails finding Flow aspect-ratio mode switch trigger #183). Headed browser + Veo credits required.Scope notes
duration_tabcascade against Flow's current DOM stays open on video i2v: --duration is silently ignored when the duration tab probe fails (requested 4s, got 8s) #288 (needs the live DOM; the screenshot this error captures is the input to that work).--best-effortopt-out flag skipped (YAGNI until someone asks);requested_duration/effective_durationpayload fields unnecessary under fail-fast.Refs #288
🤖 Generated with Claude Code