diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/superpowers/plans/2026-10-20-corrections-and-signature-library.md | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/docs/superpowers/plans/2026-10-20-corrections-and-signature-library.md b/docs/superpowers/plans/2026-10-20-corrections-and-signature-library.md index 2572cc3..fb4ad2c 100644 --- a/docs/superpowers/plans/2026-10-20-corrections-and-signature-library.md +++ b/docs/superpowers/plans/2026-10-20-corrections-and-signature-library.md @@ -174,11 +174,37 @@ between them, sometimes followed by one or more skips back, is a pretty strong s block."* A press and a skip-burst are two observations of the same event, and a skip *back* after over-shooting brackets the end precisely. Treat them as one input stream. -### 2. Push verdicts to the server — NOT STARTED +### 2. Push verdicts to the server — DONE 2026-10-24 -Phone to server. Needs an endpoint and server-side storage. Design note: a verdict is about a -*range of a specific episode's audio*, so it is only meaningful for episodes whose bytes the -server itself served — gate on `audioFromServer`, the same invariant the refresh sweep uses. +`POST /api/labels`, stored in `state.json` under a top-level `labels` list. Deployed and +exercised live: accepts, de-duplicates a re-send, refuses without the token. + +**Both kinds of label go, not just verdicts.** A *mark* is a judgement on a break detection +found; a *report* is the notification button pointing at advertising it missed. They catch +opposite errors and the library needs both, so the wire format carries `source` to say which. + +**Identified by feed and guid**, not by either side's episode id. The phone never sees the +server's id, and the server's id belongs to a mirror that forgets an episode after eight. + +**Labels outlive the episode.** They sit beside the shows rather than on them, so an episode +leaving the eight-episode window does not take the corpus with it. That is the same reasoning as +the app's own no-foreign-key decision for `break_verdicts`. + +**A report's end is marked as guessed or measured.** `endMeasured` is only true once the listener +came back and trimmed it; otherwise the end is wherever the 25-second jump happened to land. A +signature cut to a guessed end would carry programme audio, so the library has to know which it +is holding. + +**The phone re-sends everything, every sweep.** No record of what arrived, deliberately: the +server replaces rather than accumulating, so a re-send is free and there is no sync state to get +wrong. A handful of taps does not need a protocol. It also means a label lost to a crash comes +back on the next refresh. + +**Accepting a label writes the state file at once.** Everything else is written at the end of a +poll cycle, which for 61 feeds is hours. A label is a tap made once and should not wait that long +on the wrong side of a kill. + +Gated on `audioFromServer`, as the design note required. ### 3. The index spike — DONE 2026-10-24. **It passes.** |
