Skip to content

chore(release): v0.72.0 - #771

Merged
ffroliva merged 7 commits into
mainfrom
chore/release-v0.72.0
Sep 9, 2026
Merged

chore(release): v0.72.0#771
ffroliva merged 7 commits into
mainfrom
chore/release-v0.72.0

Conversation

@ffroliva

@ffroliva ffroliva commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Release v0.72.0 — published to PyPI and GitHub Releases from the signed tag v0.72.0 (db5ac82f).

Brings the full develop integration history onto main.

Headline

Gates

  • Full suite with coverage: 4146 passed, 7 skipped
  • ruff / ruff format / pyright (at baseline) / hygiene / doc-links / website mirror + PII / council-memory / release-artifacts — all green
  • Wheel + sdist built clean, no duplicate ZIP entries, both 0.72.0

Live verification

docs/LIVE_VERIFICATION_v0.72.0.md — 7 verified sections, 3 recorded as NOT verified with reasons.

Auto-close verified on four paths against a migrated account at $0: auto-close fires (84.8 s, reproduced 3x), manual close still verifies (exit 0, never exit 12), --browser auto completes, and a window closed mid-2FA is noticed in 2 s (exit 8) where it previously ran the full 600 s deadline. Migrated-host CLI t2i re-run first-hand this cycle rather than shipping on the contributor's evidence.

Recorded as unresolved: the queued-MCP i2i twin failed with exit 27 naming a dialog it cannot identify — on an account that has already consented, so the message's leading hypothesis does not fit. No incident bundle is written for that error class, so nothing names the dialog. Filed as #770, which also proposes tracking per-account upload consent in the data layer so the guard can stop guessing. Not a regression from this release.

The OAuth-callback mechanism behind the poll fix is inferred, not proven#769 carries the spike that would settle it.

Doc-review

A three-reviewer council found four items the eight green CI gates could not see: an untracked LIVE_VERIFICATION_v0.72.0.md (links resolved against the working tree and would have 404'd once pushed), the CVE bump missing from the changelog, a disproved claim still stated as fact in an unmirrored tutorial, and a user-facing fix absent from the ledger. All four fixed before the tag.

ffroliva and others added 7 commits September 8, 2026 20:03
Drives `gflow image t2i` and local-file `i2i` on Google's migrated
`flow.google.com` frontend through the page-owned `ogiZ0b` batchexecute wire, and
skips the labs-only pre-transport reCAPTCHA mint on that route while preserving the
labs path. Contributed by @arjhinety, with plan → scenario → spike → BDD → live
verification on both the CLI and the queued MCP path.

The migrated host now serves t2v, i2v/r2v from local files, character create, and
image t2i/i2i from local files — each with `--project`. References by UUID or
`@Name`, character entities, Agent instructions, Imagen 4, `image batch` and the
3:4 image aspect are refused before submit with exit 36.

Council review across ten dimensions returned RED on the edges of an otherwise
sound slice; all seven must-fixes were closed before merge:

- The page-owned-reCAPTCHA capability was derived from `page.url`, and the image
  path parks the page on `about:blank` — which routes as `labs`. The SECOND image
  in one client session therefore fell back to minting on the pooled bootstrap
  page and died with the `RecaptchaError` of #673, the exact bug this slice
  removes. Invisible to every single-image test; reachable from `gflow image
  batch`, which runs every prompt through one `FlowApiClient`. The transport now
  latches the observed host, pinned by a regression test verified to fail without
  the latch.
- `generate_images_batch` had no migrated guard and drove labs selectors against
  `flow.google.com`, surfacing as `UiSelectorDriftError` (exit 23) — telling the
  user to file a frontend-drift bug about a working frontend. Now exit 36 before
  any submit.
- `--aspect 3:4` mapped to a `crop_portrait` ligature the spike never observed;
  the aspect radiogroup was enumerated with four radios. Now an unported form, with
  the measured set kept in its own constant so observed and assumed stay distinct.
- `FlowHostMigratedError` printed a remediation contradicting the detail directly
  above it. Remediation, class docstring and the video path's refusal string all
  now name the ported matrix.
- `llms.txt`, `.env.template`, `docs/INDEX.md` and both `skills/video-production/`
  files still said images exit 36. `llms.txt` is in the documentation gate's
  `CURRENT_OPERATOR_DOCS` precisely because a stale claim there costs the most.
- `submit_images_and_observe` had zero offline coverage — the trust branches (the
  route-error listener that refuses to report a text-only generation as i2i, a
  non-200 submit, the reply timeout) were reachable only from a live account. Four
  cases added; the i2i BDD step now drives `_image_body_problem` instead of
  asserting a decoded field.
- `migrated_image_can_serve` and `ImageGenerationRecord.reference_ids` removed as
  dead.

Verified: 14/14 CI checks green on 3.11/3.12/3.13; ruff, `pyright` 0 errors, all
five hygiene gates, and 3,074 scoped tests locally. E2E: `test_migrated_host_e2e.py`
covers CLI t2i and the MCP i2i twin, run by the contributor.

DCO: merged without a `Signed-off-by:` trailer, waived by the maintainer. Recorded
here rather than left silent.

Closes #692
Refs #639
Both found while running the v0.71.1 release gates. Neither is a product bug;
both are tests that pass while checking something other than what they claim.

#758 — test_key_is_never_forwarded guards a security property: a removed key
must never be resurrected as a fallback. It cleared the process env var with
delenv, but Settings ALSO reads the dotenv files from config._env_files(), so on
any machine whose repo-root .env sets GFLOW_CLI_LLM_API_KEY — the documented dev
setup — pydantic-settings loaded it straight back and the assertion failed. CI
stayed green because CI has no .env. So it failed for exactly the developers
whose environment could exhibit the leak it exists to catch, which is the
population most likely to learn to ignore it.

The fix is one fixture, not new machinery: clean_env already fences BOTH dotenv
entries into tmp_path, and TestCleanEnvHermeticity already documents this exact
hazard ('the repo root's gitignored .env is the documented dev setup'). The test
simply never used it.

#760 — pytest inside a git worktree imports gflow_cli from the MAIN checkout.
A worktree has no .venv of its own; the venv's editable install pins src/ in the
primary checkout. So a worktree run executes the worktree's TESTS against the
other tree's SOURCE, and it fails OPEN: a release branch runs its own gates,
sees green, and has validated code it is not shipping — and a regression on that
branch passes, because the healthy tree answered for it. /gflow:release step 5
REQUIRES cutting in a worktree, so every release carried this exposure.

It surfaced during v0.71.1 only because one newly added assertion happened to
differ between the trees. Nothing structural would have caught it, so this is a
hard UsageError at pytest_configure rather than a warning.

The check is deliberately narrow: it fires only when a local src/gflow_cli
exists beside the tests AND the import came from elsewhere. Testing an installed
wheel, where no local source tree is present, is untouched.

Refs #758, #760
`Dependency audit (pip-audit)` went red on develop against an UNCHANGED lock:
neither #750 nor #762 touched `uv.lock` or `pyproject.toml`, and the same job
passed on #750's own PR run about an hour earlier. These are newly published
advisories, not a regression either PR introduced.

    httpcore2 2.9.1  CVE-2026-84381  fix 2.10.0
    httpx2    2.9.1  CVE-2026-84378  fix 2.10.0
    httpx2    2.9.1  CVE-2026-84379  fix 2.11.0
    httpx2    2.9.1  CVE-2026-84380  fix 2.11.0
    httpx2    2.9.1  CVE-2026-84382  fix 2.12.0

Both arrive transitively through `mcp`. 2.12.0 clears all five.

The bump also adds `httpx2-jsfetch` 1.0 to the lock, which is worth naming rather
than letting it pass as noise in a lockfile diff: httpx2 2.12.0 splits its transport
so a browser build can use JS fetch, and the dependency is marked
`sys_platform == 'emscripten'` — Pyodide/WASM only. It is never installed on any
platform gflow supports, and `anyio`, `httpcore2` and `truststore` gain the
complementary `!= 'emscripten'` markers in the same refactor.

Verified: `uvx pip-audit==2.10.1` on the exported requirements reports "No known
vulnerabilities found"; `uv sync --frozen` installs 2.12.0; 194 MCP + smoke tests
and 1781 api/features/worker tests pass on the new resolution.
…nar gate (#765)

`run_images` and the trust branches of `submit_images_and_observe` had no offline
coverage at all — every image test mocked `run_images` away. That put
`new_coverage` at 77.4% against an 80% gate, so #750's merge turned develop's
SonarCloud check red even though the PR itself was 14/14 green: SonarCloud is
skipped on fork PRs, so the gate first ran on the merge commit.

The coverage gap and the risk were the same thing. What was untested was the
orchestration that decides whether a run is trustworthy:

- `run_images` end to end against the existing FakePage — the happy t2i path, the
  pre-submit refusal of an unported form, the missing-`--project` ConfigurationError,
  and the case where references upload but never become mention chips. That last one
  is the silent-degrade-to-T2I failure: Flow accepts the submit, bills it, and returns
  a plausible image that ignored the reference.
- The image submit's own credits check. It is a second copy of the video path's, so it
  needed its own proof: a drained wallet REPLACES Flow's submit button (#721), and
  reporting that as selector drift tells the user to file a frontend bug that no code
  change can fix. Both directions are pinned — warning present means insufficient
  credits, warning absent means the anchor really is gone and drift is correct.
- The submit-stays-disabled timeout.

migrated_composer.py coverage 88% -> 92%, uncovered lines 92 -> 67; `run_images`
(2094-2124) goes from entirely unexecuted to fully covered.

No src/ change, so no Flow surface is touched and an e2e run is out of scope for
this commit rather than left blank.
`gflow auth login` now drives real Chrome through Playwright, watches for the
completed Flow sign-in and closes the window itself. Closing it yourself still
verifies. Where Playwright cannot resolve a Chrome channel, or Google rejects
the browser, login falls back automatically to the previous subprocess flow —
no new flag, nothing to choose.

Built on the 2026-09-08 spike (docs/superpowers/spikes/): G12 blocks
`navigator.webdriver`, NOT Playwright or bundled Chromium. Real Chrome without
the stealth flags was rejected at /v3/signin/rejected in 17.5 s; bundled
Chromium with them signed in normally. The `bare` control arm is what made that
conclusive.

Live-verified on four paths (evidence in the PR thread):
- auto-close fires end to end — elapsed_s 84.8, reproduced 3x
- manual close verifies from disk — exit 0, never exit 12
- `--browser auto` selects and completes
- window closed mid-2FA — noticed in 2 s, exit 8, not a 600 s hang

Four defects the live runs and a council review forced out, none of which
offline testing had surfaced:

- The session poll was hitting `/fx/api/auth/session` every 3 s throughout
  login, including mid-callback. That is the real cause of the 2026-09-08
  600 s timeout, which had been recorded as "timed out un-driven".
- Gating that poll on `labs.google` alone would have timed out on every
  migrated account — i.e. both maintainer accounts.
- A host check does not exclude NextAuth's callback at all: it runs on the
  app's own origin, so `/fx/api/auth/callback/google` passed straight through.
  The gate now excludes the auth routes too.
- `page.is_closed()` was reachable only via `except PlaywrightError`, so a
  window closed while on Google's host was never noticed — a full deadline
  wait, session endpoint touched 0 times.

Also replaces a fourth copy of the Flow-host set with the existing
`flow_host_kind` (https-required, exact-host, ValueError-safe), fixes
`POLL_INTERVAL_SECONDS` governing only one of two sleeps, and drops three
exit-14 doc remediations prescribing advice the spike disproved.
@ffroliva
ffroliva merged commit 43e0b58 into main Sep 9, 2026
16 checks passed
@ffroliva
ffroliva deleted the chore/release-v0.72.0 branch September 9, 2026 15:00
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.

2 participants