fix(#265): create screenshot target directory before capture — stop blaming device state#283
Merged
Merged
Conversation
…laming device state
device_screenshot with a path under a non-existent directory failed with
"The device may be transitioning state (booting, OOM, locked)" — a pure
misdiagnosis. Live-verified: `xcrun simctl io <udid> screenshot
docs/proof/<missing>/01.jpg` exits 4 with NSCocoaErrorDomain "The folder
doesn't exist" (underlying ENOENT) on a healthy booted simulator. The
capturer's bare `catch { return false }` erased the cause and
rawResultFail mapped every non-no-device failure to the device-state
guess. Same hazard on Android: createWriteStream(path) ENOENTs into the
identical message.
Fix at the shared funnel (captureAndResizeScreenshot — covers
device_screenshot, device_batch auto-captures, proof_step):
- mkdir -p the parent of the derived path before any dispatch tier runs;
new directories are the expected case since the EPHEMERAL_PATH advisory
steers agents toward fresh docs/proof/<slug>/ paths.
- If mkdir itself fails (file blocking an intermediate segment,
permissions), short-circuit BEFORE any device probing with an honest
SCREENSHOT_FAILED naming the path (reason: target-dir-unavailable).
Tests: 3 new (raw iOS path repro, mkdir-failure classification with
negative assertion on /transitioning/i, runner-path dir precondition).
Suite: 2016/2016 (main: 2013). Live gate: previously-failing repro now
captures + resizes end-to-end against the booted simulator.
Closes #265
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Node never expands `~`, so the new mkdir-p precondition turned a previously loud failure for `~/Desktop/x.jpg` into a silent mislanding: a literal `./~/Desktop/` created under the bridge cwd, success reported, screenshot nowhere near the user's Desktop. deriveScreenshotPath now expands a leading `~/` to homedir() so every consumer (mkdir, advisories, all capture tiers) sees the same real path, and refuses unexpandable forms (`~user/...`, bare `~`) with an actionable error instead of mislanding. The traversal guard still runs on the RAW input before expansion, so `~/../` cannot smuggle a collapsed `..` past it via join(). Tests: 3 new (expansion, honest refusal, guard-before-expansion pin). Suite: 2019/2019. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
device_screenshotwith apathunder a non-existent directory failed with "The device may be transitioning state (booting, OOM, locked)" — a pure misdiagnosis of a filesystem precondition (GH #265).Root cause (live-verified on a healthy booted simulator):
xcrun simctl io <udid> screenshot docs/proof/<missing>/01.jpgexits 4 withNSCocoaErrorDomain"The folder doesn't exist" (underlying ENOENT). The iOS capturer's barecatch { return false }erased the cause, andrawResultFailmapped every non-no-devicefailure to the device-state guess. The Android tier had the identical hazard viacreateWriteStream(path)ENOENT.Fix
All at the shared funnel
captureAndResizeScreenshot(coversdevice_screenshot,device_batchauto-captures, andproof_step):mkdir -pthe parent of the derived path before any dispatch tier runs (simctl raw, rn-fast-runner, agent-device daemon/CLI, adb stream). New directories are the expected case — the tool's ownEPHEMERAL_PATHadvisory steers agents toward freshdocs/proof/<slug>/paths.SCREENSHOT_FAILED/reason: 'target-dir-unavailable'naming the offending path.~/expansion (codex review finding on the first commit): Node never expands~, so the mkdir precondition would have turned a loud failure for~/Desktop/x.jpginto a silent mislanding (literal./~/Desktop/under the bridge cwd, success reported).deriveScreenshotPathnow expands a leading~/tohomedir()and refuses unexpandable forms (~user/..., bare~). The traversal guard runs on raw input before expansion, so~/../cannot smuggle a collapsed..past it.Verification
doesNotMatch /transitioning/iagainst the exact production message).platform=ios, path under a fresh nested dir) now captures + resizes end-to-end against the booted simulator (1206×2622 → 800×1739, 48% bytes saved).device_recordadvisory filed as fast-follow bug: device_record has the same missing-target-directory hazard fixed for device_screenshot in #265 #282.Closes #265
🤖 Generated with Claude Code