Skip to content

feat(test-app): add a Bluesky-depth heavy feed screen - #3884

Open
thymikee wants to merge 2 commits into
mainfrom
perf/heavy-feed-fixture
Open

thymikee wants to merge 2 commits into
mainfrom
perf/heavy-feed-fixture

Conversation

@thymikee

@thymikee thymikee commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Summary

Adds a JavaScript-only Heavy feed screen to the test app (Settings → Open heavy feed, open-heavy-feed). It reproduces the Bluesky 1.136 home feed shape: 30 nested containers, a virtualized list, and composite posts with image, link, quote, and quote-with-media embeds. Every level opts out of view flattening. The native tree is deeper than 65 levels. 6 files, no native change, so CI repacks the cached Release build.

Layer 1 of 3 for the nightly iOS perf suite (#1781 A3 un-park). The suite drives this screen.

Validation

Tested at d17b8ead56 (fixture JS equal to the measured build) on a dedicated iPhone 17 Pro simulator (iOS 27.0, Xcode 27.1) with the cached Release fixture repacked:

  • snapshot --raw: 308 nodes, max depth 64 (65 levels), truncated, served by the simulator AX bridge in ~230 ms.
  • Pinned XCTest tree backend: kAXErrorIllegalArgument, recovered by private AX after ~4.8 s, capped at depth 56 (private-ax/recovered/ax-rejected), 3/3 samples. This matches Bluesky.
  • On this screen, XCTest element queries fail, so longpress, swipe, and in-app back fail (see layer 2).
  • pnpm test-app:typecheck and oxlint pass. Gate receipt: pnpm check:affected --run --head 60cf336129 (stack head, includes this layer): passed, exactCommit: true; FAIL-OPEN full set, every local check passed; native, device, and coverage lanes are GitHub-authoritative..

CI: perf-nightly run 39679264668 (iOS 26.2, hosted M1) reproduced the same shape: raw 305 nodes at depth 64, pinned tree backend recovered by private AX after 5.2 s with ax-rejected.

🤖 Generated with Claude Code

A JavaScript-only route that reproduces a heavy React Native home feed: 30
nested containers above a virtualized list of composite posts with image,
link, quote, and quote-with-media embeds. Its native accessibility tree is
deeper than 65 levels, so XCTest tree capture fails with
kAXErrorIllegalArgument and recovers through private AX, as on Bluesky
1.136. Settings links to it with open-heavy-feed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.52 MB 5.52 MB 0 B
Package (unpacked) 5.52 MB 5.52 MB 0 B
Package (download) 1.67 MB 1.67 MB +1 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 24.2 ms 24.8 ms +0.5 ms
CLI --help 49.4 ms 49.7 ms +0.3 ms

@thymikee

Copy link
Copy Markdown
Member Author

The feed screen looks good, but one copied helper needs to go before merge, and the Apple Smoke Tests job at d17b8ea is still running.

clampInteger in HeavyFeedScreen.tsx is a character-for-character copy of the one in DeepTreeScreen.tsx, and TickerScreen.tsx:74 has a near copy too. Three parsers for fixture route params will drift apart, and the repo reuse rule treats duplicate helpers as blocking. Please keep one clampInteger in a shared test-app module (for example examples/test-app/src/route-params.ts), import it in all three screens, and delete the copies.

Not blocking, and you can take or leave it: the new button in SettingsScreen.tsx grows the Snapshot depth card by about 60pt, so every card below it moves down. The Maestro differential flows tap-retry-if-no-change.yaml and settle-after-tap.yaml tap open-inert-surface right after opening Settings, with no scroll (see #1299), so that button may now sit below the fold. That estimate comes from the styles, not from a device. It would help to confirm on an iPhone-size simulator that open-inert-surface is still hittable without scrolling, or to move the entry so it does not push the cards above it, for example as a deep link only like deep-tree. The conformance-differential CI job is not among this PR's checks.

Checks show the Apple Smoke Tests job still running, and the other checks pass, including the Linux and Android smoke jobs. I did not run the app or a simulator. The depth (more than 65), node counts and XCTest failure claims rest on your reports, and the README says about 360 nodes while you reported 305 and 308. There are no conflicts. Before merge, please share the clampInteger fix and show either that open-inert-surface still works without scrolling or that the Apple Smoke Tests job passes.

…eed card last

Review on #3884: HeavyFeedScreen, DeepTreeScreen and TickerScreen each
carried a copy of clampInteger; they now import it from route-params.ts.
The heavy feed entry moves to its own last Settings card so the cards
the Maestro differential flows tap without scrolling keep their
positions (#1299). The README node count now matches the measured
305-308 raw nodes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thymikee

Copy link
Copy Markdown
Member Author

Addressed in dbab03f:

  • clampInteger: there is now one copy, in examples/test-app/src/route-params.ts. HeavyFeedScreen, DeepTreeScreen and TickerScreen import it, and their copies are deleted. Ticker used Number.isNaN, and the shared helper uses Number.isFinite. They behave the same, because parseInt never returns Infinity.
  • open-inert-surface: open-heavy-feed now sits in its own last Settings card. Every card above it keeps its old position, so the Maestro differential flows' unscrolled tap on open-inert-surface (scrollUntilVisible: agent-device fails to find an element real Maestro finds (layer-3 differential) #1299) sees the same layout as on main. A comment on the card records this constraint. The perf suite in feat(perf): time every iOS command against the fixture app #3885 reaches the button with scroll down --until, so the move doesn't affect it. Apple Smoke Tests also passed at d17b8ea.
  • README: it now says about 300 raw nodes, which matches the measured 305 and 308.

pnpm check:affected --run passes, and so does the test-app tsc.

@thymikee

Copy link
Copy Markdown
Member Author

The Lint failure at dbab03f comes from main: snapshot-route.test.ts is 1003 lines there (cap 1000). The fix is #3890. Once #3890 lands, this PR needs a re-run.

This branch has not been deployed

No deployments
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.

1 participant