Files
LlamaCasty/HANDOFF.md
T
gramps a814bcd502 fix(chat): stop painting what YouTube removed, and retire the local word filter
TASK 49 is retired (creator ruling): YouTube owns chat moderation. Its blocked-words filter and
hold-for-review run upstream of `liveChatMessages.list` — held messages are never returned
(https://stackoverflow.com/questions/74511524/) — so a second local list would duplicate a switch
the creator already owns, with a second set of false positives and a second support surface.

What we actually owed the platform, and had wrong:

- The parser added every item to the overlay. A deleted message arrives as a `tombstone` carrying
  no text at all ("it has since been deleted … only liveChatId, type and publishedAt are present" —
  https://developers.google.com/youtube/data/live/reference/rest/v3/liveChatMessages), so every
  deletion rendered as a BLANK chat row. `hasDisplayContent:false` messages and chat-mode events
  did the same.
- Deletion events (`messageDeletedEvent`/`messageRetractedEvent`/`userBannedEvent`) are documented
  but have not been delivered to clients for years (https://stackoverflow.com/questions/44346893/),
  so nothing is built on them; they are skipped if they ever arrive.
- Found while testing: Super Chat read `displayString`, but YouTube's field is `amountDisplayString`
  — every amount silently fell back to a recomposed string, which mangles non-dollar locales. The
  model's own comment said this was the reason the field exists.

Test: `ChatModerationParseTests` — tombstone, no-display-content, chat-mode events all produce no
row; a real Super Chat still parses its pre-rendered amount (constraint 4: reward fields are never
reinterpreted).

Docs: TASK 49 marked retired with the citations, the rule recorded in decisions.md, HANDOFF updated.
verify.sh: 550 passed, 0 failed, 0 warnings.
2026-11-05 08:39:46 -08:00

37 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HANDOFF — 2026-11-05 (TASK 64 — green/blue screen for clips)
## State
- `main`. TASK 21 complete (video file layer + its soundtrack). TASK 64 shipped through slice E:
a clip with a green or blue backdrop is **offered** a key on add ("Looks like a green screen —
Remove it"), accepting it keys the background **inside the decode pipe** (bundled ffmpeg
`colorkey`/`despill`), with Amount/Softness/Fringe in the panel and the settings persisted.
Sessions are keyed by **path + look**, so identical looks share one decoder.
- Detection stays silent on lawns/pitches (confidence = coverage × hue tightness) and ignores
letterbox bars. It never acts on its own.
- Slice F shipped too: **App Settings → Video clips → "Auto Green/Blue Screen"** (off by default,
high confidence only, and the panel states when a key was automatic) and **alert clips** key through
the same settings block (one alert box per layout).
- Tests: `ChromaKeyDetectorTests` + `ChromaKeyApplyTests` (pipe asks ffmpeg to key; offer → accept →
keyed session feeds the resolver; survives save; auto-apply; alert clip keyed). App build 0 warnings.
- **TASK 49 retired (creator ruling):** YouTube owns chat moderation — blocked words and hold-for-review
run before the API. What we owed it was not a wordlist but not painting what YouTube removed: the chat
parser now skips `tombstone` (a deleted message's text is never sent) and `hasDisplayContent:false`.
Same commit fixed a live bug: Super Chat read `displayString` instead of `amountDisplayString`, so every
amount fell back to a recomposed string.
## Next action
- TASK 64 is complete. Next queued: TASK 49 (chat profanity filter). Day 3's TASK 32/33 resilience slices remain outstanding —
32·4 (fragmented MP4) is the smallest.
- Do not push absent a checkpoint request.
## Landmines
- `LayerReorderPersistenceTests.RealMouseDrag_OnTheLayerList_PersistsTheReorder` injects physical
mouse input. Do not run it while the desktop is in use.
- Integration tests constructing `MainWindow` must set a temporary `LayoutPathOverride` and clear it in `finally`.
- Media sessions are keyed by **path + look** (`MainViewModel.MediaSessionKey`); never acquire by raw
path, and release through `ReleaseMediaIfUnused`.
- Bundled FFmpeg stays outside the single-file exe (`ExcludeFromSingleFile="true"`).