uttrflow / uttrflow/uttrflow-swift
A newly copied picture evicted immediately by the disk budget leaves its PNG orphaned on disk
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 4h 27m
- Merged PRs (30d)
- 286
Description
## Problem
The noticed-picture path writes a PNG before deciding whether the clip survives retention and disk limits. If the new image is dropped immediately, `save()` cannot delete it: cleanup compares images in the previous list with the retained list, and the new file appears in neither. Repeated rejected pictures can consume disk outside the declared budget.
## Evidence
Reviewed `main` at `8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d`. Reproduced against the unchanged production source in an isolated Swift package on macOS, with fake transport or temporary stores as appropriate. These checks assert the observed defect; they are not a claim that the full app test suite passed.
With a temporary store and a deliberately tiny disk budget of one byte:
1. Record three distinct two-byte picture payloads through `record(NoticedClip, keeping:)`.
2. Each call returns zero retained clips.
3. `Images/` contains three files (six bytes).
4. Reopen the store and read clips: the three files remain, because the launch sweep refuses to sweep an empty list.
The data is intentionally tiny to exercise accounting without allocating a real oversized image; the store does not decode these bytes. The same path applies when a new picture exceeds the configured disk quota. This test establishes orphan retention, not a claim about typical screenshot sizes.
## Relevant code
- [Sources/UttrflowClipboard/ClipboardStore.swift:171](https://github.com/uttrflow/uttrflow-swift/blob/8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d/Sources/UttrflowClipboard/ClipboardStore.swift#L171)
- [Sources/UttrflowClipboard/ClipboardStore.swift:362](https://github.com/uttrflow/uttrflow-swift/blob/8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d/Sources/UttrflowClipboard/ClipboardStore.swift#L362)
- [Sources/UttrflowClipboard/ClipboardStore.swift:428](https://github.com/uttrflow/uttrflow-swift/blob/8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d/Sources/UttrflowClipboard/ClipboardStore.swift#L428)
- [Sources/UttrflowClipboard/ClipboardStore.swift:451](https://github.com/uttrflow/uttrflow-swift/blob/8d93f5b8574f3c7b8c30086d9c817bf7f5d4827d/Sources/UttrflowClipboard/ClipboardStore.swift#L451)
## Fix and acceptance criteria
Delete a newly created picture if its index entry is not retained or cannot be persisted, without deleting a previously shared image. Make orphan recovery safe for trustworthy empty indexes. Test immediate eviction, a refused index write, and repeated copies, asserting actual files and byte totals.
## Existing work checked
#404 protects pictures when an index is unreadable. This case has trustworthy empty indexes and newly-created files that never enter either index.
Contributor guide
Research direction
Read Sources/UttrflowClipboard/ClipboardStore.swift around lines 171, 362, 428, and 451, starting from record(NoticedClip, keeping:), then inspect the index and disk-cleanup paths. Reproduce the tiny-budget scenario and add coverage for immediate eviction, refused index writes, and repeated copies; done means actual files and byte totals stay within the budget without deleting shared images.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- database, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100