Skip to content

fix(video): fail fast when the duration tab probe misses an explicit --duration (#288) - #289

Merged
ffroliva merged 3 commits into
developfrom
bugfix/288-duration-fail-fast
Jul 11, 2026
Merged

ffroliva merged 3 commits into
developfrom
bugfix/288-duration-fail-fast

Conversation

@ffroliva

Copy link
Copy Markdown
Owner

Summary

  • _select_video_duration now raises UiSelectorDriftError (typed, exit code 23 — the gflow image t2i fails 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 the duration_tab probe misses.
  • No behavior change when --duration is omitted: the function only runs for an explicit duration (classic.py guards on request.duration is not None), so Flow's default path is untouched.
  • No new error class or exit code — reuses the existing UiSelectorDriftError that sibling probes (_switch_video_sub_mode) already raise for the same failure mode.
  • Error detail carries a remediation hint (omit --duration to 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

  • TDD: failing test written first (test_missing_duration_tab_raises_drift_error), then the fix to green
  • Unit: raise-on-miss, screenshot capture + Screenshot: clause, remediation hint in message
  • ruff check + ruff format --check clean repo-wide; pyright 0 errors; 1271 passed / 3 skipped (tests/api + tests/cli)
  • Needs human e2e: live i2v run with explicit --duration on 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 (why duration_tab misses on the current Frames-submode DOM — possible cohort split, cf. gflow image t2i fails finding Flow aspect-ratio mode switch trigger #183). Headed browser + Veo credits required.

Scope notes

Refs #288

🤖 Generated with Claude Code

ffroliva added 2 commits July 11, 2026 16:24
…--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.
@ffroliva

Copy link
Copy Markdown
Owner Author

Council review verdict (6 dimensions @ 868e8c8): YELLOW → findings applied in 02dcf01

Dim Verdict Headline
D0 CI-mechanical 🟢 ruff check/format, doc links, hygiene all green locally
D1 Correctness 🟢 Single choke point; nothing swallows the error (MCP → structured error, worker → task fail); no warn-path remains that drops duration
D2 Quality 🟢 Matches sibling drift-raise pattern; 2 cleanups flagged
D3 Security 🟢 No new surface; PII screenshot warning + show_locals=False renderer inherited
D4 Tests 🟡 Classic-driver call site (out_dir forwarding, propagation) had zero coverage
D5 Memory/docs 🟡 CHANGELOG + KNOWN_ISSUES entries missing per #281-wave convention
D6 UI/live-verify 🟡 Affected surface unverified (declared); locale-label hypothesis for the selector rot

Applied in 02dcf01: new tests/api/transports/drivers/test_classic.py (D4 must-fix); CHANGELOG [Unreleased] + KNOWN_ISSUES Open entry with the locale hypothesis (D5 must-fix); dropped the double-signaling pre-raise duration_not_set warning, dropped the out_dir default, fixed the misleading aria-label docstring, message now says 'typically 8s' (D1/D2/D6 nice-to-haves). Locale hypothesis also posted to #288.

Deferred (follow-up): wrap UiSelectorDriftError into ChainPartialError in chain.py:195 so a mid-chain drift abort reports completed links (D1, pre-existing for sibling raises).

Remaining YELLOW (intrinsic): the live-surface box — one headed Classic-profile run with explicit --duration (happy path + the real miss screenshot). That is the human-e2e gate already declared in the PR body; keep draft until checked. SonarCloud gate pending on CI at time of review.

…'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.
@ffroliva

Copy link
Copy Markdown
Owner Author

Live e2e result (2026-07-11, denon82, credit-free) — fail-fast verified on the affected surface ✅

gflow video i2v <local file> "…" --duration 4 (correlation b8e66830):

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 (e2e289.log).

@ffroliva
ffroliva marked this pull request as ready for review July 11, 2026 17:48
@ffroliva
ffroliva merged commit 7f1ca64 into develop Jul 11, 2026
9 checks passed
ffroliva added a commit that referenced this pull request Jul 11, 2026
@ffroliva
ffroliva deleted the bugfix/288-duration-fail-fast branch July 28, 2026 16:06
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
…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.
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
…l-fast

fix(video): fail fast when the duration tab probe misses an explicit --duration (ffroliva#288)
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
ffroliva added a commit that referenced this pull request Sep 4, 2026
…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.
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.

1 participant