Skip to content

fix(ios): preserve regular snapshot depth through structural wrappers - #1947

Merged
thymikee merged 13 commits into
mainfrom
fix/ios-regular-visible-depth-frontier
Aug 22, 2026
Merged

fix(ios): preserve regular snapshot depth through structural wrappers#1947
thymikee merged 13 commits into
mainfrom
fix/ios-regular-visible-depth-frontier

Conversation

@thymikee

@thymikee thymikee commented Aug 21, 2026

Copy link
Copy Markdown
Member

Summary

Implements the ADR 0004 regular-snapshot visible-depth frontier for #1797. This PR does not claim to close #1797.

  • Keeps raw traversal depth as the acquisition bound while regular --depth is enforced against the presented tree. A visible raw-deep child can therefore remain in snapshot --depth 1 when presentation collapses structural ancestors.
  • Reuses the existing SnapshotVisibilityFold transition instead of adding arbitrary acquisition depth, node caps, or backend-specific exceptions. Raw projection and backend capability declarations remain unchanged.
  • Preserves the presentation failure contract through the existing typed snapshot-quality reason and warning path.
  • Adds focused XCTest coverage plus a fixture-backed public CLI scenario. XCTest owns the clipped-structural-parent invariant; the live scenario proves that regular depth 1 presents a raw-deep child at depth 1 while raw depth 1 still omits it.
  • Scope is 27 files across the iOS runner/tests, existing TypeScript snapshot capability contract, ADR/guidance, XCTest workflow selection, and the fixture/live scenario. It does not expand into another platform family or command family.

Validation

  • Exact published head: 0b0a029c90fb6aba31c32009ab4783cf99333d9f, based on cb65d6ca1f18683c7e9cb60e6e454bb974d23154.
  • Test-first evidence: the focused XCTest regression was observed red before the visibility-aware frontier existed and green after the production recursive-tree wiring.
  • pnpm check:affected --run passed every locally runnable check on the published head, including formatting, lint, typecheck, layering, fallow, package verification, 2,806 related tests, XCTest selection, and the gate/fixture models. The focused iOS smoke coverage contract also passed 14/14.
  • The prior exact-head iOS smoke failure was diagnosed from its raw payload: React Native/XCTest exposed the visual wrapper and child as AX siblings, invalidating the scenario's ancestry assertion. The fixture and scenario now test only the public depth contract; no production behavior was changed to reconstruct visual ancestry.
  • Exact-head native/device lanes remain GitHub-authoritative and are running.
  • Latest size evidence before this test-only follow-up: npm unpacked +8.4 kB (+8.3 kB Apple runner source/project, +111 B JavaScript), npm tarball +1.9 kB, JavaScript gzip +48 B. The shared-fold design is the smallest owning-interface change considered.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 2.36 MB 2.36 MB +111 B
JS gzip 792.0 kB 792.0 kB +46 B
npm tarball 913.3 kB 915.3 kB +2.0 kB
npm unpacked 3.16 MB 3.17 MB +8.4 kB

npm unpacked components

Component Base Current Diff
JS / dist source 2.51 MB 2.51 MB +111 B
Apple runner source/project 553.4 kB 561.6 kB +8.3 kB
macOS helper source 54.5 kB 54.5 kB 0 B
Android helper artifacts 0 B 0 B 0 B
Other package files 44.4 kB 44.4 kB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 24.4 ms 23.6 ms -0.8 ms
CLI --help 66.1 ms 66.0 ms -0.2 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/registry.js +33 B +16 B

Top changed packed files

Packed file Base Current Diff
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentation.swift 10.6 kB 14.1 kB +3.6 kB
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotVisibilityFold.swift 9.8 kB 11.7 kB +1.9 kB
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotBackendCapabilities.swift 1.5 kB 2.5 kB +998 B
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Snapshot.swift 38.2 kB 39.1 kB +864 B
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotCapturePlan.swift 31.1 kB 31.7 kB +650 B
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+SnapshotPresentationModels.swift 3.0 kB 3.3 kB +314 B
dist/src/verdict.js 1.8 kB 1.9 kB +78 B
dist/src/registry.js 153.1 kB 153.1 kB +33 B
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+AXSnapshotFallback.swift 12.6 kB 12.6 kB +24 B
dist/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+PrivateAXPresentation.swift 4.0 kB 4.0 kB +12 B

@thymikee

Copy link
Copy Markdown
Member Author

P1: the new acquisition frontier counts regularPresentedDepth using semantic eligibility before SnapshotVisibilityFold applies visibility and clipping. A labeled or interactive node outside the viewport therefore consumes the requested depth, shouldAcquireChildren stops traversal, and the fold can then remove that node, losing an independently visible descendant that regular presentation would otherwise reparent. The committed wrapper test covers only an in-viewport ineligible wrapper, so it cannot catch this. Drive a fixture with an eligible but clipped parent and a visible independently-projected child; acquisition must continue until the requested visible presented depth is complete, or the frontier must use the same visibility decision as presentation without duplicating that policy. Please also record exact-head live depth evidence and itemize the current +4.6 kB unpacked growth.

@thymikee
thymikee force-pushed the fix/ios-regular-visible-depth-frontier branch from b2d3086 to 9e3686e Compare August 21, 2026 17:30
@thymikee

Copy link
Copy Markdown
Member Author

P1: the visibility-aware implementation resolves the original clipped-parent logic, but the new regression still does not exercise acquisition. It constructs a fully acquired three-node RawAX tree and manually reenacts traversalDecision, regularPresentedDepth, and shouldAcquireChildren; reverting the recursiveTreeSnapshotAcquisition call-site/state propagation in RunnerTests+Snapshot.swift to the old eligibility-only frontier leaves this test green. Please put the frontier transition behind one pure helper used by the production traversal and drive the clipped-parent fixture through that helper, with recorded red-on-pre-fix evidence, or add an exact-path simulator/live regression proving the child is actually acquired.

The test is also absent from the ios.yml only-testing list, while the host lane evaluates platformDefault as plainViewport rather than the iOS cursorProjected policy, so current CI does not cover the changed iOS path. The generic iOS smoke is green but does not exercise clipped-parent snapshot --depth. Please also update the PR body to exact head 9e3686e and 16 files, record exact-head live depth evidence, and itemize the current +7.6 kB npm-unpacked growth with why the shared-fold design is the smallest viable implementation.

@thymikee
thymikee force-pushed the fix/ios-regular-visible-depth-frontier branch from ee334fb to 267f2df Compare August 22, 2026 06:55
@thymikee

Copy link
Copy Markdown
Member Author

P1: the clipped-parent regression now proves the pure helper, but it still does not exercise recursiveTreeSnapshotAcquisition. Reverting that production loop to the old depth-only frontier (or dropping its parentPresentedDepth / parentTraversal propagation) while leaving regularTraversalTransition intact keeps this test green, because it starts from a fully materialized RawAXNode tree. The exact-head iOS job selected and passed it, but the PR body still says the required public snapshot --depth 1 case is pending. Please add an exact production-path regression, preferably a fixture-screen iOS test that invokes regular snapshot --depth 1, and record pre-fix red or live evidence. It must observe root plus the independently projected child at presented depth 1 with the clipped structural parent absent; raw --depth 1 must still omit the raw depth-2 child.

P2: update the PR body size figure from +7.6 kB to the exact-head Size report: +8.4 kB npm unpacked (+8.3 kB Apple runner source/project). The shared-fold rationale is useful; it should accompany the current number.

@thymikee

Copy link
Copy Markdown
Member Author

Re-review at 0bfdf57: the prior production-path P1 is fixed in design. The new public-CLI scenario is non-vacuous: full raw proves the clipped parent/descendant and raw depth >1; regular --depth 1 requires the parent absent and child projected at root depth 1; raw --depth 1 requires the child absent and all nodes bounded to raw depth 1. Reverting the acquisition frontier would fail it. Size evidence is current at +8.4 kB unpacked / +8.3 kB Apple runner with adequate minimality rationale.

Readiness remains pending only on evidence: the exact-head iOS smoke is still running, and the PR body still stamps 5f5b1ee... / says live evidence pending rather than current head 0bfdf57.... Once that fixture-backed iOS smoke passes and the body records the exact-head result, this is clean.

@thymikee
thymikee force-pushed the fix/ios-regular-visible-depth-frontier branch from b43967b to 3a9876c Compare August 22, 2026 10:26
@thymikee

Copy link
Copy Markdown
Member Author

Re-review of exact head 209ab52e6bc06e434778869bdd36488867f7f18a: not ready yet.

  • P1 — restore the regression’s raw ancestry proof. The latest scenario only proves that the clipped-parent and projected-child identifiers both exist somewhere and that the child is deeper than 1. Without proving the clipped parent is on the child’s raw parentIndex chain, an unrelated/de-flattened raw branch could let the old acquisition frontier pass. Walk the child’s raw ancestor chain and require visible-depth-clipped-parent to occur; immediate parenthood is not required.
  • Owner-action CI: lint passed, but format deterministically fails on examples/test-app/src/screens/VisibleDepthScreen.tsx; run the repository formatter and push the result.
  • Refresh the PR body/evidence: it still stamps head 5f5b1ee... / base 320a881..., says 25 files, and describes live evidence as pending; current is 209ab52... on cb65d6c... with 27 PR files.

The failed Android smoke is an unrelated wait_capture_stalled / readableCaptures: 0 infrastructure flake. Exact-head iOS and Coverage are still pending. The production implementation remains clean relative to the prior design review.

@thymikee

Copy link
Copy Markdown
Member Author

Addressed the re-review blockers in 71cd9c32b5567b2a0dc5bd5ead568e94d1770897: the live scenario now walks the raw parentIndex chain and proves the clipped wrapper is an ancestor, the fixture is repository-formatted, and the PR body is stamped with current evidence. pnpm check:affected --run passed all locally runnable gates; current-head CI is running.

@thymikee thymikee added ready-for-human Valid work that needs human implementation, judgment, or maintainer merge and removed ready-for-human Valid work that needs human implementation, judgment, or maintainer merge labels Aug 22, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Follow-up on the iOS smoke failure: the exact-head raw payload showed React Native/XCTest flattening the visual wrapper and child into AX siblings, so the ancestry assertion was invalid. I removed that false assumption and simplified the fixture. Focused XCTest remains the owner of the clipped-parent projection invariant; the public live scenario now proves the actual CLI contract: the child is raw-deep, appears at presented depth 1 in a regular snapshot, and is omitted by raw depth 1. Published as 0b0a029; all locally runnable affected checks pass, and exact-head iOS CI is running.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Aug 22, 2026
@thymikee
thymikee merged commit 7f3e355 into main Aug 22, 2026
29 checks passed
@thymikee
thymikee deleted the fix/ios-regular-visible-depth-frontier branch August 22, 2026 11:53
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-08-22 11:54 UTC

thymikee added a commit that referenced this pull request Aug 22, 2026
…equest-bound-migration-803b60

* origin/main:
  perf(contracts): granularize entry surfaces so hub importers stop evaluating the facade clump (#1969)
  fix(ios): preserve regular snapshot depth through structural wrappers (#1947)
  diagnose(1874): instrument the synthesized commit wait and add a dispatchable stall loop (#1941)
  refactor(tests): replace the test-utils barrel with direct module imports (#1956)
  fix(ios): enforce regular snapshot clip invariant (#1946)
  refactor(daemon): lazy-load platform cleanup helpers in session teardown (#1950)
  perf(typecheck): make the root tsc project incremental (#1957)
  docs: drop stale apps.ts over-budget warning from AGENTS.md (#1954)
  refactor: dedupe containsPoint and rectArea into @agent-device/kernel (#1953)

# Conflicts:
#	packages/platform-android/src/runtime.ts
#	packages/platform-harmonyos/src/runtime.ts
#	packages/platform-linux/src/runtime.ts
#	packages/platform-vega/src/runtime.ts
#	packages/platform-web/src/runtime.ts
#	packages/provider-limrun/src/app-log-runtime.test.ts
#	packages/provider-limrun/src/interaction-operations.ts
#	packages/provider-webdriver/src/platform-runtime.ts
#	src/core/command-descriptor/registry.ts
#	src/core/dispatch.ts
#	src/platforms/apple/plugin.ts
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.

iOS snapshot backends: make interpretation divergence impossible by construction (acquire/present split)

1 participant