Repository navigation
chore(release): v0.73.2 - #798
Merged
Merged
Conversation
…ainst a live bar (#784) v0.73.1 shipped with two items recorded as NOT verified. Both are now measured, and both turned out to be cheap once the right question was asked. PREVALENCE. A count of affected users is not obtainable here -- there is no telemetry -- but the gate is, and it is the more durable answer: localStorage["glue.CookieNotificationBar"] on the flow.google.com origin Not a cookie, which is why no profile carried SOCS and why grepping for a consent cookie found nothing. Measured by diffing cookies, localStorage and sessionStorage across a reject click on a throwaway profile: zero cookie changes, one new key. Three independent observations of the bar, not one: - a clean browser profile, never signed in: visible 4/4 - pr389fresh2, an authenticated profile this spike had never opened: visible 5/5 - ci-probe: visible 6/6 on the editor, both controls covered And proven by INTERVENTION rather than correlation. Removing that one key on ci-probe -- touching no cookie, so no auth -- flipped the editor from both controls hit-testable to both covered by span#glue-cookie-notification-bar-1-label. So the bar is the origin's DEFAULT state and a stored dismissal is what removes it. ci-probe was not singled out; every fresh gflow profile meets it on its first Flow load. THE CURE, AGAINST A LIVE BAR. With the bar restored by that intervention, the ordinary CLI command on the RELEASED build: cli_version 0.73.1, migrated.editor_ready -> migrated.cookie_bar_dismissed 86 ms later -> image_settings_applied -> prompt_typed -> status ok, media 257d8f79, a 651,576-byte ffd8ffe0 JPEG Pillow reads as 1024x1024 RGB. Still not measured, and said so: the covering geometry on a SECOND account's editor. denon82 and pr389fresh2 both redirect to /about, so origin-level presence is measured on three profiles and the occlusion on one. The live-verification ledger keeps its tag-time text and carries this as an addendum rather than being rewritten -- what shipped unverified should stay legible. Refs #780 Claude-Session: https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc
…al width (#785) TWO INDEPENDENT FINDINGS, both from catching a live occurrence. 1. THE /about RETRY FLAG IS NOW MEASURED. The 2026-09-10 spike got 0/5 -- the redirect had stopped reproducing on ci-probe -- and recorded that as unmeasured rather than as transience. It then named exactly what would settle it: catch a live occurrence and re-run with --attempts 5. While measuring the #780 consent bar, denon82 turned out to be redirecting. The script was run UNMODIFIED, so its pre-registered reading still governs: 5 of 5 landed on /about, over ~3 minutes, 31-35 s each. The session was healthy throughout (flow_session_cookie_present, not expired, sapisid present, 68 cookies) and the project is the account's OWN, listed by `gflow project list` on that same profile. So this is neither an expired session nor a project the account cannot see. Per the inherited reading, N/N means stable: a retry is doomed for an account in this state. `retryable=False` at raise_if_known_landing was a PRESERVED default and both the code comment and FlowAppError's docstring said so in as many words. Those two statements became false the moment this ran, and they are corrected here. Behaviour is unchanged -- the flag was already right; it just wasn't known to be. Still not measured, and said so: WHY the redirect happens, and whether it ever clears. What is newly excluded is narrow but real: not an expired session, not a missing project, not transience. This also explains, rather than merely notes, why the #780 spike could not measure the covering geometry on a second account's editor: denon82 and pr389fresh2 both land here, so neither mounts a composer at all. 2. AN AUTH TEST DEPENDED ON TERMINAL WIDTH. Found while running the suite for (1), and proven NOT to be my change by a control: same --basetemp, my edits stashed, still fails. test_auth_steps.py asserts substrings of Rich's output, which hard-wraps to the terminal. A temp path landing near the wrap column split the word: --basetemp=.../t9 -> "profile_e\nxperiments" -> FAILS --basetemp=.../t10b -> "profile_experiments" -> passes Same code, same assertion, one character of path. That is a latent CI flake waiting for a runner whose tmp path is a different length. Pinned COLUMNS at the shared CliRunner fixture rather than normalising newlines at each of the ten assertion sites -- the fixture is the single chokepoint, and fixing the symptom ten times would let the eleventh one in. Verified across the four path lengths that flipped it, then the full suite at the path that exposed it: 4234 passed. Refs #756 Claude-Session: https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc
…g Flow anything (#786) * spike(756): the /about redirect is decided client-side, without asking Flow anything #756 measured the redirect and declined to measure its cause; the 2026-09-10 spike could not investigate one because it had stopped reproducing. It reproduces stably on denon82 right now, and a stable reproducer is the condition a cause becomes measurable in -- so it was measured while the state was there. ci-probe went from reproducing to not in two days with nobody watching. Designed as an A/B rather than an inspection: reading only the failing account shows a page that redirects and a pile of requests, with nothing to say which is abnormal. Same capture on denon82 (fails) and ci-probe (opens); the finding is the difference. denon82 ci-probe document 200, no Location 200, no Location first navigation 146 ms /project 90 ms /project second navigation 338 ms /ABOUT 700 ms same /project total responses 7 43 batchexecute calls 0 20, first at 275 ms non-2xx from Flow none none NOT a server-side redirect: both documents are 200 with no Location, so the hop is the app deciding client-side 192 ms after its own first navigation commits. And it decides WITHOUT ASKING FLOW. The failing arm issued zero batchexecute calls -- not "called and was refused", never called. There is no 401/403/404 to point at because there is no request. The 16 rpcids the control makes are simply absent. The cross-arm timing is what makes that a finding rather than a race: the control had already made its FIRST rpc at 275 ms, before the failing arm hopped at 338 ms. Two runs, so suggestive rather than airtight -- but with zero calls in the 5.5 s after the hop too, the app is plainly not waiting on a Flow answer. Account-wide, not project-specific: a second denon82 project redirects identically, 2/2. Also already in hand: `gflow project list` on denon82 returns the redirecting project. The backend grants access while the frontend declines to open it. So the signal is present at page load rather than fetched. NOT established: which signal -- naming it means reading the document's embedded bootstrap payload, which is exactly where bearer tokens and account data live on this origin, and it was not read. #756's warning stands: a lead is not a cause, and no remedy should assert a mechanism this cannot see. What would settle it is the HAR harness, named in the doc. No code changes. This narrows the search for whoever picks up #756: it is not a permissions call being refused, so looking for one is a dead end. Refs #756 Claude-Session: https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc * spike(756): classify every response, and prove the hop is client-side properly CodeRabbit raised two findings on the first cut that could have falsified the headline, and both were right about the METHOD even though the conclusion survives. Fixed by re-running with better reporting rather than by arguing. 1. "Not a server-side redirect" did not follow from what was reported. `page.goto` resolves to the FINAL main resource after following any server redirect, so a 200 with no Location is equally consistent with a client hop and with a 302 to /about. `report()` only surfaced non-2xx, so a document 3xx would never have appeared at all. Now reported, and both discriminate: the document's RESOLVED url is /project/<id>, not /about (a server redirect resolves to the destination), and there is no 3xx anywhere in the failing arm. The conclusion holds; it is now supported. 2. "Zero batchexecute calls" is not "no Flow request". True, and the wording claimed more than the method checked -- the rpcid analysis only recognised routes carrying `rpcids=`, leaving every other Flow endpoint unexamined by omission. Every response is now bucketed as flow_batchexecute / flow_other / non_flow. Classified in full the finding is STRONGER than first stated: the failing arm's only request to flow.google.com is the document itself. Not zero of one route shape -- zero of everything else too. failing: batchexecute 0, other flow 1 (the document), non-flow 6 control: batchexecute 20, other flow 15, non-flow 8 3. Status comparison collapsed a multiset to a set, so [200] and [200,200] read as identical and a call made half as often would have hidden. Compares sorted lists now. Re-run end to end: identical on every row, ~3.5 hours after the first capture. Refs #756 Claude-Session: https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc
…erifiable (#790) * spike(787): Nano Banana 2 Lite is real and usable; its binding is unverifiable The capability spike the model-governance waiver demanded before this tier ships. PR #787 removes that waiver; this is what it was waiting for. RUNG 1 CHANGED THE QUESTION, TWICE. The 2026-08-26 cost/quota catalogue already establishes that image generation costs 0 Flow credits, so "cost" for an image tier means daily quota -- and that "daily quota has no such oracle. It is observable ONLY on exhaustion, via the 429." So the cost half of "cost/quality" cannot be answered without deliberately burning an account's day. Recorded as unanswerable rather than inferred. It also exposed a sharper question. migrated_composer builds its result with model_name_type=request.model.value -- it ECHOES our own request. The labs path reads generated["modelNameType"] from the response; this one does not. And image_records decodes ids, url, seed, prompt and dimensions with no model field at all. So "it generated an image with --model nano2-lite" proves the UI did not error, not that the tier bound. WHAT WAS MEASURED (4 generations, 0 credits). The tier is real: HARBOR_SEAL and "Nano Banana 2 Lite" both appear in HTrJv, Flow's own model catalogue for this account -- corroboration from a surface that is not our request reflected back. The quality is fine and is NOT ranked: both arms returned 1024x1024 RGB at 428,799 and 384,036 bytes with no visible degradation, lite slightly more textured. One prompt cannot rank two tiers and this does not try to. It supports the narrower claim the waiver needed: lite works and returns a usable image at full resolution. The binding is UNVERIFIABLE. Both ogiZ0b submit replies were real payloads (~1141 B) and neither carried any model token. Re-opening the project, HTrJv carries every model token and no media ids; Zzl0ze carries both media ids and no model tokens. The catalogue lists models, the media listing lists media, and nothing joins them. So neither #787's live check nor mine can establish that --model nano2-lite bound rather than silently falling back. That is the third pre-registered reading, reported as unmeasured. Surfaced and not about Lite: model_name_type on the migrated path is an unbacked claim on EVERY migrated image, for every tier. Pre-existing on develop, filed separately. Refs #787 Claude-Session: https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc * spike(789): widen the attribution search — the join is absent from a whole project load "Unverifiable" was challenged as too strong. Fair, and the boundary has moved. The first pass searched two replies and FILTERED, recording only ones already containing a media id or a model token. This pass removes the filter: every batchexecute reply on a project load, 20-21 of them, all checked. HTrJv 24,760 B all six model tokens no media ids Zzl0ze 41,906 B no model tokens both media ids tRARke 31,883 B none none 17 more 139-3,964 B none none No reply carries both. The join is absent from a whole project load, not merely unread on the two surfaces first checked. The page was checked too, because a UI that displays it proves the data is reachable. Two tier labels exist -- span.settings-summary and span.model-select-trigger-content -- but the first appears ON LOAD, before any interaction, so both are composer picker state rather than a property of an image. ONE READING REMAINS OPEN and would flip this: whether a tier label tracks the media you open. In one run the label read "Nano Banana 2" on load and "Nano Banana 2 Lite" after a thumbnail click -- either the settings pane showing current state, or the opened media loading its own settings into the composer, which would be attribution. The two could not be separated: thumbnail src does not carry the media id, so a per-media A/B could not be targeted, and a later run matched zero tiles. Named rather than buried. Two notes that reframe #789: gflow drives the SAME web app a user drives, so no privileged surface is being missed -- the difference is between HOSTS, since labs REST returns modelNameType per image and the migrated wire does not appear to. And Flow does store a model per media for VIDEO on the labs shape, so the concept exists in their data model, which is why "find the join" is worth keeping open rather than writing off. No evidence this is regional: region gating changes which models an account is OFFERED -- and this account is offered Lite -- not whether a reply carries a field. Untested from another region, so no claim either way. Refs #789 Claude-Session: https://claude.ai/code/session_01Nr4XuvvZv3PrL3pKEzkrLc
A missing .gflow_browser_strategy marker made the Playwright cookie reader raise SecurityError, which escaped normalization and was flattened into VERIFICATION_ERROR — whose guidance is 'check network connectivity', for a file on the user's own disk. It is also the state a failed FIRST login leaves behind, and VERIFICATION_ERROR is not GOOGLE_SESSION_ONLY, so a migrated-host fallback keyed on the latter would never run on those profiles. Adds a distinct PROFILE_MARKER_MISSING outcome, mirrored on the MCP twin as 409 / retryable=false. gflow credits raised 'aisandbox-pa authentication failed' with the remediation 'SAPISID cookie missing, expired, or unreadable' when labs.google answered 200 with no access_token — the normal shape for a migrated account. aisandbox-pa had not been contacted and SAPISID was fine, so the suggested re-login loop could never terminate. The raise now carries an accurate hint; credits stays labs-only on migrated accounts, tracked in #795. Refs #795, #796, #791
…ked (#794) The migrated composer parked its pooled page on about:blank in a bare `finally`, so on the FAILURE path it navigated away before FlowApiClient._capture_incident read the page -- whose own docstring promises to stage the bundle 'while the page is still alive'. Every migrated video and image failure shipped tag_counts.div = 0, a white screenshot and host_category = 'other' beside a network journal proving the app was alive. Reported in #792 as the driver losing its page handle on a portrait run; it is neither portrait-specific nor a lost handle -- the reporter's own viewport (1280x720, client.py:495) proves it was the driven page, captured one navigation too late. The park is deferred and drained at the top of the next locked body, before the route decision reads page.url. That placement covers the post_with_retry path, where a retryable 5xx re-enters the transport without passing the client's failure boundary -- attempt 2 would otherwise resume on a still-mounted composer and risk a double submit. Also removes a 4 s stall: _settle_if_redirecting on about:blank matches neither short-circuit and waits out URL_SETTLE_TIMEOUT_MS for a pattern a blank page can never take. The goto/settle ratchet carries the exemption with its reason. Verified live on a migrated account at zero cost by a new committed e2e case: FAILED in 46.3 s on develop, passed in 37.8 s with the fix, with div 0 -> 25, title 0 -> 81, host_category other -> flow_app. Refs #792
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release prep for v0.73.2 — a diagnostics and error-clarity patch.
Cut from
develop@15c58af0. Tagv0.73.2is signed and already pushed, so the release workflow has run; this PR brings the bump commit and the full integration history ontomain.What ships
flow.google.comfailure are no longer blank. The composer parked its own page onabout:blankin a barefinally, so the capture photographed a blank page. Deferred and drained at the top of the next run, which also covers thepost_with_retrypath the client boundary cannot see. Removes a 4 s stall from every parked run.PROFILE_MARKER_MISSINGoutcome, MCP twin returns 409 /retryable: false.gflow creditsno longer blames SAPISID for a host it never contacted./aboutmeasurement, a terminal-width test pin).Explicitly NOT fixed
Migrated login (#791) and #792's i2v dispatch failure are open. The release notes say so plainly rather than letting a migrated user infer otherwise from "auth errors fixed".
Gates
4241 offline tests ·
uv run pyright src0 errors · ruff clean · all six CI doc gates · wheel builds at 0.73.2 with no ZIP duplicates ·/gflow:doc-reviewPASS (8 fixes, two of them false claims this release contradicts) · live A/B on the affected surface by a committed e2e test, at zero cost.Full evidence:
docs/LIVE_VERIFICATION_v0.73.2.md.