Skip to content

Migrated host: image submit needs pre-submit gates (cookie bar, overlay, pointer target) + bounded UI diagnostics #780

Closed

Description

@stgmt

Migrated host: image submit needs pre-submit gates (cookie bar, overlay, pointer target) + bounded UI diagnostics

Problem

Three measured failure modes on the migrated flow.google.com image path, all presenting as bare Playwright errors with no exit code and no pointer at the cause:

  1. Cookie bar kills the run before any setting is touched (incident 8dc6c020, 2026-09-09). Google's glue cookie banner (glue-cookie-notification-bar) sits fixed at the viewport bottom and intercepts every pointer event over the composer's settings trigger. Click retries run into Playwright's timeout and the run dies as an unhandled TimeoutError — no typed error, no mention of the bar.
  2. Stacked overlays misdirect the click. After --model, Angular leaves two stacked overlays (settings pane + model menu); one Escape closes only one. The leftover pane covers the composer and send_prompt's click then dies ~5s later as a bare TimeoutError naming [contenteditable='true'] — pointing nowhere near the pane.
  3. Deterministic DOM failures must not enter the transport retry loop. A dead submit button retried at the transport layer is a second paid submit for nothing. Nothing today proves the composer is unobstructed and submit is actionable before network observers arm.

Proposed change (PR follows this issue)

  • _pre_submit_gate: dismiss cookie bar → refuse on any remaining blocking overlay → prove the submit button visible, hit-testable (elementFromPoint) and enabled — all before any page.on("request"/"response") listener is registered.
  • Bounded cookie-bar dismissal (3 attempts, visibility postcondition) raising typed UiSelectorDriftError, never a bare timeout.
  • Bounded redacted UI-failure diagnostics (out_dir/ui-failures/: structural DOM snapshot without prompt text, query-stripped URL, screenshot) attached to the typed error detail.
  • Image requests the migrated composer serves, with a named project, from a pre-navigation page prefer the migrated host on auto (migrated_images_prefer: unported forms, project-less runs, and in-editor pages keep the served host and their pre-minted token), so the page-owned recaptcha path wins the post-goto handoff race instead of the doomed pre-navigation mint (RecaptchaError on migrated Flow host with gflow-cli 0.69.0 (image i2i) #692); the mint skip is ANDed with servability in _drive_images_generation; labs.google kill-switch behavior unchanged (negative control pinned).

$0 evidence

Real-Chromium unit tests (cookie-bar both variants dismissed, overlay gate refuses before any listener arms, typed drift never retried), contract tests for the capability latch. No Generate/submit/video calls, no authenticated profile required, no credits spent. Full suite + ruff + pyright gates green on the PR branch.

Related: #692 (mint race), #719 (upload stall), #745 (selector/credit review). Follows the repo's issue-first convention.

Activity

  1. ffroliva commented on Sep 11, 2026

    @ffroliva
    Owner

    Spiked failure mode 1 before reviewing #781, because nothing in this repo had previously observed glue-cookie-notification-bar on flow.google.com — both earlier sightings are labs.google, and the 2026-09-10 spike read 159 DOM samples on that exact host and project and watched the click land 3/3.

    Confirmed, and broader than this issue states. Measured on ci-probe, same project, seventeen hours after that 0/3:

    Reading Before After dismissal
    bar elements visible 6 / 6 0 / 4
    settings trigger hit-testable 0 / 5 rendered 4 / 4
    image submit hit-testable 0 / 5 rendered 4 / 4

    div#glue-cookie-notification-bar-1, position: fixed, z-index: 1000, spanning y 547–655 of a 655 px viewport, consent bundle served from gstatic. Flow's composer is itself bottom-fixed, so this is two bottom-anchored layers colliding, not a short-window artifact.

    The issue names only the settings trigger. The image submit button is covered too — elementFromPoint over both returns the bar's label span in every rendered sample.

    This also completes yesterday's 0/3 rather than contradicting it. That spike declined to read a disappearance as transience and named "a first visit after a Flow deployment" as the state it could not summon on demand. This is that state, arriving on its own.

    Two gaps recorded rather than papered over: the labs contrast arm failed, because ci-probe is a moved account and the labs URL redirected, so whether an unmoved account sees the same bar on the labs editor is still unknown. And the control arm consumed the state, so a re-run on that profile reads 0/N until Google re-prompts.

    Writeup and script: docs/superpowers/spikes/2026-09-11-migrated-cookie-bar-blocks-the-composer.md on branch docs/spike-migrated-cookie-bar.

    Review of #781 posted separately — the dismissal is measured-good and I want it; the routing change and the diagnostics layer bundled with it need splitting.

    https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc

  2. ffroliva commented on Sep 11, 2026

    @ffroliva
    Owner

    Follow-up: the two items v0.73.1 shipped as not verified are now measured. PR #784 carries the evidence.

    Prevalence, by mechanism. The gate is one key — localStorage["glue.CookieNotificationBar"] on the flow.google.com origin. Not a cookie, which is why no profile here carried SOCS. Found by diffing cookies, localStorage and sessionStorage across a reject click on a throwaway profile: zero cookie changes, one new key.

    Three independent sightings rather than one: a clean never-signed-in browser profile (4/4 visible), a second authenticated profile this spike had never opened (5/5), and ci-probe on the editor (6/6, both controls covered).

    Proven by intervention, not correlation — removing that key on ci-probe, which touches no cookie and therefore no auth, flipped the editor from both controls hit-testable to both covered. So the bar is the origin's default state and a stored dismissal is what removes it. Every fresh gflow profile meets it on its first Flow load.

    The cure, against a live bar, on the released build. With the bar restored that way, the ordinary CLI command on cli_version: 0.73.1: migrated.editor_ready → migrated.cookie_bar_dismissed 86 ms later → status: ok, a 1024×1024 JPEG on disk.

    Still unmeasured and recorded as such: the covering geometry on a second account's editor, because denon82 and pr389fresh2 both redirect to /about.

    Useful consequence for anyone reproducing this: the state is no longer scarce. Delete that one key and the bar comes back on demand.

    https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions