diff --git a/HANDOFF.md b/HANDOFF.md index 1740cf1..e1ff9e7 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,22 +1,57 @@ -# HANDOFF — 2026-10-17 (PLANNING ONLY session; nothing pushed — push at the next milestone) +# HANDOFF — 2026-10-21 (HA lights session; the day's planned llamacasty work did NOT happen) ## At a glance -- **Branch** main, tracking `origin/main`. **origin/main = `931ab46`; HEAD = the tip commit - "HANDOFF: vv webcam plan, and drop the stale vertical-preview landmine"** — **5 ahead, 0 behind** - (nothing pushed; per the commit/push policy, push only when the creator says so). This file cannot - record its own commit's hash, so the tip is named by subject. - - The five local-only commits: `3cb29ea` (previous session's HANDOFF refresh), `a3a4681` - (per-element composite timing + scene dump), `84cbec2` (FramePumpTests thread-safe log sink), - `cdf82f6` (read the first instrumented take), the tip. Always check - `git log origin/main..HEAD` — never trust a handoff's own "0 ahead" claim. -- Working tree clean after the tip commit. -- **This session produced NO code, NO build, NO test run.** It specified the creator's **vv - (vertical 9:16) webcam feature** end to end; implementation has not started. The locked rules are - below — they are the deliverable, and they must land in `TASKS.md` when work is queued. - The session's later half moved **off-repo** to the officerFriendly/Pi-hole/PS5 "DNS errors" diagnosis — - findings and the pending creator decision are in `Open (operational)` below. +- **Branch** main, tracking `origin/main`. **origin/main = `931ab46`; HEAD = `d1e73a3`** — **6 ahead, 0 + behind** (nothing pushed; push only at sub-milestones/milestones, at the creator's word). This file + cannot record its own commit's hash, so the tip is named by subject. + - Local-only commits: `3cb29ea`, `a3a4681`, `84cbec2`, `cdf82f6`, `2a15be2`, `d1e73a3`, plus this + session's. Always check `git log origin/main..HEAD` — never trust a handoff's own "0 ahead" claim. +- **This session produced NO ytLive code, NO build, NO test run.** It was spent — entirely and + wastefully — on the creator's Home Assistant light alert system (off-repo, `192.168.50.145`). See + `MyMistakes.md` → 2026-10-21: the plan was one tweak to a verified-working script; I rewrote the + script twice, broke the alert path, and burned the day. The creator had to say so before I stopped. +- **The HA work landed OK in the end** (recipes + measurements now in `MyMistakes.md`). Records below so + the next session does not re-hunt. **llamacasty / the vv webcam Unit 1 is still NOT started.** -## vv webcam feature — locked rules (creator, 2026-10-17) +## HA light alert system — current, verified state (2026-10-21) +Five Tapo bulbs: `light.br1`, `light.br2`, `light.officeone`, `light.officetwo`, +`light.death_star_light`. Purpose: the creator is **deaf** — lights are the alert channel; the phone +(`notify.mobile_app_mis_lx9`) is secondary. **The iPhone is gone — never notify it.** + +| State | br1 / officeone | br2 / officetwo | Death Star | +|---|---|---|---| +| Idle | off | off | off | +| Pump running | off | **off** | **blue only** (creator directive) | +| Leak | warm-white 100% | purple | purple | +| Alarm | warm-white 100% | red | red | +| Doorbell | green, 8s | green, 8s | green, 8s | +| Doorbell during an alert | — | suppressed — | — | +| Clear | off | off | off | + +**Architecture:** `script.alerts_arm` / `alerts_clear` write only `input_text.light_alert` +(`none|leak|alarm|motion`, restart-surviving). **`script.alerts_render_lights` is the single writer of +the bulbs** — flat top-level `if`/`else` blocks (nested `if` and `choose:` both silently lit nothing; +do not "improve" the shape). Priority: an alert always beats pump status. + +**⛔ THE ENTITY-ID TRAP (cost this session hours):** the YAML key is `alerts_render` but the entity id is +**`script.alerts_render_lights`**. `script.turn_on` on a non-existent entity returns **HTTP 200 and does +nothing** — no error, no log. All callers now use the `_lights` id. Check this first on any "script does +nothing" symptom. + +**Pump status** is a *status*, not an alert (auto-clearing), and is keyed off +`sensor.water_pump_current_consumption` — **never** `switch.water_pump_2`, which was observed latched +`on` for hours at 0.0A draw and painted the bedroom blue at 5am. + +**HA files touched** (`/config`, root-owned → writes need `sudo`): `scripts.yaml`, `automations.yaml`, +`configuration.yaml` (added `input_text.light_alert` / `_prev`). Backups: `scripts.yaml.bak-alertbuild`, +`automations.yaml.bak-alertbuild`, `automations.yaml.bak-notify-20261020`, `configuration.yaml.bak-tplinkfix`. +Zombie entities deleted from the registry: `script.leak_strobe`, `script.doorbell_flash` (old one), +`automation.leak_strobe_notify_clear_restore`, `script.alerts_render_lights_2`. +**Leak sensor is healthy** (`binary_sensor.pump_leak_moisture` = off, battery 100, signal 3) — an earlier +"unavailable" claim was a bad read during a reload; `alert_leak_on` now also triggers on the latched +`sensor.pump_leak_last_water_leak_alert`. + +## vv webcam feature — locked rules (creator, 2026-10-17 — unchanged, still awaiting go-ahead) | mode | shape | size | position | |---|---|---|---| | 16:9 | as today | as today | as today | @@ -24,119 +59,90 @@ | **vv · Chat** | **rect only — no circle option** | normal, or enlarged to fill one area (607×540) | enlarged → top or bottom | | Starting / BRB / Ending | unchanged | unchanged | unchanged | -- **Placement is set by tap/click-drag with snap, exactly like the socials today**, plus manual entry - in properties. Creator's explicit precedent, not an inferred one. -- **vv keeps its own camera position, size and shape per scene** — creator-confirmed: switching back - to 16:9 restores the desktop layout exactly as it was. -- **No explicit borderless/no-background mode is needed**: round + border/bg options already let the - creator strip both (creator's ruling — this deletes that item from the original request). +- **Placement is set by tap/click-drag with snap, exactly like the socials today**, plus manual entry in + properties. **vv keeps its own camera position, size and shape per scene** — switching back to 16:9 + restores the desktop layout exactly. +- **No explicit borderless/no-background mode is needed** (round + border/bg options already allow it). - Creator's "square" means the rectangular view (the camera's own aspect), not a literal 1:1 box. -## What the code already gives us (established this session — do not re-hunt) +### What the code already gives us (do not re-hunt) - **vv = the active tier's centred band crop.** 1080p60-vertical: master band **x 656.25–1263.75 (607.5 wide), full height**, upscaled to 1080×1920 (`MainViewModel.Streaming.cs` `ApplyStreamQuality` - → `OutputRect*`). The band splits into **two 607×540 areas** (top/bottom) — the creator's "two mini - 16:9 views", each exactly 50% of the frame. -- **The Live webcam sits at x≈1425 → entirely outside the band.** That is the whole motivation: in vv - the camera is not misplaced, it is invisible. -- **Geometry only — no render-path change.** Preview (`Controls/PreviewPane.xaml` 144–230) and - compositor (`Services/Compositor/SceneCompositor.cs` 389–397, `DrawBorder`) both read the element's - own `X/Y/W/H` + `ClipShape`, so parking the camera needs no compositor or preview work. The - two-tile look *falls out of* the camera covering half the band — the capture element, chat box and - blit path stay untouched. -- **Round / border / background are independent**: `ClipShape.Round`; `HasBorder` = width > 0 AND a - valid 6-hex colour; `BackgroundEffect` = None/Remove/Blur. -- **Per-scene camera size policy already exists**: `MaxWebcamWidthFor/HeightFor` (Chat 1358×764, - others 960×540) + `ClampWebcamToBounds`. **A 607×540 tile sits inside both → the clamp needs no - change.** -- **Storage**: `WebcamSceneConfig` table; new columns go in `MigrateWebcamConfigTable()` as idempotent - `ALTER TABLE … ADD COLUMN` guarded on `PRAGMA table_info` — the established "additive, no version - bump" idiom (`RectWidth/RectHeight`, TASK 51's `BackgroundEffect` landed this way) — plus - `LayoutStore.Save.cs` INSERT and `LayoutStore.Load.cs` SELECT. -- **Existing per-element precedent for remembered geometry**: `RectWidth/RectHeight` + - `ToggleClipShape` (`Models/SceneElement.cs` 124–152) — the pattern for keeping the 16:9 layout - while vv owns its own. + → `OutputRect*`). The band splits into **two 607×540 areas** (top/bottom). +- **The Live webcam sits at x≈1425 → entirely outside the band** — in vv it is invisible. That is the + whole motivation. +- **Geometry only — no render-path change.** Preview (`Controls/PreviewPane.xaml` 144–230) and compositor + (`Services/Compositor/SceneCompositor.cs` 389–397) both read the element's own `X/Y/W/H` + `ClipShape`. +- **Round / border / background are independent:** `ClipShape.Round`; `HasBorder` = width > 0 AND valid + 6-hex colour; `BackgroundEffect` = None/Remove/Blur. +- **Per-scene camera size policy exists**: `MaxWebcamWidthFor/HeightFor` (Chat 1358×764, others 960×540) + + `ClampWebcamToBounds`. **A 607×540 tile sits inside both → no clamp change.** +- **Storage:** `WebcamSceneConfig` table; new columns via `MigrateWebcamConfigTable()` as idempotent + `ALTER TABLE … ADD COLUMN` guarded on `PRAGMA table_info` + `LayoutStore.Save.cs` INSERT and + `LayoutStore.Load.cs` SELECT. +- **Precedent for remembered geometry:** `RectWidth/RectHeight` + `ToggleClipShape` + (`Models/SceneElement.cs` 124–152). -## Units (each: ONE Good Dog integration test, own commit, memory in the same commit) -1. **vv camera layout** — stored separately per scene, resolved when the tier changes. Live: small - tile (circle or rect) snapped to one of six spots; drag like the socials + properties entry. +### Units (each: ONE Good Dog integration test, own commit, memory in the same commit) +1. **vv camera layout** — stored separately per scene, resolved when the tier changes. Live: small tile + (circle or rect) snapped to one of six spots; drag like the socials + properties entry. *Test:* with the vertical tier active, dragging the Live camera to top-right places it top-right inside the band; switching back to 16:9 restores the original layout. -2. **vv · Chat** — rect enforced with the circle option unavailable, plus enlarge-to-one-area - (607×540) snapping top or bottom. - *Test:* in Chat under the vertical tier, enlarge sets the full top area and the circle option is - not offered. - -## Corrections made this session -- **Withdrawn landmine (creator-confirmed):** the old line "Vertical-format regression (STALE, not - fixed): 1080p60-vertical selection no longer shrinks the capture border in the preview" was **never - verified**, and it cost this session a pointless question. The creator confirms vv *does* dim the two - bands astride the centre band and that this is expected/best practice. If the original symptom was - something else (the capture element's own border?), it is **unexplained, not known-broken** — do not - re-raise it as a dependency. -- The prev-session content (first instrumented take: judder did not reproduce, no element slow; probe - + recipe; the four local commits) is unchanged and lives in `ai.md` → - "✅ What the first instrumented take said". +2. **vv · Chat** — rect enforced with the circle option unavailable, plus enlarge-to-one-area (607×540) + snapping top or bottom. + *Test:* in Chat under the vertical tier, enlarge sets the full top area and the circle option is not + offered. ## Next step -- **Implement Unit 1 on the creator's go-ahead.** Nothing is queued in `TASKS.md` — the creator queues - work, and this plan lives here until then. Queue it in `TASKS.md` as part of the first Unit 1 commit. +- **Implement vv Unit 1 on the creator's go-ahead.** Nothing is queued in `TASKS.md` — the creator queues + work; this plan lives here until then. Queue it in `TASKS.md` as part of the first Unit 1 commit. +- **The creator's stated plan for "today" (2026-10-21) was llamacasty. It did not happen.** Confirm the + intended target before starting — do not assume. ## Open (operational) -- **verify.sh's known-failure whitelist is too loose (confirmed twice on 2026-10-16):** it passes when - ANY known failure appears, so a new failure rides along unnoticed — and when the ONLY failure is a - known flake (`LayerReorderPersistenceTests.RealMouseDrag_OnTheLayerList_PersistsTheReorder`, which - passes in isolation) it reports "NOT the known pre-existing pair". **Follow-up: require EVERY - failure line to be whitelisted**, and add `MasterLimiter_CapsTheLiveMix_OnThePipe` + +- **verify.sh's known-failure whitelist is too loose** (confirmed twice 2026-10-16): require EVERY failure + line to be whitelisted, and add `MasterLimiter_CapsTheLiveMix_OnThePipe` + `RealMouseDrag_OnTheLayerList_PersistsTheReorder` to the list. - **A pre-existing stash is still sitting there:** `stash@{0}` = "WIP on main: 0464593 Compositor: - fast-path opaque 1:1 when source fills canvas" (NOT this session's; do not drop it blindly). -- The judder reproduction take in the FAILING geometry (vertical 1080p60 first) is still outstanding — - **no fix until a take names the stage** (see `ai.md`; the `parts` line decides the latch hypothesis). + fast-path opaque 1:1 when source fills canvas" (NOT this session's; do not drop blindly). +- The judder reproduction take in the FAILING geometry (vertical 1080p60 first) is still outstanding — no + fix until a take names the stage. - ⛔ Sudo password rotation pending (user; then update both `CREDENTIALS.md` password lines). - TASK 56 secret scan before `gramps/LlamaCasty` goes public. -- TASK 55 disk hygiene (`startup.log` uncapped — 23MB and the new lines add to it every 5s). +- TASK 55 disk hygiene (`startup.log` uncapped — 23MB and growing every 5s). ## Tests - Last full run: **428/428 passed, 0 warnings** (2026-10-16, the gate run for `84cbec2`). **No run this - session (planning only).** + session (no ytLive code was touched).** - Known flaky-by-environment (all pass in isolation): `AudioPipelineTests.Mix_HonorsProviderGains…`, `MasterLimiter_CapsTheLiveMix_OnThePipe`, `LayerReorderPersistenceTests.RealMouseDrag…`, - `Round_Clip_Corner…`. **Read verify.sh's output — it can pass with an unlisted failure present, or - fail on a known flake (see above).** + `Round_Clip_Corner…`. ## Secrets / paths (do not re-hunt) - Layout DB: `%APPDATA%\ytLlive\ytLlive.db` (SQLite, full-rewrite per save). Auth: `%APPDATA%\ytLlive\ytLlive.auth` (DPAPI). Startup log: `%APPDATA%\ytLlive\startup.log` (23MB). - Recordings land in `C:\Users\gramp\Downloads\recordings\` (`ty--