mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
04052fdcd2
* fix(android): retire recording evidence stranded by a re-adopted device 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 * fix(android): keep an unreadable recorder off the delete path 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. * fix(android): keep a mixed writer scan inconclusive The writer search answered `found` as soon as it identified one recorder, which hid the candidates it could not read. Start reconciliation already refuses a found writer, but owned cleanup stops only the recorders it was handed and then removes the artifact and marker — deleting under an unreadable recorder still writing that same path. A search now reports the writers it identified together with whether every candidate was read. Cleanup requires both halves: an identified recorder does not prove the others are gone, so an inconclusive scan retains the evidence before anything is signalled or removed. * test(android): record retirement side effects through one evidence rig 21 reconciliation scenarios each rebuilt the same marker reader and the same recording transport stubs. One rig holds the marker and the ordered side-effect log, so a test names only the probe outcome it is about. * test(android): keep legacy reconciliation scenarios as they were The scenarios that already covered retirement were rewritten into a shared rig, which spent most of this PR's churn budget on moving lines around. They read from the device marker again as before; only the recorder-state table names the outcome each state now produces, and the stale row that expected evidence naming another device identity to be kept is gone, since retiring it is this fix. New scenarios use the rig. * test(android): table-drive the inconclusive writer scans Each inconclusive writer-scan scenario rebuilt the same scoped adb fake and the same cleanup transport. The transport cases now differ only in which candidate reads fail, and the owned-cleanup cases differ only in the scan they return, so both run from one table against the same assertions.