Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(android): retire recording evidence stranded by a re-adopted device id - #2564

Open
thymikee wants to merge 2 commits into
mainfrom
t3code/fix-2550-quality-refactor
Open

fix(android): retire recording evidence stranded by a re-adopted device id#2564
thymikee wants to merge 2 commits into
mainfrom
t3code/fix-2550-quality-refactor

Conversation

@thymikee

@thymikee thymikee commented Sep 13, 2026

Copy link
Copy Markdown
Member

Summary

Android record start refused forever once an emulator was re-adopted under a new serial. The
device-side marker names the device identity that wrote it, and reconciliation retired evidence only
when that identity matched, so a marker left by an earlier session on the same AVD blocked every later
recording with Android screenrecord native recovery evidence already exists — surfaced as UNKNOWN
whose hint asked for a bug report — while record stop owned nothing that could clear it.

Reconciliation now retires evidence that is terminal or names an unreachable device identity, after
proving every artifact it names is released: committed recorders through process inspect, an
uncommitted pending artifact against the recorders running on the device. Nothing is deleted under a
live recorder — the refusal is DEVICE_IN_USE with details.writer naming named-recorder or
other-recorder. Unreadable evidence, the other transport mode, and an open recording this identity
owns stay refused, now as typed errors naming the marker path and the command that clears it.

Reconciliation moved to start-reconciliation.ts, marker persistence to manifest-store.ts.
14 files. Closes #2550.

Residual risk: evidence under an unreachable identity can name artifacts nobody ever pulled; retiring
it removes them, since no reachable session can recover them. Marker removal is not compare-and-delete.

Validation

Commits 44682608bc and 200ad13429. pnpm check:affected --run passed on each: format, lint,
typecheck, layering, fallow, build, vitest-related, unit, provider-integration.

200ad13429 answers a review finding that an inconclusive writer probe could be read as "path is
free" and delete a live artifact: the transport now reports clear | found | uncertain, and both
retirement and owned cleanup retain evidence on uncertain. Both regressions were confirmed to fail
when that branch is reverted to the doubt-as-proof reading.

Live on emulator-5554 (Pixel 7 CI, Android 16) at 44682608bc:

  • terminal marker with deviceId: emulator-9999record start --scope device succeeded and retired
    it; previously this was the reported refusal;
  • open marker naming emulator-5554DEVICE_IN_USE, retriable: false,
    reason: native_recovery_evidence_open, hint names the owning session; marker retained;
  • foreign marker naming a path an unmanaged screenrecord was writing → DEVICE_IN_USE,
    reason: native_recording_artifact_claimed, writer: other-recorder; marker and artifact retained,
    and the retry after that recorder ended succeeded and removed the orphan artifact.

Sessions closed and device markers cleaned. Coverage stays CI-authoritative.

…ce id

Android `record start` refused forever with "native recovery evidence already
exists" once an emulator was re-adopted under a new serial: the device-side
marker names the device identity that wrote it, reconciliation retired evidence
only when that identity matched, and the leftover classified as neither
recoverable nor retireable — an `UNKNOWN` internal error whose hint asked for a
bug report, while `record stop` owned nothing to clear.

Start reconciliation now retires evidence whose recording is terminal or whose
device identity the transport can no longer address, and only after every
artifact it names is proven released: a committed recorder through process
inspect, an uncommitted pending artifact against the recorders running on the
device. A recorder still writing is never deleted; the refusal names the writer
in `details.writer`. Remaining refusals — unreadable evidence, the other
transport mode, and an open recording this identity owns — are typed errors
carrying the marker path and the command that clears it.

Closes #2550
@github-actions

github-actions Bot commented Sep 13, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
Installed (including dependencies) 4.52 MB 4.52 MB +3.2 kB
Package (unpacked) 4.52 MB 4.52 MB +3.2 kB
Package (download) 1.33 MB 1.33 MB +776 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 22.4 ms 23.5 ms +1.1 ms
CLI --help 59.2 ms 59.6 ms +0.4 ms

@thymikee

Copy link
Copy Markdown
Member Author

The pending-artifact cleanup at start-reconciliation.ts:108 can delete a recording that is still being written. findRunning drops uncertain process inspections, so a failed /proc read for a live recorder can produce an empty list; reconciliation then removes its artifact and recovery marker. Preserve that uncertainty and refuse cleanup when ownership cannot be established, with a regression covering an inconclusive inspection. The reported device scenarios and green checks do not cover this case. Reviewed 4468260.

The writer probe filtered candidate processes down to the ones it could prove
were recorders, so a caller that read an empty list as "nothing writes this
path" removed an artifact from under a recorder whose /proc entries could not
be read, along with the marker that named it. A process table it could not read
at all threw a bare Error, which reached callers as an unclassified failure.

The transport answers a writer search with `clear`, `found`, or `uncertain`.
Only `clear` proves an artifact is free: start retirement refuses with
`native_recording_recorder_unproven` and owned cleanup keeps the evidence
pending, so both wait for a conclusive answer instead of deleting on doubt.
@thymikee

Copy link
Copy Markdown
Member Author

Fixed in 200ad13. findRunning filtered candidates down to proven recorders, so an empty list was read as "path is free" while a live recorder's /proc reads were failing; an unreadable process table threw a bare Error.

The transport probe now answers clear | found | uncertain (probeRunningWriters), and only clear proves an artifact free: start retirement refuses with native_recording_recorder_unproven and owned cleanup returns the evidence pending, so the marker and artifact stay put until the answer is conclusive.

Regressions: src/platform-runtime-screen-recording-android-host.test.ts covers an unreadable candidate and an unreadable process table; start-reconciliation.test.ts refuses with zero side effects; recovery-cleanup.test.ts retains evidence. All three fail when the uncertain branch is reverted to doubt-as-proof.

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.

Android record start refuses with "native recovery evidence already exists" on an emulator re-adopted from a previous session

1 participant