diff options
| author | Claude <noreply@anthropic.com> | 2026-09-21 19:18:56 +0000 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-09-21 19:18:56 +0000 |
| commit | 4c99649d4fdc77334f749c68b81c33a2fcb6d36f (patch) | |
| tree | 4c9b2432f1ea1b70b625ba0ba0e93192490bcc6a /CLAUDE.md | |
| parent | 42fce8b0293f78e8cf9f60a0bf2c4cd1bd010a5a (diff) | |
Fix a queue bug that deleted episodes, and delete dead DAO methods
Review found a data-losing bug. advance() drops the head of the queue, but
play() never put the played episode there. Play something from a show list,
let it finish, and advance dropped whatever was actually at the head -- a
different episode, removed from the queue having never been played.
The fix is an invariant rather than a special case: anything played becomes
the head, so advance always drops the episode that just finished. playNow()
does that, play() calls it, and the tests name the scenario.
Two DAO methods had no caller -- getQueue, superseded by observeQueue, and
observeUnplayed, written for a screen that was never built. Deleted. Room
generates an implementation for each, so they were not free.
The reachability guard now covers DAO methods too, which is the shape that
bit FeeDreader: three superseded methods sat undetected until a manual audit.
Interfaces need looser matching than objects, since a call's receiver varies
by site and a @Transaction default method calls its siblings unqualified, so
it matches both forms and errs toward "called" -- a false alarm costs more
attention than a missed one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 24 |
1 files changed, 23 insertions, 1 deletions
@@ -54,11 +54,23 @@ with `adb shell monkey`. Use the shared wrappers, which report from exit codes, and a logcat capture started before launch: ``` -/workspace/devtools/bin/gradle-test /workspace/listen -- --rerun-tasks +/workspace/devtools/bin/gradle-test /workspace/listen -- --rerun-tasks +/workspace/devtools/bin/gradle-report /workspace/listen detekt /workspace/devtools/bin/android-launch-check org.terst.listen \ --apk app/build/outputs/apk/debug/app-debug.apk --settle 15 +/workspace/devtools/bin/android-ui org.terst.listen dump +/workspace/devtools/bin/publish-apk \ + app/build/outputs/apk/debug/app-debug.apk listen-debug.apk ``` +**Never read `app/build/reports/detekt/detekt.xml` directly.** An invalid config aborts detekt +before it analyses anything and leaves the previous run's report in place; it was read as +current findings three times. `gradle-report` refuses a report older than the run. + +**Never `adb shell input tap X Y`.** A blind tap landed in FeeDreader's settings and the +screenshot after it was reported as Listen. `android-ui` checks the foreground package first +and taps by label. + See `/workspace/devtools/README.md`. These exist because grepped console text has produced wrong claims three separate times across these repos. @@ -130,3 +142,13 @@ intro/outro skipping. Schema fields for manual skip offsets exist but nothing re - **Feeds are big.** A real subscription in testing produced 2753 episodes in one refresh. Any per-episode work — a query in a loop, an O(n²) match — needs to be considered at that scale. + +- **The playing episode is always the head of the queue.** `advance()` drops the head, so if + something played from a show list isn't there, finishing it deletes a queued episode unplayed. + `play()` calls `playNow()` first to hold that invariant. Don't add a playback entry point that + skips it. + +- **Two reachability tests guard dead code**, one for helper objects and one for DAO methods. + Both exist because code was written, tested, documented and never called: `findFeedLink` (the + share-sheet bug) and `QueueRepository.advance` (the queue silently stopped). Adding to their + allowlists needs a reason, not just a name. |
