summaryrefslogtreecommitdiff
path: root/CLAUDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md40
1 files changed, 40 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 5a7d1ae..807a35c 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -266,6 +266,46 @@ by default and correct; it is simply waiting for a publisher who marks breaks.
seeks approximate on a VBR file, and the playback position is the crown jewel. Full numbers in
`docs/detection-findings.md`.
+- **Detection runs on a server now, and `server/` is part of this repo.** Go, deployed on
+ tungsten as `listend.service`, behind Apache at https://listen.terst.org with a Let's Encrypt
+ cert. Data in `/site/listen.terst.org/data` (`state.json`, `audio/`, `token`). It polls the
+ phone's feed list, mirrors the newest 8 episodes per show, detects across all of them at once,
+ and serves the offsets *and the audio they belong to*. `FingerprintWorker` and `MidrollWorker`
+ are gone from the app.
+
+ **Serving the audio is load-bearing, not a convenience.** Dynamic ad insertion is on every
+ episode: Radiolab's Grass Apes declares 22:05 and the server was served 28:18. An offset
+ measured on one copy is minutes wrong for another, so the phone has to play the bytes the
+ detector examined. `EpisodeDownloader` prefers the server and falls back to the publisher --
+ the fallback matters, because skips improve playback rather than being a precondition for it.
+
+ **The offsets go into the same columns the on-device detector wrote**, which is why playback
+ needed no changes: `effectiveIntroMs`, `effectiveOutroMs` and `PlayheadPolicy` already read
+ them. No migration either.
+
+- **The confirmation threshold does not survive simultaneous mirroring, and currently detects
+ ads rather than intros.** Proved, not suspected: the segment confirmed on 8 of 8 Radiolab
+ episodes was searched for in an ad-free copy of the same episode fetched hours earlier and
+ scored **r = 0.0621**. It is in the ad break, not the programme. Mirroring 8 episodes within
+ one minute from the same ad server makes them maximally dependent, so whatever campaign is
+ running is in all of them, identical -- and `SelfCheck` cannot catch it, because the segments
+ genuinely *are* the same audio. Do not describe the current offsets as intro detection. The
+ fix is to record fetch times and require the agreeing episodes to span more than one fetch
+ occasion; full reasoning in `docs/detection-findings.md`.
+
+- **`android-ui tap` can land on the soft keyboard.** The dump reports the layout's own
+ coordinates, which the IME does not move, so an element listed at y=1643 can be underneath the
+ keyboard -- taps on it silently do nothing, which reads exactly like a broken handler. Found
+ the hard way: a Save button and a text field both appeared tapped and neither fired. Check
+ `adb shell dumpsys input_method | grep mInputShown` and dismiss with `input keyevent
+ KEYCODE_BACK` (not `KEYCODE_ESCAPE`, which does not close it) before tapping anything low on a
+ screen that has a text field.
+
+- **The server's API token is alphanumeric on purpose.** It is typed into a phone by hand, and
+ the first generated token was base64url -- whose leading `-` was eaten by `adb shell input
+ text` treating it as a flag, producing a silent 401 that looked like broken wiring. The
+ alphabet also omits l, I, 1, O and 0.
+
- **Android Auto is verified in a real car**, as of 2026-09-28. It appears, and connects. The
notification Peter saw on first connect was Android Auto's own new-media-app announcement,
not Listen: the only notification this app can raise is the Media3 transport control, which