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:
2026-09-10 00:49:26 -04:00
co-authored by Claude Opus 5
parent cc1ca5ef78
commit bcba621f3f
8 changed files with 696 additions and 7 deletions
+14
View File
@@ -9,6 +9,20 @@ When a round closes, move its finished items to `tasks-done.md`.
- [ ] archive the done tasks in here to another file, this is crufty....
## Round 48 (2026-09-10) — A library to break: done, see tasks-done.md
`scripts/make_dev_library.py` + the andTunes resume docs. Left on the table:
- [ ] **The fixture has no iTunes XML.** `test_itunes_importer.py` still leans
on the gitignored `itunes-test-library/`. A generator flag that emits a
matching `iTunes Library.xml` would make the import path developable
without trav's own export too.
- [ ] **No fixture for a Syncthing conflict.** The merge rules are the
subtlest thing in the codebase and the generator could plant a
`*.sync-conflict-*` pair on demand — two copies with different
`date_modified`, one stamped and one not — instead of every conflict
test hand-rolling one.
## Round 47 (2026-09-06) — LinTunes writes the device's library: done, see tasks-done.md
The desktop half of andTunes: a de-duplicated `Music/andTunes/` tree, a