Skip to content

perf(ios): speed up deep snapshots and keep first taps reliable - #2414

Merged
thymikee merged 6 commits into
mainfrom
fix/ios-ax-depth-recovery
Sep 9, 2026
Merged

perf(ios): speed up deep snapshots and keep first taps reliable#2414
thymikee merged 6 commits into
mainfrom
fix/ios-ax-depth-recovery

Conversation

@thymikee

@thymikee thymikee commented Sep 9, 2026

Copy link
Copy Markdown
Member

Summary

Recover rejected deep iOS snapshots with bounded lower-depth requests and complete withheld branches. Preserve zero-based depth limits, reuse unchanged native trees, and fall back with non-launch failure codes when recovery cannot finish.

Contain optional coordinate-tap probe issues without penalizing later taps or granting an invalid typing witness. Required queries and mutation failures remain visible.

26 files across Apple capture, runner, tests and packaging/CI enforcement. No app-specific logic or public API change. Size comparison uses the measured revision's asset policy.

Validation

Tested head: 7c84acfe684fbb45191460766ac8e9f6d739aa95.

  • pnpm check:affected --run passed.
  • Rebased onto perf(apple): gate the launch-observation probe on the snapshot circuit breaker #2391; Capture/launch/circuit tests passed, including 31 compiled native cases. Planted failures prove recovery and non-retry classification.
  • Before the rebase, eight native iOS tests and iOS/macOS builds passed; native sources are unchanged. Immediate tap-then-type recovery is covered.
  • Live Settings depths 0/1/4/64 and instrumented Bluesky frontiers verified. Missing/invalid boundary evidence fails closed. Independent review clear; follow-up perf(ios): align AX recovery contracts and evaluate generation-scoped depth hints #2424.
  • Earlier benchmark at 8e402a0ac4: warm startup to a verified Bluesky post averaged 11.14s vs 16.13s on 0.21, two warm samples each. This fixture-specific benchmark has not been repeated after review adjustments.
  • Updated GitHub CI pending.

@thymikee thymikee left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single-pass review at high effort (the Agent tool was unavailable in this session, so this is one reviewer working through all angles in one context rather than the usual multi-agent fan-out plus subagent verification). Seven inline findings, most severe first: the materializer's depth bound is one level stricter than nodeFromSnapshot and the previous release (the adapter.ts threshold shift is the tell); continuation-budget exhaustion discards a valid partial tree; capture-internal errors are mapped to application-server-unavailable, which launch observation re-polls for 5 s; a single contained probe issue penalizes the XCTest channel for 120 s and disables tap-then-type; the retry keys on the generic kAXErrorIllegalArgument; and one efficiency note on the per-node mutableCopy. No CLAUDE.md governs these paths. Let me know if any scenario doesn't reproduce and I'll retract it.


Generated by Claude Code

Comment thread apple/snapshot-bridge/SnapshotBridgeCapture.m Outdated
Comment thread apple/snapshot-bridge/SnapshotBridgeCapture.m
Comment thread apple/snapshot-bridge/SnapshotBridgeCapture.m
Comment thread packages/platform-apple/src/snapshot-source/adapter.ts Outdated
Comment thread apple/snapshot-bridge/SnapshotBridgeCapture.m Outdated
Comment thread apple/snapshot-bridge/SnapshotBridgeRuntime.m
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.51 MB 4.52 MB +10.9 kB
Package (unpacked) 4.51 MB 4.52 MB +10.9 kB
Package (download) 1.34 MB 1.34 MB +2.4 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 27.8 ms 27.7 ms -0.1 ms
CLI --help 76.8 ms 77.4 ms +0.6 ms

@thymikee

thymikee commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

The depth, continuation-error and packaging fixes look correct at dde65f3, and checks are green. Before merging, please itemize the +10.1 kB unpacked growth and explain why the smaller alternatives would not retain the recovery guarantees. The new capture module accounts for about 5.9 kB; the remaining growth needs accounting. Keep the Bluesky timing claim tied to the earlier revision unless it is repeated on this head.

@thymikee
thymikee force-pushed the fix/ios-ax-depth-recovery branch from dde65f3 to 7966e9d Compare September 9, 2026 12:03
@thymikee

thymikee commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Addressed using the exact CI artifact from Size run 34336292457, measured at dde65f3e66:

Packaged file Unpacked delta
apple/snapshot-bridge/SnapshotBridgeCapture.m +5,395 B
apple/snapshot-bridge/SnapshotBridgeCapture.h +513 B
apple/snapshot-bridge/SnapshotBridgeRuntime.m +1,229 B
Runner RunnerTests+TextInputProbe.swift +3,123 B
Runner RunnerTests+Interaction.swift (moved query code removed) −1,253 B
Runner RunnerTests.swift +102 B
Runner RunnerTests+CommandExecution.swift +13 B
apple/snapshot-bridge/README.md +865 B
dist/src/adapter.js (native source/compile lists) +78 B
Total +10,065 B

That is 0.223% unpacked growth and +2,230 B compressed. The new regression-test files are not packaged. Probe logic costs 1,985 B net after accounting for the moved code.

An independent design review found no smaller equivalent owning fix:

  • A shallow cap loses requested content. Bounded continuation retains it or explicitly falls back.
  • Folding recovery into serialization still needs the traversal and safeguards, while mixing acquisition policy with wire conversion. Unchanged native trees already retain identity.
  • Skipping field probing breaks tap-then-type. Catching exceptions misses XCTest recorded issues. Broad suppression would hide required failures; the local, thread-bound scope contains only the optional lookup. The expected-failure API was tested and rejected because it could end the long-lived runner test.

The merged #2391 completes the failure path: #2414 recovers acquisition first, and gives unrecoverable failures non-launch codes; after capture opens the existing generation circuit, #2391 makes later launch observation honor it. A relaunch re-enables the bridge through the existing generation owner. No second circuit or cooldown is introduced. #2391's existing transient-failure settle tradeoff is unchanged.

Rebased onto #2391 and added composition tests for both recovery failure codes. 49 focused tests pass; treating these failures as launch transitions produces two planted-red failures. The rebased full affected gates passed before publication.

The Bluesky 11.14s vs16.13s result remains attributed to 8e402a0ac4; it was not repeated on the review-adjusted head. My recommendation is to merge once the new head's CI is green: this repairs our acquisition/error-ownership mechanisms while adapting to an AX limitation we cannot repair inside Apple.

@thymikee

thymikee commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

Reconciled the latest review in 7c84acfe68 and opened follow-up #2424.

The dictionary keys are now proven on real capped Bluesky nodes. A temporary instrumented copy of the native bridge, using the final production recovery code, produced this sequence on iOS 26.2:

request 1: native depth 65 -> rejected (code 5)
request 2: native depth 32 -> success
frontier: ChildrenCount=1, Children=[]; Element=__NSCFType
request 3: re-root at that live Element, depth 32 -> success
two further frontiers: ChildrenCount=1, Children=[]; Element=__NSCFType
requests 4 and 5: re-root, depth 3 -> success

The final traversal-depth-64 capture retained 227 nodes, including “Mochi napping in a sunbeam” at depth57, with no truncation residue. The deliberately depth48 capture retained136 nodes and correctly disclosed depth truncation. A repeated full capture was79ms; this is a capture receipt, not a new startup benchmark. Full recovery should end complete, so requiring final truncated:true would assert the wrong result. Instrumentation is outside the repository and is not shipped.

Live support alone was insufficient. Missing child-count evidence could previously look like a leaf. The fix tracks each native fragment's remaining levels: an unknown boundary with requested depth remaining now fails with the existing non-launch malformed-tree code; an unknown boundary at the requested cap conservatively reports depth truncation. Fractional, negative and non-finite counts cannot prove terminal nodes. Natural leaves above a native boundary remain unaffected.

31 compiled native cases pass; seven fail against the published implementation. Final affected gates pass, and adversarial review found no remaining blockers. The native runner source is unchanged in this correction.

Follow-up: #2424 scopes shared recovery conformance and measured generation-scoped depth hints. Default host acquisition starts at65 native levels, not129. Also, the process is reused per simulator, not per generation: hints must use the existing target/generation identity. A shared engine is not mandated because representations and policies differ. The route remains the sole circuit owner from #2391.

The +10,065B unpacked accounting at dde65f3e66 was answered in the earlier size reply. This correction adds701B of native source and178B of README; tests remain unpackaged. Updated CI size evidence will report the final package delta. The earlier Bluesky startup claim remains tied to 8e402a0ac4.

@thymikee

thymikee commented Sep 9, 2026

Copy link
Copy Markdown
Member Author

The recovery correction looks good at 7c84acf. The reported live frontier evidence, fail-closed regressions and package-growth accounting address the remaining gaps. Ready for human review. The iOS failure is likely unrelated: the unchanged runner-cache SDK probe timed out after five seconds, as tracked in #2422. The earlier startup benchmark remains specific to its measured revision.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 9, 2026
@thymikee
thymikee added this pull request to stack #2426 September 9, 2026 13:56
@thymikee
thymikee merged commit 0dfd65f into main Sep 9, 2026
18 of 19 checks passed
@thymikee
thymikee deleted the fix/ios-ax-depth-recovery branch September 9, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant