v0.17.1: a library to break
Round 47 was verified by loading trav's real 21,531-track library. Nothing was written and nothing was at risk, but it's the wrong habit and he said so. The alternative is better for development anyway: reproducible, in-repo, and full of the awkward cases on purpose rather than by luck. scripts/make_dev_library.py builds a complete synthetic library — data dir and music tree — from ffmpeg sine waves in six containers, with art on some albums and not others, every playlist type (regular, folder, live/non-live/ unsupported/limited+nested smart, system, empty, duplicates), a play journal and a tombstone. ~4 MB, gitignored; the generator is the artifact worth keeping, not the sine waves. The edge cases are the point. A collision pair identical in artist/album/title/ number, slashes and colons in every name, a track with no artist, a multi-disc release, a compilation whose album_artist differs, a dangling location, a 208-character title, and non-ASCII plus an emoji all the way out to the m3u filename. CLAUDE.md now carries the rule: never develop against the real library, and when a feature needs a shape the fixture lacks, add it here. Using it found two bugs in it — a relative --out made every location resolve against the wrong root, and four-minute uncompressed clips made it 62 MB. andTunes is paused on a weak connection (the Android SDK is a ~1-1.5 GB one-time download; after that --offline builds need nothing). andtunes/ README.md now carries everything needed to resume cold: measured device facts, the dp trap, exact toolchain commands, locked design decisions, and the library.json contract. JDK 21 is installed and ticked off. Also answers the scroll wheel question: it reads as volume because the ROM's key layout maps the wheel's KEY_UP/KEY_DOWN to KEYCODE_VOLUME_UP/DOWN, but a focused activity sees key events first — so andTunes can claim it by consuming both those and DPAD_UP/DOWN, in onKeyDown and onKeyUp. No system file touched, no other app affected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015wrTys5U1fLb4pBD2LKWzV
This commit is contained in:
@@ -1,5 +1,63 @@
|
||||
## Done
|
||||
|
||||
### Round 48 (2026-09-10) — A library to break (v0.17.1)
|
||||
|
||||
Round 47 was verified by loading trav's real 21,531-track library. Nothing was
|
||||
written to it and nothing was at risk, but that is the wrong habit and he said
|
||||
so: "it's too precious… mistakes happen and it makes me nervous." He's right —
|
||||
the safety of a given run isn't the point when the alternative is a fixture
|
||||
that's better for development anyway: reproducible, in-repo, and full of the
|
||||
awkward cases on purpose rather than by luck.
|
||||
|
||||
- [x] **`scripts/make_dev_library.py`.** Builds a complete synthetic library —
|
||||
data dir *and* music tree — from ffmpeg sine waves in six containers
|
||||
(mp3, m4a, flac, wav, aiff, ogg), with embedded art on some albums and
|
||||
none on others, every playlist type (regular, folder + children,
|
||||
live/non-live/unsupported/limited+nested smart, system, empty,
|
||||
duplicates), a per-machine play journal and a tombstone. ~4 MB, a few
|
||||
seconds to build, `--force` to rebuild, gitignored — the generator is
|
||||
the artifact worth keeping, not the sine waves.
|
||||
- [x] **The edge cases are the point.** Each one has bitten something: a
|
||||
collision pair identical in artist/album/title/number (the `[track_id]`
|
||||
suffix), slashes and colons in every name (`sanitize_name`), a track
|
||||
with no artist and none with an album (Unknown Artist/Album), a
|
||||
multi-disc release (the `2-04` prefix), a compilation whose
|
||||
`album_artist` differs from every track artist (album grouping and the
|
||||
art key), a dangling `location` (the "skipped, no local file" counters),
|
||||
a 208-character title (the 150-char truncation — and the manifest still
|
||||
carries it in full, which is what the app displays), and non-ASCII plus
|
||||
an emoji all the way out to the device's m3u filename.
|
||||
- [x] **Two bugs in the generator, found by using it.** Passing a relative
|
||||
`--out` made every `Track.location` resolve against the wrong root on
|
||||
load, because locations are absolute in memory and stored relative to
|
||||
the data dir; and four-minute uncompressed clips made the fixture 62 MB.
|
||||
Durations only need to *differ* (sorting, smart-playlist limits,
|
||||
`#EXTINF`), so they're now 2–20 s and the whole thing is 4.4 MB.
|
||||
- [x] **Round 47 re-verified against the fixture**, not the real library:
|
||||
first sync, an idempotent re-sync (0 copied, 6 kept), unticking, and the
|
||||
awkward playlist end-to-end — `Song [19].mp3` / `Song [20].mp3` for the
|
||||
collision pair, `mix summer 2003 🎧.m3u`, the dangling track counted as
|
||||
skipped rather than fatal.
|
||||
- [x] **A standing rule in CLAUDE.md**: never develop or verify against the
|
||||
real library; when a feature needs a shape the fixture lacks, add it to
|
||||
the generator.
|
||||
- [x] **andTunes documented for a cold resume.** `andtunes/README.md` now
|
||||
carries the measured device facts, the dp trap, the exact toolchain
|
||||
commands, the locked design decisions and the `library.json` contract;
|
||||
`andtunes/TASKS.md` renumbered to andTunes' own phases. Work is paused
|
||||
on a weak connection — the Android SDK is a ~1–1.5 GB one-time download,
|
||||
after which `./gradlew --offline` needs no connection at all. JDK 21 is
|
||||
already installed and ticked off.
|
||||
- [x] **The scroll wheel question answered.** It reads as volume in every app
|
||||
because the ROM's key layout maps the wheel's KEY_UP/KEY_DOWN to
|
||||
`KEYCODE_VOLUME_UP/DOWN` — but a focused activity sees key events first,
|
||||
so andTunes can claim it by consuming both those *and* `DPAD_UP/DOWN`
|
||||
(the mapping is unconfirmed) in `onKeyDown` **and** `onKeyUp`. No system
|
||||
file touched, no other app affected.
|
||||
|
||||
Not done, deliberately: no iTunes XML in the fixture (the importer tests still
|
||||
use the gitignored real export), and no synthetic Syncthing conflict pair.
|
||||
|
||||
### Round 47 (2026-09-06) — LinTunes writes the device's library (v0.17.0)
|
||||
|
||||
The first half of andTunes, a music player for the Rabbit R1 that never scans
|
||||
|
||||
Reference in New Issue
Block a user