summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Sonnet 5 <noreply@anthropic.com>2026-09-26 12:59:05 -1000
committerClaude Sonnet 5 <noreply@anthropic.com>2026-09-26 12:59:05 -1000
commitae55ee952e10904096c65e47c69a6364f076720a (patch)
tree9dceb7357003ce5d487f9ca586b985a37b77f4b4
parent2ef1b63f1ea1536d8c56e62adac425971665101d (diff)
Record Listen Tier 3 fingerprinting: prototype findings and the DAI-ad trap
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sj3CoWEedM56bebByKgNxA
-rw-r--r--MEMORY.md1
-rw-r--r--project_listen_tier3_fingerprinting.md48
2 files changed, 49 insertions, 0 deletions
diff --git a/MEMORY.md b/MEMORY.md
index 7c70dfb..ceb613d 100644
--- a/MEMORY.md
+++ b/MEMORY.md
@@ -1,5 +1,6 @@
# Memory Index
+- [Listen Tier 3 fingerprinting](project_listen_tier3_fingerprinting.md) — prototype findings (DAI-ad false-positive trap), built 2026-09-26, unverified on a device
- [Delegation & context protection](feedback_delegation_and_context_protection.md) — fork vs fresh vs inline decision rule; `~/.claude/agents/verifier.md` custom agent for adversarial claim-checking without redoing work
- [Terse manager-level updates](feedback_terse_manager_updates.md) — status updates should be outcome+next-step only, not sub-fix technical narratives
- [User doesn't read the code](feedback_user_does_not_read_code.md) — never cite commits/diffs as evidence to Peter; explain in observable behavior, and own correctness since he won't catch errors by review
diff --git a/project_listen_tier3_fingerprinting.md b/project_listen_tier3_fingerprinting.md
new file mode 100644
index 0000000..a7f4d06
--- /dev/null
+++ b/project_listen_tier3_fingerprinting.md
@@ -0,0 +1,48 @@
+---
+name: project_listen_tier3_fingerprinting
+description: "Tier 3 skip detection (audio fingerprinting) — desktop prototype findings and the resulting design, built 2026-09-26, unverified on a device"
+metadata:
+ node_type: memory
+ type: project
+ originSessionId: 0e4bffd6-5847-4b40-9037-6bfb9055e654
+ modified: 2026-09-26T22:58:51.673Z
+---
+
+Commit `4e37185` on `listen` (pushed to tungsten) adds Tier 3 of the skip feature: detecting a
+show's recurring intro/outro from the audio itself, rather than a manual per-show offset (Tier 2,
+already built) or publisher-marked chapters (also already built). This was the one item Peter
+explicitly deferred from Phase 2 pending a desktop prototype — see [[listen-handover-2026-09-21]]
+for the standing instruction that drove that order of operations.
+
+**Prototype findings** (throwaway Python, `numpy`/`scipy`, not committed anywhere — real episodes
+downloaded fresh from each show's real feed):
+- **NPR Up First**: a clean ~6s intro sting, same position, found in all 6 tested episode pairs
+ (r = 0.96–0.998 against a ~0.05–0.15 noise floor). The clean case.
+- **Tangle**: a long (60–90s) segment at both ends, found in every pair (r mostly 0.93–1.000) —
+ probably a scripted open/sponsor read, not a jingle, but just as reliably matchable.
+- **Darknet Diaries**: no real intro. A segment that matched between two temporally-close
+ episodes turned out to be a **dynamically-inserted ad** — confirmed by fetching a 2018 episode,
+ which matched the same "intro" at r≈1.000 despite the multi-year gap, while two *other* recent
+ episodes (fetched at the same time as the false match) matched nothing. These feeds route
+ through PodTrac's ad redirect layer, which re-stitches whatever ad is currently rotating into
+ archived episodes on every fetch, not just new ones.
+
+**Why this matters beyond Listen:** any future fingerprinting/dedup work against podcast audio
+(here or elsewhere) needs to know that "the same segment appeared in 2 episodes fetched close
+together" is not evidence of anything structural — it's exactly what a rotating ad produces too.
+The mitigation that shipped: `IntroOutroDetector` requires 3+ *independently-fetched* episodes to
+agree before trusting a candidate and auto-applying it to real playback. That threshold is now a
+parameter (`confirmThreshold`), not hardcoded — a coverage review during implementation found the
+"still tentative" branch was structurally unreachable at the original hardcoded value of 3,
+because the design counts 2 already on first-candidate discovery.
+
+**How to apply:** if Peter reports Tier 3 confidently "detecting" something wrong (skips real
+content, or the confirmed count climbs suspiciously fast for a show he only recently subscribed
+to), re-fetch that show's episodes on a real *time delay* before concluding the detector is buggy
+— check whether it's actually the DAI-ad trap recurring, the same way it did for Darknet Diaries.
+
+**Not yet verified on a device** — no phone was connected this session. In particular:
+`MediaCodecClipSource` (the MediaExtractor/MediaCodec decode loop) has never run on real hardware,
+and the `MigrationTest` 6→7 case has never run on an emulator/device either. Both need a real run
+before this is trusted with real playback — check `adb devices` first next session, per
+[[listen-handover-2026-09-21]]'s own standing note about that.