Skip to content

test(ui-react): split navigation reach pointer case families - #2434

Merged
schlessera merged 6 commits into
mainfrom
as/split-navigation-browser-tests
Oct 22, 2026
Merged

schlessera merged 6 commits into
mainfrom
as/split-navigation-browser-tests

Conversation

@schlessera

@schlessera schlessera commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Refs #2417; part of #1849.

What changed

The navigation reach matrix schedules its seven existing declaration families as separate files. An eighth wrapper retains every imported durable Actions case once per rail pointer project. Shared scenes retain their original hooks, abort checks and disposal. This continuation merges current main, retains the delivered Storage and diagram-scene checks, and freezes positive audit fixtures at independently delivered main 419f3a51b5017a4705e6fe4dba9982b6fc8de3bc. Production audit pins, guards and qualification are unchanged.

Why this shape

The split follows the existing case boundaries and preserves every width, start, target, theme, pointer, assertion, deadline and capture identifier. Rail discovery uses the new leaf glob with the existing project scheduling bounds. The durable wrapper preserves suite-before-fixture import order and both cleanup layers. Test fixtures read raw Git blobs and frozen directory membership; candidate bytes have separate refusal controls so this changed configuration cannot qualify by recomputing metadata.

No changeset is needed: only tests and their documentation change. No supported contract or provider-facing history changes. The decision record now cites the fixture owner and actual current-source controls, and correctly describes refresh admission across every browser shard.

Proof

  • Current head: 49cb2970de26574d640fdb3b54fba7637bfcca37; merged base: 7b8a755ea329bd48a11b790e916c417b6f608eee. Merge commit 35c5c5cf00cc07c5582adb93c1cc056cc4f21915 preserves parents 7d6fd28573d4ca97e4e79b52fdb8f3c2dbb16a13 and that base.
  • Source equivalence against the merged main: all 62 non-import/export navigation statements and all 42 complete assertion expressions match exactly, retaining complete parameter loops, helpers and hooks. The durable suite retains all 139 assertion sites. The current-main assertion-to-file map is below.
  • Installed Vitest discovery: 24 unique instances, eight files × rail-fine, rail-coarse and rail-mixed; the shared fixture is excluded. Whole-repository proof inventory passes (1,537 execution instances); all 24 new navigation weights remain explicitly unmeasured and discovered.
  • Recovered focused audit tests after restoration: 40 pass / 0 fail / 210 assertions across bound-browser-documents, browser-command-activation and browser-worker-audit. This includes all main's scene-producer refusal controls.
  • Mutation: bypass the document configuration digest check; all four current document sources retain only their reviewed binding cases fail at CURRENT_DOCUMENT_SOURCE_DRIFT_REQUIRES_FRESH_PROOF (expected false, received true). Restore the exact bytes; focused suite passes.
  • Mutation: replace the independent positive-fixture owner with this PR's split head; the same four cases fail at FROZEN_DOCUMENT_CONTROL_QUALIFIES (expected true, received false). Restore the exact owner bytes; focused suite passes. These are assertion failures, not setup or module-load failures.
  • Fresh omission controls: narrowing discovery to the counts leaf fails actual installed inventory with Undiscovered browser scenario: packages/ui-react/tests/browser/navigation-reach.desktop.pointer.tsx; deleting Sessions once fails the independent ORIGINAL_NAVIGATION_STATEMENTS_RETAINED assertion. Both restore byte for byte; current source equivalence and complete installed discovery pass.
  • Recovered workspace build passes; fresh strict TypeScript, lint and the combined audit/citation suite pass (84 tests / 323 assertions). Lint reports existing hook warnings without failing any gate.
  • Recovered real pinned browser execution on this exact head exits 0: 24/24 file/project instances, 2,151/2,151 cases passed, no skipped/failed cases or unhandled errors, 360.16 s Vitest wall time. Independent installed discovery, selected/collected/reported case identities, and checkout/tree/parents reconcile through scripts/proof-case-report.mjs --check. Every local file/project elapsed time is below 250 s; maximum 177.180 s. Runtime: Bun 1.4.2, Vitest 4.1.11, Playwright 1.63.0; unchanged image mcr.microsoft.com/playwright@sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27. Shared native lock, existing runner guards, default sequential files per project and original deadlines remain enabled. This is local proof on tree 9965372add6ccd9b9b8a946009d0b43580de7bd5, not hosted candidate confirmation.
  • bun run check:pr --base origin/main exits 0 on this final head: 970 fast tests / 6,439 assertions plus 40 affected import-feedback tests / 210 assertions, zero failures. The fresh run started with 94 mountinfo entries and retained the sandbox setup prerequisite.
  • Cheap draft gates are distinct from complete candidate confirmation; their exact-head result will be recorded in the coordinator handoff.

Local file elapsed seconds (observations on this head; no hosted shard/job-wall or controlled speedup claim):

Leaf family Fine Coarse Mixed
counts 0.208 0.228 0.263
desktop 156.875 176.502 177.180
durable-actions 34.516 33.846 33.988
handoff 6.957 8.112 8.225
inventory 4.073 4.596 4.559
keyboard 38.819 39.308 39.436
parity 69.757 78.781 78.144
targets 5.936 6.166 6.081

Case-family mapping

All paths are under packages/ui-react/tests/browser/; each family executes in every unchanged rail pointer project. Complete assertion expressions are unchanged, including helper assertions and the existing dynamic parameter expansion.

Family Split file Cases per pointer
Matrix count completeness navigation-reach.counts.pointer.tsx 1
Inventory and phone palette guard navigation-reach.inventory.pointer.tsx 14
Desktop reach matrix navigation-reach.desktop.pointer.tsx 429
Dedicated route / palette parity navigation-reach.parity.pointer.tsx 84
Conditional backend handoff navigation-reach.handoff.pointer.tsx 7
Palette hit targets / pointer density navigation-reach.targets.pointer.tsx 10
Keyboard reach and focus navigation-reach.keyboard.pointer.tsx 60
Unchanged durable Actions suite navigation-reach.durable-actions.pointer.tsx 112

The direct families contribute 605 cases per pointer and the durable suite 112; the complete inventory is 2,151 cases. navigation-reach-fixture.tsx owns the shared scene and helper assertions. Historical wait-evidence locations retain their original SHA; the map below uses merged main's original navigation-reach.pointer.tsx and the current split locations.

Exact assertion mapping

Current main original line Split file / line Unchanged assertion
116 navigation-reach-fixture.tsx:114 expect(matchMedia("(any-pointer: coarse)").matches, "coarse media premise").toBe(mode !== "fine")
117 navigation-reach-fixture.tsx:115 expect(matchMedia("(any-pointer: fine)").matches, "fine media premise").toBe(mode !== "coarse")
118 navigation-reach-fixture.tsx:116 expect(matchMedia("(prefers-reduced-motion: reduce)").matches, "reduced motion premise").toBe(true)
225 navigation-reach-fixture.tsx:223 expect(name, `a named control: ${el.outerHTML.slice(0, 80)}`).not.toBe("")
228 navigation-reach-fixture.tsx:226 expect(r.height, `44px target height: ${name}`).toBeGreaterThanOrEqual(43.5)
229 navigation-reach-fixture.tsx:227 expect(r.width, `44px target width: ${name}`).toBeGreaterThanOrEqual(43.5)
233 navigation-reach-fixture.tsx:231 expect(el.contains(hit), `nothing covers ${name} at ${point.x},${point.y}: ${hit?.outerHTML.slice(0, 120)}`).toBe(true)
415 navigation-reach-fixture.tsx:413 expect.poll(() => (el = step.find(s)) !== null && !moving(el), { interval: 16, message: `${step.name} on screen and at rest, toward ${toward}` }).toBe(true)
424 navigation-reach.counts.pointer.tsx:6 expect(Number.isInteger(allowed(name, start, width)), `${name} from ${start} at ${width}`).toBe(true)
426 navigation-reach.counts.pointer.tsx:8 expect(new Set(PALETTE_ROWS).size, "one target per palette row").toBe(PALETTE_ROWS.length)
437 navigation-reach.inventory.pointer.tsx:12 expect(ui$(s).paletteOpen, "phone guard clears programmatic opening").toBe(false)
438 navigation-reach.inventory.pointer.tsx:13 expect(s.host.querySelector('[data-palette]'), "no hidden modal below 480").toBeNull()
442 navigation-reach.inventory.pointer.tsx:17 expect([...rows].sort(), `the palette at ${width} lists the routed commands`).toEqual([...PALETTE_ROWS].sort())
443 navigation-reach.inventory.pointer.tsx:18 expect(rows.filter((r) => r === "Sessions"), "Sessions once").toHaveLength(1)
455 navigation-reach.desktop.pointer.tsx:12 expect.poll(() => target.reached(s), { message: `${name} from ${start} at ${width} (${mode}) after ${steps.length}` }).toBe(true)
456 navigation-reach.desktop.pointer.tsx:13 expect.poll(() => SURFACE[name]!(s), { message: `${name} is drawn, not only flagged, from ${start} at ${width}` }).toBe(true)
457 navigation-reach.desktop.pointer.tsx:14 expect(steps.length, `activations to ${name} from ${start} at ${width} (D52 §2)`).toBe(allowed(name, start, width))
462 navigation-reach.desktop.pointer.tsx:19 expect.poll(() => s.writes, { message: `${name} from ${start}: requests that write` }).toEqual(job)
463 navigation-reach.desktop.pointer.tsx:20 expect(document.documentElement.scrollWidth, "no horizontal overflow").toBeLessThanOrEqual(width)
490 navigation-reach.parity.pointer.tsx:27 expect.poll(() => target.reached(s), { message: `${name} by the palette row` }).toBe(true)
500 navigation-reach.parity.pointer.tsx:37 expect.poll(() => target.reached(s), { message: `${name} by its route` }).toBe(true)
504 navigation-reach.parity.pointer.tsx:41 expect({ ...routed, paneFocused: name === "Sessions" ? routed.paneFocused : null }, `${name}: route and palette agree`) .toEqual({ ...reference, paneFocused: name === "Sessions" ? reference.paneFocused : null })
594 navigation-reach.handoff.pointer.tsx:14 expect([...paletteRows(s)].sort(), "the palette lists the routed commands and the handoff").toEqual([...PALETTE_ROWS, HANDOFF].sort())
598 navigation-reach.handoff.pointer.tsx:18 expect.poll(() => handoffOpen(s), { message: `${HANDOFF} by the palette row` }).toBe(ITHACA.id)
604 navigation-reach.handoff.pointer.tsx:24 expect(reference.review, "the palette row opened a review").toBe(ITHACA.id)
609 navigation-reach.handoff.pointer.tsx:29 expect.poll(() => handoffOpen(s), { message: `${HANDOFF} by the row's overflow` }).toBe(ITHACA.id)
613 navigation-reach.handoff.pointer.tsx:33 expect({ ...routed, panels: routed.panels.filter((p) => p !== "sessionPanelOpen"), paneFocused: null }, `${HANDOFF}: the overflow and the palette agree`).toEqual({ ...reference, panels: reference.panels.filter((p) => p !== "sessionPanelOpen"), paneFocused: null })
632 navigation-reach.targets.pointer.tsx:18 expect(rows.length, "the palette lists its rows").toBe(PALETTE_ROWS.length)
641 navigation-reach.targets.pointer.tsx:27 expect(row.contains(hit), `the row's own box takes a press at ${x},${y}: ${name} hit ${hit?.outerHTML.slice(0, 120)}`).toBe(true)
644 navigation-reach.targets.pointer.tsx:30 expect(Math.round(r.height * 10) / 10, `fine-pointer density: ${name}`).toBe(/sync|spends/.test(name) ? 35.7 : 34)
646 navigation-reach.targets.pointer.tsx:32 expect(r.height, `44px target height: ${name}`).toBeGreaterThanOrEqual(43.5)
647 navigation-reach.targets.pointer.tsx:33 expect(r.width, `44px target width: ${name}`).toBeGreaterThanOrEqual(43.5)
669 navigation-reach.keyboard.pointer.tsx:21 expect(document.activeElement, "Tab reaches All commands").toBe(all)
673 navigation-reach.keyboard.pointer.tsx:25 expect(dialog(), "Enter opens the palette").not.toBeNull()
674 navigation-reach.keyboard.pointer.tsx:26 expect(document.activeElement, "focus enters the query").toBe(dialog()!.querySelector("input"))
677 navigation-reach.keyboard.pointer.tsx:29 expect(dialog()).toBeNull()
678 navigation-reach.keyboard.pointer.tsx:30 expect(document.activeElement, "Esc returns focus to All commands").toBe(all)
683 navigation-reach.keyboard.pointer.tsx:35 expect(index, `${target.palette} is listed`).toBeGreaterThanOrEqual(0)
686 navigation-reach.keyboard.pointer.tsx:38 expect((document.activeElement?.textContent ?? "").startsWith(target.palette!), `arrows reach ${target.palette}`).toBe(true)
689 navigation-reach.keyboard.pointer.tsx:41 expect.poll(() => target.reached(s), { message: `${name} by keyboard` }).toBe(true)
690 navigation-reach.keyboard.pointer.tsx:42 expect.poll(() => SURFACE[name]!(s), { message: `${name} is drawn after the keyboard route` }).toBe(true)
691 navigation-reach.keyboard.pointer.tsx:43 expect(dialog(), "running a row closes the palette").toBeNull()

Checklist

  • Focused local preflight/behavioral receipts and complete selected hosted proof passed; complete hosted candidate proof remains coordinator-owned.
  • Acceptance gaps are named below.
  • The PR and issue retain release milestone 0.44.0; both read back during this continuation.
  • No changeset needed: this changes nothing a package consumer can see.
  • Leakage gate is clean; no personal data in the diff.
  • No supported machine surface changed; no CONTRACT: commit.
  • Decision documentation reflects frozen fixture ownership and current shard admission.
  • Nothing on a provider-facing turn path changed.

Anything left open

The coordinator owns complete candidate confirmation and merge. This PR remains draft; no ready transition, integration reservation, confirmation or merge is requested by this continuation.

The shard weights are unchanged. The established scripts/refresh-browser-costs.ts requires a successful overall attributed CI run with all three fresh browser jobs and complete checkout/image/spec timing evidence. Historical run 39217736277 failed overall and remains inadmissible, although its 24 navigation instances / 2,151 cases passed and its maximum file cost was 186.961 seconds. Successful cheap draft gates cannot supply browser measurements. After the coordinator obtains a successful full run, refresh through the existing tool, record every new file/project below 250 seconds plus per-shard whole-job durations, and confirm the final weight-bearing head. The maintainer's 2026-10-22 ruling dropped the #2350 edge; the issue has no remaining declared blocker. Contributor-guide drift discovered during this work is filed separately as #2550.

@schlessera schlessera added this to the 0.44.0 milestone Oct 19, 2026
@schlessera schlessera added type: test Coverage, harness or proof work with no behaviour change. area: ui-react React chat/files/voice components, stores, WebSocket transport. area: ci CI workflows, the gates they run, release scripts, packaging. labels Oct 19, 2026
@schlessera
schlessera marked this pull request as ready for review October 19, 2026 07:42
@schlessera
schlessera marked this pull request as draft October 19, 2026 08:00
@schlessera

Copy link
Copy Markdown
Owner Author

2026-10-19 — #2417 continuation r2, under the parent's existing claim e1849-2417-20261019-r1.

The nine relevant unit failures are repaired in 86457357cc94d5917c98aa49f6941f3c2158eab8. Positive browser-document, inactive-command and worker-boundary fixtures now read independently owned raw Git blobs from delivered base 90a95123cfceb169bd2ecf7c213544db742eaed7; document directory membership and binary fonts are frozen too. Actual current config/caller/producer bytes are tested separately. Production qualification hashes, audit implementations, offline guards, images, deadlines and navigation cases are unchanged. This follows delivered #2374/#2388 rather than granting qualification to changed source.

Focused evidence: the original three files reproduce exactly 24 pass / 9 fail. Repaired tests pass 38/38, 181 assertions, with all original assertions retained. Bypassing the document config check fails all four current-document negatives; bypassing worker enforcement fails the real current-config negative even after recomputing the manifest; bypassing the command digest fails its drift guard, and admitting just the actual changed config fails CURRENT_COMMAND_SOURCE_DRIFT_REQUIRES_FRESH_PROOF. Changing the positive fixture owner to the PR's unreviewed config fails the original and added positive assertions. Every mutation is restored byte-for-byte. Initial strict types caught a readonly test.each input; copying that list resolves it. Final strict types pass (31.79 s wall, 49.54 s accounted CPU); required bun run check:pr --base origin/main passes 719 fast tests / 4,622 assertions plus 38 affected import-feedback tests / 181 assertions (64.69 s wall, 91.17 s accounted CPU); focused execution is explicit because the initial split preflight did not select these tests. No failing setup is represented as behavioral evidence.

Source equivalence is rechecked: all 62 direct top-level statements / 42 assertion sites and all 43 imported durable-suite statements / 138 assertion sites remain exact. Fresh private empty-cache frozen copyfile dependencies match qualified identity 0c2758c046f2b69d5f33b66521baf3098db5f44256b73ec96961c98d381e6245 (843 packages, 59,516 files, 1,833,832,361 bytes).

Initial hosted measurement: run 39217736277 attempt 1 failed overall. Its three browser jobs succeeded. Their actual checkout logs, case/resource artifacts and immutable Git API agree on synthetic 4e2448ea8ab6402f64413e1080738eb09fd27b8e, tree 07874b2132e08cde15e0e0b8d743f483a1f59fba, parents base 90a95123cfceb169bd2ecf7c213544db742eaed7 and original split head 17766e9a065e1e8dfb58c33c36af7f27991ed77e. This is evidence for the original split, not new hosted proof of the repair head.

Downloaded immutable browser artifacts have verified ZIP SHA-256:

All 330 discovered browser file/project instances reconcile exactly once across the three shards. All 24 navigation instances and 2,151 cases pass, with case names matching the prior complete local receipt, zero navigation skips/failures and zero unhandled errors. The complete browser domain reports 9,056 passed and 10 skipped cases outside navigation; those skips are not hidden in the navigation count. Every navigation file/project is below 250 seconds, maximum 186.961 seconds. The table records logged file elapsed time, not summed case-body time; every entry has passed status.

File suffix Cases per pointer Fine s Coarse s Mixed s
counts.pointer.tsx 1 0.174 0.185 0.183
desktop.pointer.tsx 429 163.335 182.984 186.961
durable-actions.pointer.tsx 112 33.996 33.64 34.917
handoff.pointer.tsx 7 7.442 8.335 8.321
inventory.pointer.tsx 14 4.33 4.406 4.624
keyboard.pointer.tsx 60 42.068 41.387 41.425
parity.pointer.tsx 84 74.917 83.702 85.133
targets.pointer.tsx 10 5.929 6.309 6.24
Browser shard Whole job s Build s Browser command s VM active CPU s Sampled peak used bytes
1 881 106.1 729.183 1879.57 11303219200
2 416 105.647 264.918 698.07 6673592320
3 898 106.799 745.892 1833.37 11814854656

Browser job IDs are 117945823735, 117945823953 and 117945823662. All used the unchanged pinned image mcr.microsoft.com/playwright@sha256:eff16c30e6f3f4af0a03fa4b706120d5e9b0891c344a27d64559aff5900a4a27, with four logical CPUs and approximately 16.77 GB VM memory. VM active CPU and sampled used memory cover proof commands including containers; they are not process CPU or exact peak memory. Whole-job times include setup/finalization; build/browser phases overlap that wall interval and are not extra costs.

Historical scheduling evidence at main 7f22bb6ac2892360f3a5c4d3a1f93d9997af43e8, run 39109891338, recorded the original single navigation file at approximately 481/411/428 seconds (fine/coarse/mixed). The split's largest files are 163.335/182.984/186.961 seconds respectively; summed navigation file time is 1,060.943 seconds versus about 1,320 historical seconds. These different-source observations establish smaller measured scheduling units, not a controlled speedup. Historical browser job walls were 808/887 seconds across two shards (1,695 total); this initial three-shard run is 881/416/898 (2,195 total). No whole-browser job-wall improvement is observed or claimed; the unmeasured new files still use positive default weights.

The established scripts/refresh-browser-costs.ts admission requires a successful overall CI run, not merely successful browser jobs. Executing it against this run refuses with A successful attributed CI run/attempt is required. Its checks and the existing weights remain unchanged. The issue's successful-run weight criterion remains pending even though this initial measurement meets the numeric per-file threshold.

PR #2434 stays draft and uses Refs #2417. Native mount-inspector blocker #2350 remains unresolved; no native code was changed, no expensive confirmation/ready event was requested, and no merge is claimed. Remaining: resolve that blocker, obtain successful complete candidate proof, refresh weights through the established tool, then qualify the final refreshed source. The initial base remains unchanged; no rebase or main integration was performed. The parent retains the assignment and claim, and owns the next hosted decision and final handoff. No competing claim or unassignment is introduced.

@schlessera

Copy link
Copy Markdown
Owner Author

2026-10-20 source-only handoff: preserved candidate fix/2417-navigation-source-r3, head 7d6fd28573d4ca97e4e79b52fdb8f3c2dbb16a13, tree 0f2ed147f624f9ab17cb99aece68b5c745aca8ae. History-preserving merge e75f113bd242193cb1349af5f3dba168017527f1 has ordered parents prior PR head 86457357cc94d5917c98aa49f6941f3c2158eab8 and inspected main 468618cf106c3e793cbb030f8fc90bf8d018913f. The actual merge had no conflicts despite the earlier API conflict indication.

Main's Storage row and browser command registration are retained. Positive fixtures now read the independently delivered Storage owner caae12da2e678dd4720bf112e93ef21812cfdc18, matching main's already-delivered audit inputs; no production pin was recomputed. Parent source review independently confirms nine literal navigation blocks, all 42 direct assertion sites, unchanged leaves and current-source refusal controls. The durable suite retains 138 direct expect calls plus one expect.element call (139 total); the old 138 count omitted the latter, without an assertion change. Scripts, workflows, manifest, lockfile, weights and production audit/guard files match inspected main.

No install, build, tests, runtime discovery, types, preflight or hosted proof ran in this source allocation. Parent reviewed and pushed only the separate preservation branch after the child finished; the existing #2434 branch and draft head remain unchanged. No new PR, qualification or current-tree timing claim is made. Historical 2,151-case/24-instance results and 186.961-second maximum retain their original failed-overall-run identity.

#2350 remains the canonical unresolved prerequisite. Resume by reclaiming this preserved candidate, assessing live source changes, obtaining focused positive/refusal/mutation and actual browser inventory proof plus required preflight, then complete selected confirmation after the prerequisite is resolved. Weight refresh still requires an admitted successful overall run, followed by final weight-bearing candidate and main proof. No guard relaxation or unchanged failed-run retry is authorized.

Claim e1849-2417-20261020-r3-source is complete and released; the parent is removing only its own assignment. #2417 remains open/blocked and #2434 remains draft, both milestone 0.44.0. No integration reservation was acquired. The clean prepared worktree and indexed source receipts are retained for resumption.

@schlessera
schlessera marked this pull request as ready for review October 22, 2026 09:38
@schlessera
schlessera merged commit 9af45a8 into main Oct 22, 2026
23 of 25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI workflows, the gates they run, release scripts, packaging. area: ui-react React chat/files/voice components, stores, WebSocket transport. type: test Coverage, harness or proof work with no behaviour change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant