R21 — After a failed save, the only button the UI offers destroys the file the code deliberately kept #30

Closed
opened 2026-08-23 03:44:50 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-08-23 03:44:50 +00:00 (Migrated from github.com)

Finding R21 from the overnight max-effort review (Fable lead, Opus sub-agents). Full report: scratchpad/overnight/REVIEW.md.

R21 — After a failed save, the only button the UI offers destroys the file the code deliberately kept

severity: low-medium
verdict: CONFIRMED (lead re-read all four sites)
where: app/src/main/java/org/libremediaconverter/convert/ConversionViewModel.kt:414-421 vs ConverterScreen.kt:221-231; same shape JoinViewModel.kt:232-239 / JoinScreen.kt:164-174
scenario: 40-minute transcode done; Save fails (destination full). save()'s onFailure deliberately keeps pendingStaged ("deleting here would destroy the work") and sets Failed — whose screen branch renders exactly one control: "Start over" -> reset() -> discardStaged() deletes it. No Save button on Failed. The only rescue is process death -> reattach (unadvertised, <24h sweep window).
evidence: All four sites read by lead and reviewer. No JVM test asserts what Failed offers.
fix: Failed variant carrying the staged handle when the failure came from save(); render "Try saving again" beside "Start over". Decide what Start-over does from that state (delete — but only once the alternative was offered).
risk: Touches the state machine and both screens; a Failed that carries a file is a new invariant for reset(). VM half JVM-testable now; screen half needs createComposeRule.


LOW


Cut: below — held for manual review: product decision, CI/workflow, hardware, or PLAUSIBLE verdict.

🤖 Generated with Claude Code

_Finding **R21** from the overnight max-effort review (Fable lead, Opus sub-agents). Full report: `scratchpad/overnight/REVIEW.md`._ ### R21 — After a failed save, the only button the UI offers destroys the file the code deliberately kept severity: low-medium verdict: CONFIRMED (lead re-read all four sites) where: app/src/main/java/org/libremediaconverter/convert/ConversionViewModel.kt:414-421 vs ConverterScreen.kt:221-231; same shape JoinViewModel.kt:232-239 / JoinScreen.kt:164-174 scenario: 40-minute transcode done; Save fails (destination full). save()'s onFailure deliberately keeps pendingStaged ("deleting here would destroy the work") and sets Failed — whose screen branch renders exactly one control: "Start over" -> reset() -> discardStaged() deletes it. No Save button on Failed. The only rescue is process death -> reattach (unadvertised, <24h sweep window). evidence: All four sites read by lead and reviewer. No JVM test asserts what Failed offers. fix: Failed variant carrying the staged handle when the failure came from save(); render "Try saving again" beside "Start over". Decide what Start-over does from that state (delete — but only once the alternative was offered). risk: Touches the state machine and both screens; a Failed that carries a file is a new invariant for reset(). VM half JVM-testable now; screen half needs createComposeRule. --- ## LOW --- **Cut:** `below` — held for manual review: product decision, CI/workflow, hardware, or PLAUSIBLE verdict. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMediaConverter#30