Repository navigation
fix(selectors): anchor the New project CTA on add, and revert a guard I got wrong - #740
Merged
Merged
Conversation
…rd I got wrong Live verification overturned my own fix from an hour earlier. That is the headline. #739 shipped a guard raising FlowHostMigratedError, asserting flow.google.com "renders no '+ New project' control gflow can drive". A $0 run of _enter_editor with no project id CREATED A PROJECT there in one click. The claim was an UNPROVEN NEGATIVE - generalised from a sweep of two other surfaces (composer, character editor) to a third that was never probed. The gallery is where NEW_PROJECT_SELECTORS actually lives, and I never measured it. That is the exact failure this session has been documenting, committed by me hours after writing the rule into repo memory. WHAT THE GALLERY ACTUALLY SHOWS (denon82, control 47 ligature nodes, $0): add* ligatures {"mat-icon|add": 1} [0] add_2 / i.gs 0 [1] add_2 / i 0 [2] add_2 / role=button 0 [3] text-matches regex ERR Error [4] has-text('New project') 1 <- the ONLY match So the ligature finding was right - `add`, never `add_2` - and the conclusion was wrong. The CTA is present and clickable; every structural Tier-1 entry missed and it survived purely on the ENGLISH TEXT fallback, which is the anti-pattern Tier 1 exists to prevent and which fails outright on a non-EN migrated profile. My guard would then have told that user the control does not exist: false, and a dead end. Fixed with a class-only `add` anchor leading Tier 1, covering both carriers. Re-measured live: entry [0] now matches 1 where every previous entry matched 0. ALSO DELETED: button:text-matches('^\+\s+\S+$', 'i'). It is not a valid Playwright selector and RAISES on every evaluation - observed twice against the live gallery - with `except Exception: continue` swallowing it. It never matched anything on any host while costing a round trip per attempt. TWO GUARD TESTS CAUGHT THIS CHANGE, AND ONE OF THEM WAS THE PROBLEM: - test_new_project_selectors_icon_leads pinned the add_2 selector exactly. Updated to the measured anchor, with the measurement as its reason. - test_new_project_selectors_plus_regex_is_anchored asserted the regex was ANCHORED - a property of a selector that never ran. It inspected the string instead of evaluating it, so it passed happily for as long as the selector was broken. Replaced with the guard that would have caught the real bug: every shipped cascade entry must PARSE against a real CSS engine (.count() on a blank page - no account, no network, no credits), plus a companion asserting the known-bad selector DOES raise, so the guard cannot quietly stop discriminating. Verified: 4069 passed, pyright 0 errors, ruff clean, doc links, hygiene, website mirror, memory round trip, PII scan - and the `add` anchor re-measured on the live gallery. Refs #730
Merged
tranzmatt
pushed a commit
to tranzmatt/gflow-cli-unofficial
that referenced
this pull request
Sep 9, 2026
Version bumped in pyproject.toml, .codex-plugin/plugin.json and src/gflow_cli/__init__.py. CHANGELOG [Unreleased] migrated to [0.71.0] with the compare/vPREV...vNEW footer the repo already uses. Gates on this tree: repo hygiene 1034 files clean, doc links 29 resolved, website mirror in sync, website PII clean, council memory 49/49, ruff, ruff format, pyright 0 errors, and the offline suite 4070 passed / 24 skipped at 92% coverage against an 80% floor. An earlier run of that suite reported two failures and both were mine, not the release: I bumped __init__.py while it was running, and I started a scoped pytest against the shared tmp/pytest basetemp alongside it. Each passes in isolation, and the suite above is a clean re-run with nothing else touching the tree. Recording it because "two tests failed, then passed on a re-run" is exactly what a real flake looks like and this was not one. docs/LIVE_VERIFICATION_v0.71.0.md carries the 5-layer ledger, and docs/INDEX.md points at it as the latest. The headline item is that `gflow character create --voice` is verified end to end for the first time: before this release a repo-wide grep for `--voice` across tests/e2e/ matched nothing. It also settles a contradiction between two of our own documents (`sent='Charon' stored='Charon' identical=True`). This release contains a mistake and its retraction twice over, and the notes say so rather than presenting only the corrected state: - ffroliva#739 asserted the migrated gallery renders no "+ New project" control; a $0 run created a project there in one click, and ffroliva#740 anchors the CTA on `add` instead of on English text. - The entity guard was given the reason "the backend rejects it"; entity-bound generations are in fact accepted and queued, and ffroliva#742 retracts it. What fails is the observer, on a null MZZa6b payload against a 60s budget. One item is recorded as NOT verified rather than omitted: whether a bound character's voice reaches rendered audio (ffroliva#738). Attachment is proven, application is not, and the blocker is no longer credits or account access but retrieval.
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.
Summary
Live verification overturned my own fix from an hour earlier. That is the headline, and it is the reason this PR exists.
#739 shipped a guard raising
FlowHostMigratedError, assertingflow.google.com"renders no '+ New project' control gflow can drive". A$0run of_enter_editorwith no project id created a project there in one click.The claim was an unproven negative — generalised from a sweep of two other surfaces (the project composer and the character editor) to a third that was never probed. The gallery is where
NEW_PROJECT_SELECTORSactually lives, and I never measured it.Refs #730
What the gallery actually shows
denon82, control 47 ligature nodes,
$0:The ligature finding was right —
add, neveradd_2. The conclusion was wrong. The CTA is present and clickable; every structural Tier-1 entry missed, and it survived purely on the English text fallback — the anti-pattern Tier 1 exists to prevent, and one that fails outright on a non-EN migrated profile. My guard would then have told that user the control does not exist: false, and a dead end.Fixed with a class-only
addanchor leading Tier 1, covering both carriers. Re-measured live: entry[0]now matches 1 where every previous entry matched 0.Also deleted: a selector that never worked
button:text-matches('^\+\s+\S+$', 'i')is not a valid Playwright selector. It raises on every evaluation — observed twice against the live gallery — andexcept Exception: continueswallowed it. It has never matched anything on any host, while costing a round trip per attempt.Two guard tests caught this change, and one of them was the problem
test_new_project_selectors_icon_leadspinned theadd_2selector exactly. Updated to the measured anchor, with the measurement as its stated reason.test_new_project_selectors_plus_regex_is_anchoredasserted the regex was anchored — a property of a selector that never ran. It inspected the string instead of evaluating it, so it passed happily for as long as the selector was broken.Replaced with the guard that would have caught the real bug: every shipped cascade entry must parse against a real CSS engine (
.count()on a blank page — no account, no network, no credits), plus a companion asserting the known-bad selector does raise, so the guard cannot quietly stop discriminating.Validation
pytest -q --cov— 4069 passed, 7 skippedpyright src0 errors ·ruff check/format --checkcleanaddanchor on the migrated galleryE2E: the CTA path is only reached when a generation runs without
--project. The live gallery probe above is the direct evidence for the changed selector, and it is stronger than an e2e for this purpose: it counts what each cascade entry matches, rather than confirming that something in the cascade worked. Not re-running the character-create e2e — that path passes--projectand never touches this code.