Skip to content

ci(replay): prepare hosted readiness-wait decision evidence - #3490

Closed
thymikee wants to merge 2 commits into
mainfrom
t3/readiness-evaluation-3077
Closed

thymikee wants to merge 2 commits into
mainfrom
t3/readiness-evaluation-3077

Conversation

@thymikee

@thymikee thymikee commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Summary

Prepare the hosted readiness-wait decision for #3077. Fourteen files add source/mode/corpus manifests, action attribution, one Android shell invocation, semantic Settings replay checks, and opt-in native diagnostics. Diagnostic-only runs cannot vote. All six cases and existing assertions remain; gross diff is 989 lines.

Intentionally draft. Omit the temporary harness from the eventual decision change.

Validation

Tested PR head: b8ca87bb1fbefca1384e3da76800365fde4b8c46.

  • Install/build, repository-wide format, fresh review and exact-head pnpm check:affected --run passed; 231 related test files passed.
  • All 37 reported checks completed without failures, including Coverage and Integration Tests.
  • Native/shell regressions and restored mutants passed. Normal Android passed full E2E and ordinary six-case replay.
  • Decision evidence: iOS now has five eligible pairs, zero engagements/rescues; wall p50 218800/183480 ms (+19.25%). Android has two eligible pairs and two failed engagements, zero rescues. Global decision unresolved.
  • Separately gated setup-only b94c49e9d preserves measured source/corpus. Disabled passes; original enabled SDK provisioning fails. Its sole replacement passes bounded preparation, then fails semantically: no new eligible pair. Separate shipping stack #3554, #3555, #3560 is ready for review with final-head CI and changed-route live proof. Later unchanged iOS full-fixture geometry assertion fails separately. Private 8527d147 passed review/gates; fresh enabled/disabled sanity pair passes authored query-state outcomes after independent scope adjudication; loading/No Results limitations retained. The completed audit and one scoped infrastructure retry establish 4/5 eligible pairs per platform; pair4 navigation failures remain excluded. No final decision. Diagnostic branch unmerged; PR head unchanged.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.17 MB 5.17 MB +67 B
Package (unpacked) 5.17 MB 5.17 MB +67 B
Package (download) 1.55 MB 1.55 MB +14 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 28.4 ms 27.2 ms -1.2 ms
CLI --help 78.5 ms 78.8 ms +0.3 ms

@thymikee

Copy link
Copy Markdown
Member Author

The code looks sound at 2a72c7e, but the evidence is not there yet. The repaired first pair, enabled run 38248643131 and disabled run 38248646748, has to finish. Each run's artifacts need test/artifacts/readiness-experiment/{android,ios}-summary.json with pathProven=true, all six corpus cases matched, requestFiles non-empty and validForDecision=true. The enabled arm should show readiness.observations > 0 and the disabled arm should show 0. We also need one readiness_wait=normal dispatch of replays-manual.yml that still reaches 'pnpm gate replay-android --retries 2' through the new single-shell Android script.

CI is pending. Both Smoke Tests jobs are queued or in progress, and nothing has failed yet. iOS Smoke samples replay-ios, which runs through the replay-port adapter changed here. The only change on that route is extra data on a debug-level diagnostic, so a failure there would be unlikely to come from this diff.

I did not trace which diagnostics scope gets the dispatch-path interaction_target_readiness lines in a real daemon run. If they land in the outer test session, eventBelongsToCases drops them. The enabled arm's pathProven check would only catch that if gate events are also missing. I also did not run the focused tests or the mutation claims, and I did not check that 'test' accepts --serial and --debug through pnpm gate replay-android. A hosted run will show that.

Not blocking, and you can take or leave these. The collector rebuilds per-action readiness from request-log diagnostics, with about 120 lines of session, path, step and timestamp matching, while the response already carries it via interaction-touch-response.ts:236 and replay_action_stop is written in session-replay-action-runtime.ts. The baselineSource refusals in readiness-experiment.test.ts are asserted with a bare .toThrow(), so any throw passes. Please assert the message for both the changed and the duplicated declaration. evidenceValidity at readiness-experiment.ts:303 requires suitePassed with --retries 0, so a disabled run that fails because the wait is absent gets dropped from the vote. Per-arm pass and fail counts would keep that signal visible. The single-shell change in android-manual.sh now carries BOOT_FINISHED_AT and ANDROID_SERIAL across lines, which is a second fix that no normal-mode dispatch exercises yet. The normal dispatch above would cover it.

Could replay_action_stop gain an optional readiness field, taken from the gate wait or the dispatch response? The collector could then count that field and read JUnit and wall time. That would drop the diagnostic tagging, the request-log scan and the timestamp attribution, and the experiment would no longer need --debug. Could the A/B also run from the draft branch through workflow_dispatch on that ref, with results posted to #3077 and the harness left unmerged or deleted in the keep/drop PR? Then main would not carry a one-off 360-line script, a vitest include and a source-rewriting step.

Before merge, the repaired first pair must finish with validForDecision=true on both platforms, and only then should the other four pairs launch. Please also decide whether per-action readiness moves onto replay_action_stop instead of the tagged debug diagnostic.

@thymikee

Copy link
Copy Markdown
Member Author

The corpus repair at 8a342c2 is in, and the replay corpus now matches what the readiness wait measures. The readiness-wait decision evidence is still missing, and the new tests no longer load on current main.

The earlier request for hosted evidence still stands. At 8a342c2 we need five paired hosted runs, one with readiness_wait=enabled and one with readiness_wait=disabled for each pair. Each run should upload test/artifacts/readiness-experiment/{android,ios}-summary.json with pathProven=true, all six corpus cases matched, requestFiles non-empty and validForDecision=true. The enabled arm must show readiness.observations > 0 and the disabled arm must show 0. Please also dispatch replays-manual.yml once with readiness_wait=normal. Its log should show pnpm gate replay-android --retries 2 running in the single-shell invocation. There are no hosted run artifacts for 8a342c2 yet, and Smoke Tests was still queued.

Coverage fails in scripts/replays/android-manual.test.ts and scripts/replays/readiness-experiment.test.ts with "Cannot find module ../../src/tests/test-utils/tmp-dir.ts". Fallow reports the same two files as unresolved imports. Both are this PR's own new tests. Main moved that helper to @agent-device/test-kit in #3483 (packages/test-kit/src/tmp-dir.ts), after this branch's merge-base. The other Fallow findings (the test-kit clone groups and the session-test-harness unused exports) come from main, not from this diff. I did not re-run the collector tests or the mutants here, because the tests fail to load on merged CI, so the mutant claim is unverified. I also could not check without a live run that the Android Settings search control exposes text="Search Settings" and not content-desc on the hosted emulator image.

Next, please rebase onto main and import mkdtempForTest from @agent-device/test-kit in both scripts/replays/*.test.ts, so Coverage and Fallow can load them. Then collect the five paired hosted runs at the repaired corpus. Those two steps are what must happen before merge.

Not blocking, and fine to take or leave: in test/integration/replays/ios/simulator/03-scroll-discovery.ad:5, scroll down --until 'label=Accessibility' is followed by find text "Accessibility" exists, which mostly repeats what the scroll already checked. The scroll also turns that part of the corpus from fixed steps into a polled loop outside the press/click readiness wait being measured. It would help to note in #3077 that the evidence uses the 8a342c2 corpus and that pre-repair runs are dropped from the comparison.

This review covers 8a342c2. The newer head 30953a7 adds an Android search diagnostic and keeps the old tmp-dir import, so the points above still apply; I will look at the new diagnostic separately.

@thymikee
thymikee force-pushed the t3/readiness-evaluation-3077 branch from 30953a7 to 26c0c31 Compare October 12, 2026 17:02
@thymikee

Copy link
Copy Markdown
Member Author

Android sanity-pair validation at 26c0c317c9f2c677ae735a95f8a22c292dfc3291: enabled run, disabled baseline.

Both uploaded artifacts verify the exact head, all six matching corpus hashes, and the expected source variants: default 2000 ms / SHA 1781fb1dfa42a9ac593b79daf0e391a26f0cead4c1e6a750366f7162c949cb20, versus default 0 / SHA 6bf4620fb2fda33d978b0b0fb476622783463ebcd172ed5843f8708d1d6786fa.

Mode Cases passed Replay time Wall time Engaged waits / rescues
Enabled 5/6 217.273 s 224.057 s 0 / 0
Disabled 5/6 202.493 s 209.195 s 0 / 0

Both fail 04-text-input-keyboard.ad, step 4 / line 8: wait 'role=text-field focused=true' 5000, after the Search click dispatch succeeds. Enabled reports typed wait_deadline_exceeded; disabled reports wait_capture_stalled (no readable capture completed within its budget). Post-failure trees show the Settings homepage. The focus/value assertions, typing, and search screenshots were not reached: the strengthened guard catches the previous false pass.

All four acting click requests completed in each mode. Enabled has four actual readiness events, each polls=1; baseline has none. These incomplete suites provide no attributable rescue or causal disabled acting-target failure, and are excluded from keep/drop and p50 evaluation. No additional pairs dispatched.

@thymikee

Copy link
Copy Markdown
Member Author

iOS readiness evidence checkpoint for head 26c0c317c9f2c677ae735a95f8a22c292dfc3291 after the 45-minute bounded wait:

  • Enabled iOS job passed 6/6. Artifact source hash 1781fb1d…949cb20 matches the exact head’s 2000 ms variant; all six corpus hashes and uploaded replay bytes match. All 47 ordered action stops succeeded, including the focused editable editor and exact value="General" assertions. The uploaded query screenshot visibly shows General with an insertion caret; it shows “No Results,” so a matching Settings result is not claimed.
  • Raw readiness: three observations, all first-poll; zero engagements and zero rescued actions. Measured suite wall time: 170,014 ms; JUnit replay time: 159,447 ms. These are single-run observations, not a speedup claim.
  • Disabled iOS control remained queued at 17:54 UTC with zero executed steps and no iOS artifact. Its source/budget/corpus, semantic checks, readiness and timings remain unvalidated. Paired eligibility is pending external execution; earlier-pair rows were not reused.

@thymikee

Copy link
Copy Markdown
Member Author

Update at 26c0c317c9f2c677ae735a95f8a22c292dfc3291:

  • Rebased onto main and moved all three new test imports to @agent-device/test-kit/tmp-dir. The exact affected gate passed; all 19 PR checks are now green, including Coverage and Integration Tests.
  • Earlier source/corpus rows are excluded or held. The strengthened fresh pair verifies exact source and all six corpus hashes, but Android fails its focused-editor wait in both modes. Enabled iOS passes the focused editor/exact query assertions; the disabled control fails post-click capture. These are incomplete comparisons, with zero attributable rescues; the remaining four pairs are not launched.
  • The requested normal-mode dispatch is now running. Its Android log must prove the single-shell path reaches the ordinary --retries 2 replay gate; no such success is claimed yet.
  • The harness is intentionally running from this unmerged draft branch. It will be omitted from the eventual keep/drop change, preserving only independently needed corpus/normal-lane repairs.

I am retaining the tagged debug diagnostics for this temporary experiment. Successful dispatch responses expose readiness only for repeated polls, and the adapter only attaches its gate evidence to failures; response-only tracing would lose first-poll path proof and successful gate waits. The revised issue explicitly requires --debug, and the attributed raw logs also preserve failure evidence. Moving this into production trace contracts is a broader alternative rather than a prerequisite for this bounded evaluation.

The disabled failure/pass signal remains visible in per-arm JUnit, raw traces and assessment comments; incomplete suites cannot provide comparable wall-time p50. A matched acting-target failure can still be reviewed as a counterfactual to an actual successful rescue. No rescue is established in this pair. The baseline refusal test-message strengthening is accepted and will accompany the next source revision.

@thymikee

Copy link
Copy Markdown
Member Author

Normal Android workflow validation passed at 26c0c317c9f2c677ae735a95f8a22c292dfc3291: run 38289828169, Android job.

The job ran the single-shell helper in normal mode on emulator-5554: cached fixture APK restored/repacked and installed, initial drag replay passed, then the full-tier fixture E2E passed all 10 selected scenarios (including the three full-tier scenarios). Its nested fixture suite passed 3/3 on first attempts.

The log explicitly reached pnpm gate replay-android --retries 2 --artifacts-dir test/artifacts/replays-android --report-junit test/artifacts/replays-android.junit.xml. Downloaded JUnit confirms 6/6 passed, zero failures/skips, every case on attempt 1, including strengthened 04-text-input-keyboard.ad. Evidence is in uploaded replay-nightly-android-artifacts (artifact 11765442216). This validates the local ADB Android normal lane; it makes no Appium or readiness keep/drop claim.

@thymikee

Copy link
Copy Markdown
Member Author

Thanks for the update. At 26c0c31 the code looks fine and all 19 checks pass, but the readiness evidence #3077 asks for is still missing. The normal-mode single-shell dispatch ask is now fixed: run 38289828169 shows it works. What remains is the paired data. #3077 asks for five paired hosted runs, one with readiness_wait=enabled and one with readiness_wait=disabled per pair. Each arm must upload test/artifacts/readiness-experiment/{android,ios}-summary.json with pathProven=true, all six corpus hashes matched, requestFiles non-empty and validForDecision=true. The enabled arm must show readiness.observations > 0 and the disabled arm 0. Today Android fails 04-text-input-keyboard step 4 (wait 'role=text-field focused=true') in both experiment modes, while the normal lane passed 6/6. The disabled iOS arm has no valid artifact. I did not open the hosted run logs or artifacts, so these results come from your comments. I also did not run the new tests. I could not tell why Android 04 fails only in the experiment arms (--retries 0, no prior warm-up). It may be a corpus or ordering effect rather than a readiness effect. Next, please find the cause of the Android 04 focused-editor failure and of the disabled iOS capture failure, then collect five eligible pairs on both platforms with validForDecision=true. Not blocking, and you can take or leave these: the new android-search-diagnostic.ts and the android_diagnostic input debug the corpus failure rather than produce readiness evidence, and with readiness_wait=normal plus android_diagnostic=true the workflow skips iOS and android-manual.sh silently skips the diagnostic, so it should fail fast or not skip iOS. Thanks for answering the earlier question about the harness staying on the draft branch. The delta now carries repairs that main needs, so would a smaller shape work: one small PR to main with android-manual.sh, its test and the three Settings .ad repairs (already validated by run 38289828169), the readiness-experiment harness only on the unmerged draft dispatched by ref with results posted to #3077, and no checked-in diagnostic, using the existing --debug replay artifacts or a throwaway branch for the Android focus failure?

@thymikee
thymikee force-pushed the t3/readiness-evaluation-3077 branch from 26c0c31 to b8ca87b Compare October 12, 2026 18:45
@thymikee

Copy link
Copy Markdown
Member Author

Thanks for the update. The code looks fine at b8ca87b, and all 37 checks pass. The hosted readiness runs are manual dispatches, so they are not part of PR CI. I could not see a merge conflict. The earlier gaps are now covered by the new harness, but the decision evidence for #3077 is still missing.

scripts/replays/android-manual.sh: #3077 needs five paired enabled/disabled hosted runs. Each arm must show validForDecision=true, pathProven=true and six matched corpus hashes, with readiness.observations > 0 when enabled and 0 when disabled. At this head, Android 04 failed its focused-editor wait in both arms (runs 38281615034 and 38281619167). Per the PR body, the only eligible pair comes from c7289c2, an unmerged branch that adds a shared preparation step for the Boot receiver that kills the Search provider. This head does not have that step, so running replays-manual.yml from b8ca87b should repeat the Android 04 failure. That means no keep/drop decision can be attributed to the harness under review. Only one pair exists, and it comes from another commit. Four pairs and the aggregate audit are still missing. The rule is that every pair counted for #3077 comes from one named harness commit, and its summary.json head matches that commit. Could you either land the shared preparation here and collect all five pairs from this head, or name c7289c2 as the evidence harness? Either way, please post the five pairs (enabled and disabled, Android and iOS) with run links. For each, include the summary.json fields (validForDecision, pathProven, corpus hashes, readiness.observations/engagements/rescues) and the aggregate engagements, rescues and wall/replay times.

I did not open the hosted runs or artifacts, so pair eligibility is taken from the PR body. I did not run the new shell and native tests or the mutants. I also could not judge whether the preparation step on c7289c2 is corpus-neutral between the two arms. Please confirm that when you post the pairs. Before merge, the five eligible pairs from one harness commit and the aggregate audit must be posted.

@thymikee

Copy link
Copy Markdown
Member Author

Closing: this draft harness only gathered the hosted evidence for the #3077 keep/drop decision and was never meant to merge. The decision ships in #3599; the workflow runs linked from #3077 remain as the record.

@thymikee thymikee closed this Oct 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-14 06:43 UTC

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