Repository navigation
feat: add photo organizing, a new category - #10
Merged
Merged
Conversation
Photos are the largest clutter surface on a normal machine and the one people most want sorted. The blocker was that near-duplicate detection needs image decoding, which would break the no-dependency rule. Most of the value turns out not to need it. scripts/photos.py reads EXIF dates, camera make and model, and image dimensions straight from file headers. No decoding, no dependencies, same behaviour on every platform. That buys the thing sorting usually gets wrong. A file's modified date is not when the photo was taken; copying, syncing, restoring a backup, or receiving an image through a messaging app all rewrite it. Sort by file date and a 2019 holiday lands in whatever month the phone was last restored. The skill leads with how many photos carry a real date and offers the rest separately rather than silently guessing. Bursts are detected by timestamps three seconds apart on the same camera, not by comparing pixels, and are deliberately kept distinct from exact duplicates. Forty near-identical frames are a person holding the shutter down, and only they can see which one has everyone's eyes open. Nothing in this skill deletes a photo. The most it does unprompted is move files into a clearer structure. The EXIF parser was validated against an independent reader rather than against its own test fixtures: splicing the generated APP1 segment into a real JPEG and reading it back with macOS sips returns the same make and model this parser reports.
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.
Photos were the highest-value candidate from the category brainstorm and the one I set aside, because near-duplicate detection needs image decoding and that breaks the no-dependency rule.
Most of the value turns out not to need it.
Reading photos without decoding them
scripts/photos.pypulls EXIF dates, camera make and model, and image dimensions straight from file headers. Stdlib only, same behaviour on every platform.That buys the thing sorting usually gets wrong:
Copying, syncing, restoring a backup, or receiving an image through a messaging app all rewrite it. Sort by file date and a 2019 holiday lands in whatever month the phone was last restored.
So the skill leads with the count and offers the rest separately:
Bursts are not duplicates
Forty near-identical frames are a person holding the shutter down. Only they can see which one has everyone's eyes open, so the skill never picks the keeper.
Nothing in this skill deletes a photo. Not to the trash, not "safely", not even exact duplicates without asking. The most it does unprompted is move files.
The EXIF parser is validated against an independent reader
Testing a parser against fixtures written by my own generator proves nothing — both can be wrong the same way. So I spliced the generated APP1 segment into a real JPEG and read it back with macOS
sips:A different implementation confirms the layout.
Also
mediais a new category, so the set is now one skill per category across four categories152 tests, 25 of them new.