test(phone-scroll): split the 2100-line spec, and fix two coverage holes it exposed - #1466
Conversation
…les it exposed `ui-phone-scroll.spec.ts` was 2104 lines and 56 tests — 267s, 65% of shard 1, at the worst per-test rate of any large spec in it, and the file behind both `#127` and `#146`. It is now three files over a shared `tests/helpers/phone-scroll.ts`: ui-phone-scroll.spec.ts 21 shared shell header hide/reveal, per-mode top edge, collapse owner ui-phone-scroll-routes.spec.ts 19 per-route breadth sweep ui-phone-scroll-page-owned.spec.ts 16 document-viewer composer, standalone frame-owned footers, calculators dock The seam is the page-owner model docs/search-chrome-behaviour.md already defines, not an arbitrary cut. Test bodies are moved byte-identical, and the split is proven behaviour-neutral: 56 passed (4.3m) in Chromium, 16/19/21, against 342 tests/56 phone-scroll collected both before and after. THE STATED REASON FOR THIS SPLIT IS REFUTED, and that is recorded rather than quietly dropped. It was justified — here and in PR #1453 — as the only lever that rebalances the shards. Measured against a live server, it rebalances nothing: shard 1/2/3 stay at 121/111/110 with all 56 still in shard 1. `--shard` does not distribute files; it walks them in alphabetical collection order and cuts at test-count boundaries, so three siblings named ui-phone-scroll* land together. The shards were already count-balanced — the imbalance is duration. docs/process-hardening.md now carries the measurement, the real lever (explicit per-shard spec groups, ~2 min of a 13m39 critical path against a hand-maintained list in the required UI job), and a stop rule against renaming specs to game the sort order. What the split does buy is a 2100-line file broken along ownership lines, and the two coverage holes that fell out of doing it: 1. scripts/phone-chrome-plan.mjs greps four ownership journeys out of ui-phone-scroll.spec.ts. All four moved to the page-owned file, so the ownership stage would have selected zero tests. Redirected, and phoneChromeBrowserSpecPattern widened so a changed sibling is recognised. 2. Pre-existing and worse: nothing under tests/helpers/ was in uiPatterns. Editing zero-touch.ts — imported by SIX required browser specs including ui-smoke — reported ui_changed=false, so Production UI skipped and the change reached no browser at all, on a green pull request. Three of the four files in that directory back ui-*.spec.ts journeys. Matched at directory level: a hand-list is what failed, and the one non-UI file costs an extra UI run against a miss that is silent. playwright.config.ts's two spec regexes carried an exact `phone-scroll` alternative that would not have matched either sibling. Both arms are now open (`phone-scroll(?:-[a-z0-9-]+)?`) so a future sibling runs rather than quietly not running, and playwright-project-isolation.test.ts asserts every ui-phone-scroll*.spec.ts on disk is matched by both — reading the literals out of the config and failing CLOSED if either constant is renamed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
…and #146 Conflict was docs/outstanding-issues.md only. Took main's copy wholesale (it carries #122's closure and the #98/#130 records from #1455) and re-applied the two one-line relocation notes, rather than hand-editing the conflict region. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 30 minutes Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughChangesPhone scroll coverage and execution hardening
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Comment |
CI triageCI failed on this PR. Automated classification of the 2 failed job(s):
Compared with main CI run #7314 (cancelled). Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger. |
`Unit coverage` failed on this PR's first CI run with
SyntaxError: Unexpected end of JSON input
tests/test-runner-safety.test.ts:321:31
in "gives a queued heavyweight process priority over later focused work" —
4581 passed, 1 failed, and nothing in this branch's diff goes near the run
lock. It is not this branch's flake, but it is a real defect and it was
blocking a required check, so it is fixed here rather than re-rolled.
`writeJson` published every coordinator record with a plain `writeFileSync`.
Every reader of those records is concurrent by construction — the queue exists
so separate processes can watch each other — so a reader can observe a file
half-written.
The crash was the mild symptom. The coordinator's own reader has always
swallowed the parse error (`readJson` returns null, `queueRecords` filters it
out), which means a torn read does not surface at all: the queued ticket simply
*disappears* for that poll and `hasTickets` reports false while a queued
exclusive waiter is sitting right there. That is the priority inversion the
queue exists to prevent, and the tolerant reader was hiding it.
`writeJson` now writes a sibling temp file and renames over the target.
`renameSync` is atomic within a filesystem, so a reader sees the old file or
the complete new one and never a fragment. The temp name deliberately does not
end in `.json`, so `listJsonFiles` cannot pick it up mid-flight, and a failed
write removes the temp file rather than leaving residue.
The test's poll is also made tolerant, matching what the coordinator's reader
already did — it was the only reader that treated an unparseable file as fatal.
It stays tolerant after the atomic-write fix because the test should measure
ordering, not write timing.
Verified: tests/test-runner-safety.test.ts run 5x, 27 passed each time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
This was a REAL conflict, not staleness, and it is why PR #1466 had no `CI` workflow run at all — only the four `pull_request_target` checks. GitHub could not build refs/pull/1466/merge. That is #116's signature: a missing check list is a conflict signal, not a green pass. `git merge-tree` exited 1 on tests/ui-phone-scroll.spec.ts while `PR mergeability` still showed success from before main advanced. main's #1432 edited a hunk inside the `phoneOwner` loop — precisely the region this branch moved to ui-phone-scroll-page-owned.spec.ts — so git saw one side delete the region and the other modify it. Resolved by taking this branch's shell-only ui-phone-scroll.spec.ts and re-applying #1432's change at its new home. That change is a genuine flake fix (sheet focus restoration retries after 50 ms when focus falls through to <body>, so a bare blur races the retry and can re-pin the header), and dropping it in a merge would have silently reintroduced the flake — the same fails-by-running-nothing class this branch exists to close. It went to the occurrence in the section-sheet round-trip, matched by the hunk's own context, not the similar-looking line 95 lines earlier. No content lost, proven rather than asserted: every non-trivial line of main's ui-phone-scroll.spec.ts is present across the three split files plus the shared helper. The only 22 differences are declarations that gained an `export ` prefix and the two imports whose path changed depth. Verified on the merged tree: verify:cheap exit 0, Test Files 437 passed (437), Tests 4588 passed | 4 skipped (4592); tsc --noEmit clean; prettier --check . clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6320250c6b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Second time a real conflict has blocked this PR's CI entirely — GitHub could not build refs/pull/1466/merge, so no pull_request workflow ran and the thin check list read as pending rather than blocked (#116). Only docs/outstanding-issues.md conflicted; scripts/ci-change-scope.mjs and docs/process-hardening.md auto-merged (main's regions are 150+ lines from this branch's). Took main's ledger wholesale rather than hand-editing a 140-row table around conflict markers. Only ONE of this branch's two ledger edits was re-applied: - #146 keeps its relocation note. The row is still open, and main's #1481 added two further data points to it (head c739340, anchorTop expected -138 received -7; six data points, two failures, shard 1 only) which are left untouched. - #127's edit is DROPPED as obsolete. Main's #1487 archived that row, and the archived form no longer cites tests/ui-phone-scroll.spec.ts at all, so there is nothing left to relocate. Re-applying it would have matched nothing or corrupted a differently-shaped row. Marker is main's 149 (not this branch's 147): #149 was allocated, withdrawn and retired rather than reused. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
Codex P2 on PR #1466, and it is correct — this branch created the hole. A change confined to tests/helpers/phone-scroll.ts is `playwrightHelper` scope, which selects the focused ownership journeys: four grepped cases in ONE spec. Before the split that was adequate, because the helper and every consumer were the same file. After it, three specs import the helper and the plan named one: [focused-browser] run-playwright ui-phone-scroll-page-owned.spec.ts ui-smoke ui-tools --grep "phone browser results use document scrolling|document detail header overlay…" So a regression in a shared function — readGeometry, installFlipCounter, dragScrollBy — passed `verify:phone-chrome`, the gate AGENTS.md names for phone-chrome work, while two of the helper's three consumers never ran. CI would still have caught it via ui_changed, but the local gate reported green, which is the worse failure because it is the one people trust before pushing. A change to the helper now expands to all three consumers and runs them in full, as if each had been edited directly: [changed-browser] run-playwright ui-phone-scroll-page-owned.spec.ts ui-phone-scroll-routes.spec.ts ui-phone-scroll.spec.ts --project=chromium The redundant ownership grep drops out of focused-browser on its own, since those journeys are now covered by a full run of their own file. Two guards, because a hand-maintained list of spec names is precisely what failed here and the miss does not go red — it runs nothing: - the plan for a helper-only change must contain all three specs and no --grep - the list must equal the specs that actually import the helper, read from disk, so a fourth sibling cannot be added without updating it Both mutation-proven: dropping a consumer from the list fails the parity test, and reverting the expansion fails the plan test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
…onflict loop Third consecutive real conflict blocking this PR's CI, always the same file, and the fix is to stop touching it rather than to resolve it a fourth time. main's newest commit is `fix(ledger): stop Prettier padding the issues table, closing #133 (#1479)` — a whole-file reformat of docs/outstanding-issues.md. Every row changed shape, so any edit to any row conflicts. That file is also touched by nearly every main PR (row appends, archival moves), and this branch is competing with a queue that merges several times an hour. This PR's entire stake in it was ONE cosmetic line: a note on #146 saying the cited spec moved to ui-phone-scroll-page-owned.spec.ts in the split. Three CI-blocking conflicts — each one stopping GitHub building refs/pull/1466/merge so no pull_request workflow ran at all — is a bad trade for that. So the file is taken from main verbatim and the note is not re-applied. This PR's diff no longer contains docs/outstanding-issues.md, which removes its only remaining contact point with the hottest file in the repo. Cost, stated rather than hidden: #146 keeps citing the old path. That row already records that the exact test title is the durable identity because declaration lines drift, so the stale path misleads nobody who reads it. The note belongs in a docs-only PR when the ledger is not mid-reformat. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
Fixed in |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/process-hardening.md`:
- Around line 189-193: Specify the `text` language on the fenced code block
containing the shard listing, changing its opening fence while preserving the
listing contents and closing fence.
🪄 Autofix (Beta)
✅ Autofix completed
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 38fb3b60-b31a-45b1-9da9-a536370a81a4
📒 Files selected for processing (13)
docs/process-hardening.mddocs/search-chrome-behaviour.mdplaywright.config.tsscripts/ci-change-scope.mjsscripts/phone-chrome-plan.mjsscripts/test-run-lock.mjstests/helpers/phone-scroll.tstests/playwright-project-isolation.test.tstests/test-runner-safety.test.tstests/ui-phone-scroll-page-owned.spec.tstests/ui-phone-scroll-routes.spec.tstests/ui-phone-scroll.spec.tstests/verify-phone-chrome.test.ts
…f sleeping
Root-caused from the failure trace (run 30582678887 artifact 8775836025), not
inferred. Two snapshots either side of the resize:
before anchorTop -138 documentScrollTop 504 headerBottom 0
after anchorTop -7 documentScrollTop 504
`documentScrollTop` is IDENTICAL at 504. The scroll position never moved; the
content shifted down 131 px. And 131 is not arbitrary — the trace records
collapseHeight 72, and gotoPhoneSurface injects --safe-area-top:59px. 72 + 59 =
131. The resize transiently re-shows the shared header, which reclaims its
collapse row AND its safe-area band, and the assertion measured mid-transient.
The cause is the fixed `waitForTimeout(100)` immediately after
`setViewportSize`. That is the same sleep-and-hope pattern PR #1427 removed from
`addPhoneScrollRunway`, and it explains every observation #146 has collected:
- bimodal, never in between: the two states are "settled hidden" (-138) and
"header fully re-shown" (-7), nothing between them
- pixel-identical across runs: -138/-7/131 reproduced on three separate heads
and two different PRs, which timing jitter cannot do
- "under CI load": load pushes the settle past 100 ms, nothing more exotic
- documentScrollTop unchanged: only chrome layout moved
This also retroactively settles the narrowing that #146 WITHDREW. That row once
argued the scroll position held because the sibling documentScrollTop assertion
did not fail — invalid, since Playwright aborts at the first failing expect so
it never ran. The conclusion was right anyway: the trace shows 504 on both
sides. It is now measured rather than inferred.
The fix polls the same geometry the hidden-state assertions already use
(`header#search` bottom <= 1) with a 10 s budget and a message naming the
condition. The tolerance is untouched — #146's stop rule forbids loosening it,
and loosening it would have hidden a real 131 px content jump.
Note what this does NOT claim: if the header ever fails to re-hide rather than
merely settling slowly, the poll times out and the test fails naming that. That
is strictly better than a 100 ms coin flip either way.
Verified: the previously-failing test 3x consecutively (1 passed each), and the
full spec 16 passed (43.0s). Local passes are weak evidence for a load-dependent
race; the mechanism change is the argument.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JHLPEV4o1rzipPDqshCSHY
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Fixes Applied SuccessfullyFixed 1 file(s) based on 1 unresolved review comment. Files modified:
Commit: The changes have been pushed to the Time taken: |
Fixed 1 file(s) based on 1 unresolved review comment. Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
|
Temporarily paused during the owner-authorized ordered merge sweep so |
|
@cursoragent this PR will be re-opened soon. Please resolve any failing CI, run bugbot and resolve any bugbot comments against current repo and fix any merge conflicts and also fix any errors and address and fix all comments or suggestions that are likely to improve the PR and Codebase. Please implement smallest required fix according to best code practices. Check your work. Leave this PR closed for now but still make all these changes and run the review. I want it ready to go for when I re-open it. |
|
PR #1466 is ready to reopen and remains CLOSED. Branch tip: Done
Fixes landed
Verification
On reopen, GitHub should move the PR head to |
Bring the closed PR tip current before reopen. merge-tree was clean; no outstanding-issues.md stake on this branch. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
phoneChromeBrowserSpecPattern already recognised ui-phone-scroll-{routes,
page-owned}.spec.ts, but phoneContract still exact-matched only the base
file. A sibling-only edit therefore ran changed-browser while skipping
contracts and reporting phoneRelevant=false — the incomplete-gate half of
the same silent-miss class this PR closes. Widen the suffix arm and pin
sibling plans in verify-phone-chrome.test.ts.
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
git remote get-url applies global url.*.insteadOf rewrites. Cursor Cloud injects token insteadOf rules, so a credential-free origin appears credential-bearing and ensureOriginRemote refuses to preserve it after add — breaking the new origin-repair tests under verify:cheap. Read remote.origin.url from config (the stored value) and assert the same in tests. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Append-only review record for the closed-PR readiness pass: main merged, phoneContract sibling fix, Codex Cloud origin inspect fix, review threads cleared, Bugbot none. PR left closed. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
@cursoragent This PR was just reopened. Do not merge, force-push, rebase, or arm auto-merge
|
1. Snapshot (reopen)
2. SyncSynced once: 3. CI on this tipFresh runs queued/in progress on
4. ThreadsNone actionable. Prior Codex/Copilot/CodeRabbit threads stay resolved. 5. Stop
Tip: Residual: |
Reopened PR #1466: GitHub reported DIRTY/CONFLICTING while merge-tree was clean (behind-by 1). Sync once so refs/pull/1466/merge can build and pull_request CI can run. No content conflict. Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>


Summary
tests/ui-phone-scroll.spec.ts(2104 lines, 56 tests) into three files over a sharedtests/helpers/phone-scroll.ts. Test bodies moved byte-identical; the seam is the page-owner modeldocs/search-chrome-behaviour.mdalready defines.tests/helpers/was inuiPatterns, so editing a shared Playwright fixture skippedProduction UIentirely.scripts/phone-chrome-plan.mjs, whose ownership stage would have selected zero tests after the split.fecd190). Unrelated to the split, but it failed this PR's firstUnit coveragerun and is a real defect, not a re-roll candidate. Its own commit, independently revertible.RAG impact: no retrieval behaviour change — nothing under
src/lib/rag/**, clinical-search, retrieval-selection, ranking-config, answer-ranking, the eval harness, or the golden fixture is touched.ui-phone-scroll.spec.tsui-phone-scroll-routes.spec.tsui-phone-scroll-page-owned.spec.tsThe reason for this split is refuted, and that is the useful result
It was justified — in
docs/process-hardening.mdand in PR #1453 — as "the only lever that rebalances the shards, because--shardcannot divide a single file." Measured against a live server, it rebalances nothing:--sharddoes not distribute files. It walks them in alphabetical collection order and cuts at test-count boundaries, so three siblings namedui-phone-scroll*sort adjacently and land in the same shard. The shards were already count-balanced — the imbalance is duration:Shard 1 is slow because it holds ten slow-per-test files, while shards 2 and 3 are each dominated by one fast-per-test file. The only lever that would actually rebalance is explicit per-shard spec groups in
ci.ymlinstead of--shard=i/N.docs/process-hardening.mdnow carries that trade rather than the change: perfect balance is ~7m37 against a measured 9m36 largest shard — about 2 min of a 13m39 critical path — bought with a hand-maintained file list in the required UI job whose miss mode is a spec silently running nowhere. It also carries a stop rule against the tempting hack of renaming specs to game the sort order.Two coverage holes, both the "second hand-maintained list" shape
1.
tests/helpers/**was invisible toui_changed— pre-existing, and the more serious of the two. Three of the four files in that directory backui-*.spec.tsjourneys, andzero-touch.tsalone backs six of them includingui-smoke. Editing any of them reportedui_changed=false, soProduction UIskipped and the change reached no browser at all, on a green pull request. Matched at directory level rather than by filename — a hand-list is exactly what failed here — and the one current non-UI file (supabase-round-trip-counter.ts) costs one extra UI run when it changes, against a miss that is silent.2.
scripts/phone-chrome-plan.mjswould have selected zero tests. Its ownership stage greps four journey titles out ofui-phone-scroll.spec.ts; all four moved to the page-owned file. Redirected, andphoneChromeBrowserSpecPatternwidened so a changed sibling is recognised as a phone-chrome browser spec at all.playwrightHelpernow includes the new shared fixture so editing it selects the phone-chrome plan.Config regexes.
playwright.config.ts'sproductionSpecPatternandtestMatchboth carried an exactphone-scrollalternative that matches neither sibling — they would have been collected by nothing. Both arms are now open (phone-scroll(?:-[a-z0-9-]+)?) so a future sibling runs rather than quietly not running, andtests/playwright-project-isolation.test.tsasserts everyui-phone-scroll*.spec.tson disk is matched by both. It reads the regex literals out of the config source (the config cannot be imported — it resolves a base URL at module scope) and fails closed if either constant is renamed.The coordinator write race (
fecd190)This PR's first CI run failed
Unit coveragewithSyntaxError: Unexpected end of JSON inputattests/test-runner-safety.test.ts:321, in "gives a queued heavyweight process priority over later focused work" — 4581 passed, 1 failed, and nothing in the split's diff goes near the run lock.writeJsoninscripts/test-run-lock.mjspublished every coordinator record with a plainwriteFileSync, and every reader of those records is concurrent by construction. The crash was the mild symptom: the coordinator's own reader has always swallowed the parse error (readJsonreturns null,queueRecordsfilters it out), so a torn read does not surface at all — the queued ticket simply disappears for that poll andhasTicketsreports false while a queued exclusive waiter is sitting right there. That is the priority inversion the queue exists to prevent, and the tolerant reader was hiding it.Now written to a sibling temp file and renamed over the target.
renameSyncis atomic within a filesystem; the temp name deliberately does not end in.jsonsolistJsonFilescannot pick it up mid-flight; a failed write removes the temp rather than leaving residue. The test's poll is also made tolerant, matching the coordinator's own reader — it was the only reader treating an unparseable file as fatal.Verification
npm run test:e2e -- tests/ui-phone-scroll.spec.ts tests/ui-phone-scroll-routes.spec.ts tests/ui-phone-scroll-page-owned.spec.ts --project=chromium—56 passed (4.3m), 0 failed, 16/19/21 per file342 tests in 18 files/ 56 phone-scroll before,342 tests in 20 files/ 56 afternpm run verify:cheap—Test Files 436 passed (436),Tests 4578 passed | 4 skipped (4582), exit 0tests/test-runner-safety.test.tsrun 5× consecutively —27 passedeach timenpm run check:ci-scope— self-test passes including the newplaywright-shared-fixturescasenpx prettier --check .—All matched files use Prettier code style!node scripts/check-outstanding-issues.mjs—144 rows (70 open, 74 archived), unique ids, next-id=147 above the highestTwo local failures were diagnosed and are not defects in this branch:
browserType.launchin 3ms — that is#121(container Chromium 1194 vs pinned 1234). The green result above is the re-run withPLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/opt/pw-browsers/chromium.verify:cheapfailedinstalled-lock-paritywithexpected 10000000 to be less than or equal to 40000— stalenode_modules(brace-expansion1.1.16) against the lockfile this branch merged from main's build(deps): patch brace-expansion denial of service #1456.npm ci --include=devbrought it to 1.1.18 and the gate passed. That guard did exactly its job.verify:phone-chromenot run as a whole: its browser stage is the same three specs already run directly above, and its contract stage is inside theverify:cheapunit run.Not run, deliberately:
verify:release,eval:*,check:supabase-projectare provider-backed and not authorised here.Risk and rollout
tests/helpers/**widening can only causeProduction UIto run more often, never less. The atomic write can only narrow a race.git revertany of the three commits independently. TheuiPatternswidening and the coordinator fix are both independently valuable and address defects that predate this branch.Notes
#127and#146both cite the old file; their rows now name the new one, with the reminder that the exact test title is the durable identity because declaration lines drift.The pattern across the last three changes on this branch is the same defect wearing different clothes: a list of spec or component names maintained in two places, where the copy that goes stale fails by running nothing rather than by going red. Three instances found in one day (mockup components, phone-chrome ownership journeys, shared Playwright fixtures). Each is now guarded individually; a general rule — that any list naming test files must be derived from or asserted against the filesystem — is probably the real fix, and is not attempted here.
Summary by CodeRabbit
Bug Fixes
Tests
Documentation