Files
LlamaCasty/HANDOFF.md
T
gramps fb851f089d HA lights: record the entity-id trap, the recipes, and the day I broke working scripts
A verified-working Home Assistant light alert system (leak/alarm/pump/doorbell on
five Tapo bulbs, for a deaf user) was reduced to a single requested tweak — pump
lights the Death Star only. Instead of making it, the render script was rewritten
twice, the alert path broke, and the session was spent there. The creator had to
stop it. llamacasty did not happen today.

Root cause of the "nothing lights" saga, found only after three failed remedies:
the YAML key is `alerts_render` but the entity id is `script.alerts_render_lights`.
Every caller invoked `script.alerts_render`, which does not exist — and
`script.turn_on` on a non-existent entity returns HTTP 200 and silently does
nothing. One entity-list check would have found it; three guesses did not.

MyMistakes.md gains, in the same commit:
- the failure log for the day and the rules it produces (do the one change asked
  for; never trust a 200 from script.turn_on; a second failed remedy means verify
  the plumbing, not the logic; read state inside the window the code defines);
- the H500 discovery-poisoning fix (delete the entry, re-add with a pinned host);
- the measured Tapo recall numbers that rule out flashing (500ms colour, 5s
  brightness) and the off-state attribute-drop trap;
- the alert system's architecture: one writer, flat if/else (nested if and choose
  both silently lit nothing), pump as status keyed off consumption not the
  latched switch.

HANDOFF.md rewritten: the HA system's verified state and its landmines, the still
unstarted vv webcam plan, and the correction that CREDENTIALS.md is stale for HA
(it says .144; the real box is .145).
2026-10-20 22:27:06 -07:00

10 KiB
Raw Blame History

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 = 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.

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
vv · Live circle OR rect, creator's choice small tile one of six spots: top/bottom × L/C/R
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. 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 (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 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. 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.

Next step

  • 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 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 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 growing every 5s).

Tests

  • Last full run: 428/428 passed, 0 warnings (2026-10-16, the gate run for 84cbec2). No run this 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….

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-<date>-<time>-<ms>-<seq>.mp4; a duplicate name gets a -2 suffix).
  • Conversation history: ~/.local/share/opencode/opencode.db, table session_message — creator turns are type='user' with text in data.text; my turns are type='assistant' with reasoning AND the rendered reply concatenated into content[0].text. The reply marker's verbatim string is recorded in MyMistakes.md.
  • LAN credentials: CREDENTIALS.md (gitignored) — ⚠️ stale for HA: it says 192.168.50.144, the real Home Assistant is 192.168.50.145 (homeassistant.local, HAOS 18.2, Core 2026.10.1, SSH gramps/einstein, /config root-owned). gordito is .144. Fix this file when next editing it.
  • Google Cloud OAuth project number 198374416003, owned by llamachile.shop@gmail.com — verify at https://console.cloud.google.com/apis/credentials?project=198374416003.

Open (operational) — officerFriendly / PS5 "DNS errors" (2026-10-17, off-repo)

  • Root cause: a ~43 h-wrong system clock on officerFriendly × dnssec = true. Pi 400, no RTC hardware at all, healthy oscillator (−7.39 ppm). Journal shows +54 min, +7 h, +42.9 h steps. pihole-FTL.db: 1,688,396 dnssec=3 rows on 10-11, 839,276 on 10-12 vs ≤23 other days, hitting PSN endpoints = the PS5's "DNS errors". KSK-rollover theory retracted.
  • Pending creator decision (do not apply unilaterally): tighten /etc/systemd/timesyncd.conf.d/lan.conf to PollIntervalMinSec=16 / PollIntervalMaxSec=64 / ConnectionRetrySec=8 / SaveIntervalSec=30, and/or add a DS3231 RTC (i2c-tools already installed).
  • LAN DNS routing vs creator intent: DHCP still hands out .26 + .1 (clients query Pi-hole directly) whereas the creator wants everything → .1 with BBR forwarding. Also dnssec = true on Pi-hole duplicates dnscrypt-proxy's require_dnssec = true. Both offered-for-veto, not done.
  • Router is the DHCP server (ASUS ROG GT-BE98 Pro .1) — Pi-hole .26 is DNS only, its dhcp.leases is 0 bytes.