summaryrefslogtreecommitdiff
path: root/gradle.properties
AgeCommit message (Collapse)Author
2026-10-31Deep clean, part one: get the pipeline out of the commandPeter Stone
cmd/listend/main.go had reached 1,249 lines carrying nine passes, and cmd has no test file -- so every judgement in the transcript pipeline lived where nothing could reach it. That is not hypothetical: a refetch master blocked the recurring detector for a fortnight because the condition was wrong in a place no test could see. internal/words now holds the five passes with judgement in them -- Harvest, Recognise, Rederive, Recurring, SecondCopy -- behind a Pipeline that names its dependencies. main.go is 631 lines and does what a command should: read flags, wire things together, serve. **Moving it found a latent bug.** Pruning an episode's audio cleared its transcript fields but not its master ones, so a re-mirrored episode would claim a master whose file had been deleted -- a second description it could not produce, and subtraction finding nothing for it for ever. Exactly the shape of the bug that had just cost a fortnight. Pipeline.Forget now clears all of it, including the attempt timestamps, so a re-mirrored episode is done again rather than skipped for ever. Pinned by a test that asserts it needs recognising afterwards. Also in this part: Gradle's file-system watching is off. Chaquopy extracts a 3,200-file Python environment into app/build mid-build and the watcher tripped over re-registering it, printing "Caught exception: Already watching path" in front of every build error this project produced all week. It costs nothing to turn off -- measured twice each on a no-op compileDebugKotlin, 1.50s and 1.59s with, 1.46s and 1.46s without -- because that extraction invalidates the VFS anyway. A watcher holding stale state about a tree another tool rewrites causes the "clean and try again" class of problem rather than curing it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
2026-09-21Scaffold Listen, with a podcast-native feed parserClaude
Sibling to FeeDreader, not a shared module. That was a considered call: its FeedParser only inspects <enclosure> while hunting for a thumbnail, and its FilterRuleEngine is 46 lines of title substring matching that doesn't generalise to queue rules, so only Opml.kt would genuinely have transferred. The parser is the piece everything else sits on, so it goes first, test-first: 18 tests covering audio/video enclosure selection, iTunes durations in both second and clock form, season/episode numbers, podcast:chapters for the skip feature, RFC 5005 archive paging for drip subscriptions, and episode identity falling back to the enclosure URL when a guid is missing. Two things worth recording: - Built on XmlPullParserFactory rather than android.util.Xml. The latter returns null off-device, which is why FeeDreader's 297-line parser has no tests at all. Both resolve to the same KXmlParser on Android. - SimpleDateFormat with isLenient=false rejects "Tue, 02 Sep 2026 06:00:00 GMT" -- an entirely ordinary RFC 822 date. Left strict, every pubDate in the app would have been null and episode ordering would have been silently wrong everywhere. minSdk is 29, deliberately not FeeDreader's 36, which would restrict the app to Android 16 and newer. Permissions: INTERNET and ACCESS_NETWORK_STATE for feeds; FOREGROUND_SERVICE, FOREGROUND_SERVICE_MEDIA_PLAYBACK, POST_NOTIFICATIONS and WAKE_LOCK because Android requires a foreground service with a notification to play audio in the background. That notification is the transport control, not an alert -- Listen posts no new-episode notifications by design. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B