Files
LlamaCasty/HANDOFF.md
T
gramps 769c616706 Preview: promote selected layer for hit testing
Temporarily raise the selected preview item and prioritize it in the custom hit test without changing scene order. Refresh integration-test expectations for Brand logo layers and explicit thumbnail assets.

WPF references: https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.panel.zindex?view=windowsdesktop-10.0 https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/hit-testing-in-the-visual-layer
2026-10-28 13:09:15 -07:00

35 KiB
Raw Blame History

HANDOFF — 2026-10-28 (selected-layer preview stacking; suite green)

Current state

  • Branch main; origin/main remains at 7ae30d4. The five feature commits since that point are 90cd039 (fade starts from outgoing picture), f67a263 (transition picker), b86b6bb (Wipe), 841c905 (brand logo layer), and 7da2872 (preview and program transitions). They are not pushed; no push was requested.
  • Four UI-redesign commits already on origin/main were missing from the older handoff: 24aca7d moved the scene strip above the preview and removed the default CRT/on-air image seeds; 3239808 added the Scene Layers header/count and layer icons plus scene-card names, hotkeys, and PROGRAM badge; a8814b4 added the explicit EDIT toggle and fixed the scene-card/left-column sizing; 7ae30d4 moved readouts/resolution into the top-left cell, added the Socials rail drawer, and restored webcam/chat border controls and vertical 1080p30. b7ab169 added DESIGN.md with exploratory color/type tokens; it explicitly is not a layout spec or a theme implementation. ai.md and Controls/index.md now describe the landed surface. No new task was added to the queue.
  • Shipped in those commits: type/duration picker persisted with the layout; CPU left-to-right Wipe; one locked Brand logo image layer per scene; preview transition animation in every mode; program transitions while recording or streaming. The 7da2872 commit omitted a memory update; TASKS.md and ai.md now reflect it.
  • Current work unit: when a draggable element is selected from the layer list, PreviewPane temporarily raises its item container and gives it priority in the custom preview hit test. On deselection, normal preview stacking returns; the scene collection order and saved/program z-order never change. SelectedLayerPreviewHitTestingTests verifies the overlapping Brand logo/webcam visual hit, custom hit priority, and deselection restore.
  • The six prior suite failures are resolved in their tests, not by reverting current behavior: LayerReorder now accounts for the permanent Brand logo after Background; BorderColorPicker validates every palette picker and scopes its rendered-widget lookup to the visible webcam control; both thumbnail cases persist explicit tile assets instead of relying on removed default seed files; SourceNaming only considers user-created Text overlays; ZoomBox locates its placeholder by type, not a list index changed by Brand logo.
  • The worktree already had three uncommitted user edits before this docs sync; they are preserved: Controls/OverlayHost.xaml groups App Settings into Recordings, Brand logo, Preview, and Scene transition sections with compact controls; Controls/TopBar.xaml wires right-click on the gear; Controls/TopBar.xaml.cs opens App Settings directly on right-click while left-click keeps the menu. These are active UX-redesign work, not part of the selected-layer fix. On-screen verification is still pending.
  • This work unit is committed locally, not pushed. The three pre-existing user edits above remain uncommitted and untouched.
  • Next: continue the creator's UX redesign and verify the current App Settings/gear changes, transitions, and Brand logo on-screen. The earlier vertical-webcam hands-on check is also still pending unless the creator confirms it was completed. Move's persistent-layer behavior and Cube remain queued; distribution remains deferred until near v1.
  • Verification state: verify.sh passed: clean build with 0 warnings, 444/444 tests passed, and scope check passed. The new selected-layer integration test also passes by itself.
  • Follow-up, not fixed here: ytLive.csproj's GenerateBuildStamp comment still describes a commit-count-based +1 per commit counter, but the target now reads/writes local BuildCounter.txt and increments it per build. ai.md records the code's current behavior; correct the stale source comment in a separately scoped change. ViewModels/MainViewModel.Socials.cs also still calls the Socials surface a modal dialog in its method comment; the committed UI is now a preview-rail drawer. Correct that source comment separately if the file is next in scope. The new deterministic WPF hit-test recipe is in MyMistakes.md; the final commit cites its Microsoft reference.
  • WPF stacking reference: Panel.ZIndex governs preview container order. The code also prioritizes the selected element in HitElementAt, because the custom hit test does not consult WPF's visual z-order. The deterministic test recipe and hit-testing reference are recorded in MyMistakes.md; cite that Microsoft reference in the commit.

Historical notes (retained reference; current checkout state is above)

At a glance (2026-10-26 docs session)

  • ai.md is being split into docs/ai/*.md (user-approved: verbatim move, staged units, "ai.md only"). Three units landed as separate commits, docs only, not pushed: 804b1d2 (frame pipeline: cadence/timing/budget/compositor/pump), 096bf6d (capture: backdrop/webcam/background effects/vertical tier), a4dfca6 (output: ffmpeg/encoder/recording/audio). Each move is byte-identical in the new file; ai.md keeps a short stub with the load-bearing invariants + a link. docs/ai/index.md routes. ai.md is now 1,289 lines (~32k tokens), down from 2,702 (~64k) — more than half the mandatory-read cost is gone.
  • Also landed (docs only, not pushed): ef60f1f — distribution & packaging deferred until near v1 (creator ruling 2026-10-26); see "Next step" below for the still-open route contradiction.
  • Remaining split candidates in ai.md (not yet moved — smaller, more interleaved with law that should stay): Architecture's "Social bar" (46) + "Toast notifications" (24) + "Licensing — do not violate" (60); "YouTube Live API — design constraints" incl. "Native events & alerts" (349 total, 99 of it alerts); "Monetization" (136); "Windows packaging & distribution" (135, frozen per the deferral above). None of these is urgent — pick back up only if the user asks to continue the split.
  • Scope-check passed on all three commits; no source touched this session.

Earlier detailed state (2026-10-22) — properties-panel asks shipped, incl. TASK 63, and pushed; vv webcam Units 1+2 state below

At a glance

  • Branch main, tracking origin/main. The six-commit properties-panel batch is PUSHED (2026-10-22, as a sub-milestone): TASK 58 the theme sweep, TASK 59 the properties hierarchy, TASK 60 the colour names, a docs commit, TASK 61+62 the geometry field widths and the colour name beside the hex, and TASK 63 the border-colour picker as the app's own drop-down — the creator's properties-panel asks, done in one batch. origin/main is now 987fdda.
    • The vv feature (Units 1+2) was pushed at its close (2026-10-21 — the creator approved the Unit 1 push after testing it, and the completed feature is a milestone).
    • The push path changed: origin is now https://llgit.llamachile.tube/gramps/LlamaCasty.git (HTTPS + the credential helper /home/gramps/bin/gitea-credential, which reads the password from the gitignored CREDENTIALS.md; plain git push works). The old SSH remote was broken twice over: the repo was renamed gramps/ytLlive → gramps/LlamaCasty, and llgit:2214 refuses the publickey of this machine's key even though it IS registered (account key id 6 "Corsair VSC"). Ask the Gitea REST API, don't do key archaeology — recipe in MyMistakes.md → 2026-10-21.
  • This session shipped vv webcam Units 1+2 (the vertical 9:16 tier keeps its OWN camera placement per scene; 16:9 restores the desktop layout exactly; the Chat scene in vv is rect-only and can be enlarged to fill a whole 607×540 area). Code + memory in ONE commit each; the ONE Good Dog tests are ytLive.Tests/VerticalWebcamLayoutTests.cs (Unit 1) and ytLive.Tests/VerticalChatCameraLayoutTests.cs (Unit 2). Only the creator's hands-on check is left — see the vv section.
  • TASK 58 — the properties panel now wears the theme (shipped 2026-10-21). The creator's "why is the drop-down not in the same style as the others?" was a real defect: those drop-downs (and every check box, and every properties field) had been hand-painted with a Background/ Foreground instead of a style, so WPF drew the light system template on top of the dark panel. Now: ComboBox → YtComboBox, CheckBox → YtCheckBox (new), properties fields → YtTextBoxCompact (new, BasedOn YtTextBox). Guard: ytLive.Tests/PropertiesStyleTests.cs.
  • TASK 59 — the properties panel is a hierarchy (shipped 2026-10-21). A title owns its content and the content is indented one level (10px): Shape (new title) over the Mirror switch and the shape choice, the drag hint indented under that row, Geometry / Border Color / Border Thickness as titles with their fields indented, Background's Remove + Blur indented, and Strength one level deeper under Blur. The shape became a CHOICE: Rect | Circle as two segment options with Rect selected by default (the old single button showed the next action, "Round"). The mutual exclusion lives in the model (IsRectShape/IsRoundShape on SceneElement) — a WPF RadioButton group would kill the bindings. Guard: ytLive.Tests/PropertiesHierarchyTests.cs.
  • TASK 60 — the border-colour drop-down names every colour (shipped 2026-10-21). The creator: "the #hex values are good, but add a corresponding color name/label next to the value" — each row now reads #e94560 Crimson (the name dimmed, the tooltip "Crimson (#e94560)"). The 14 colours moved out of the click handler into Models/BorderColorPalette.cs (NamedColor(Hex, Name) + NameOf(hex)), so the list is testable and extensible. Guard: ytLive.Tests/BorderColorPaletteTests.cs.
  • TASK 61 + 62 — the geometry fields and the border-colour field (shipped 2026-10-21).
    • 61: the X/Y/W/H fields share ONE fixed width (44px — the largest geometry value, 1920, plus a sign) and their rows set LastChildFill="False", so Y/H no longer stretch to fill the row while X/W sized themselves to their text. Guard: ytLive.Tests/GeometryFieldWidthTests.cs (it MEASURES the widest value with WPF's FormattedText — measure, don't guess).
    • 62: the border-colour field shows the palette's name beside the hex (SceneElement.BorderColorName, empty for a custom hex), and the hex field keeps a fixed width so the name stays next to the hex. The field stays editable (a custom hex can still be typed). Guard: ytLive.Tests/BorderColorNameTests.cs.
  • TASK 63 - the border-colour picker IS the app's drop-down (shipped 2026-10-21; popup click deselection fixed 2026-10-22). The creator: "why does the drop down under the web cam properties not show the same style for the border color drop down list box?" and "we established look-and-feel standards. And yet you keep ignoring these and I'm wondering why." Root cause of the miss: the TASK 58 sweep looked for control types (ComboBox/CheckBox/TextBox) without a theme style - and the border picker was NONE of those: it was a ... Button whose Click handler built a ContextMenu in code. It was never in the sweep's scope, and PropertiesStyleTests.cs (a type-based guard) could not see it either. Now: the picker is a YtComboBox bound to the palette (SelectedElement.BorderColorOptions / BorderColorEntry), the closed box shows the swatch + the colour's NAME, the rows show swatch + hex + name, the hex field stays for a custom colour, the swatch is painted by the theme's HexToBrush converter, and the hand-built menu + WebcamBorderColorPicker_Click are gone. The closed box != the rows only through Helpers/ClosedBoxTemplateSelector.cs (WPF copies ItemTemplate into the read-only SelectionBoxItemTemplate; the selector is told them apart by the ContentPresenter's templated parent - ComboBox = closed box, ComboBoxItem = a row). 2026-10-22 creator bug fix: clicking a colour in the open ComboBox popup registered as an exit from the properties listing because LeftPanel.IsDescendantOf used child is Visual ? VisualTreeHelper.GetParent(child) : LogicalTreeHelper.GetParent(child) — at PopupRoot (which IS a Visual), VisualTreeHelper.GetParent returns null, so IsDescendantOf stopped without crossing PopupRoot's logical parent (PART_Popup → ComboBox → ElementsScrollViewer), and MainWindow.Window_PreviewMouseLeftButtonDown cleared SelectedElement = null. Fixed by falling back to LogicalTreeHelper.GetParent / TemplatedParent when VisualTreeHelper.GetParent returns null. Guard: ytLive.Tests/BorderColorPickerTests.cs (model + panel + the real widget, including LeftPanel.IsClickInside on an open popup row and clicking a row to change BorderColor). The TASK 60 guard (BorderColorPaletteTests) was updated to guard the new wiring (the drop-down is bound to the palette; no second list of colours anywhere).
  • TASK 55 slice 1 — the log is capped (shipped 2026-10-22). startup.log was uncapped (23 MB and growing every few seconds — ffmpeg logs every stderr line). Now it rolls to startup.1.log at 5 MB (one rolled copy kept), so the growth is bounded. The policy is Helpers/LogRotation.cs (a pure function over a path — AppLog's 156-call-site surface is unchanged; the seams are two internal properties). Guard: ytLive.Tests/AppLogRotationTests.cs. Slices 2 (temp alert-clip cleanup) and 3 (low-disk guard before recording) are still open.
  • TASK 48 slice 2 — the app PACKS as a Store MSIX (shipped 2026-10-22). Packaging/Package.appxmanifest (full trust: Windows.FullTrustApplication + uap10:TrustLevel=mediumIL + uap10:RuntimeBehavior=packagedClassicApp + rescap runFullTrust, plus webcam/microphone DeviceCapabilitys, x64, en-US only) + Packaging/Assets/ (four logo tiles generated from the app's own artwork by scripts/make-store-logos.py) + scripts/package-msix.sh (publish Release -r win-x64 --self-contained → stage → makeappx pack, optional MSIX_PFX signing). First real package built: artifacts/LlamaCasty.msix, 159 MB, 509 files, Package creation succeeded (artifacts/ is gitignored). Guard: StorePackagingTests.The_package_manifest_declares_full_trust_camera_and_microphone. ⚠️ Before submission the manifest's Identity/@Publisher and PublisherDisplayName must be set to the exact values Partner Center shows — a mismatch is a rejection.
  • TASK 48 slice 3 — the self-updater is gone (shipped 2026-10-22). The Store route (creator ruling 2026-09-27) means the Store updates the app, so the Velopack package + bootstrap were deleted (ytLive.csproj, App.xaml.cs) — a compliance action, not cleanup: the updater downloaded and executed, which Store policy 10.2.2 does not permit. The DO update-URL droplet dies with it. Guard: ytLive.Tests/StorePackagingTests.cs (no updater package, no updater API in any app source file). The app was smoke-tested after the removal: MainWindow loaded, no exceptions. Still open on TASK 48: slice 2 (the Package.appxmanifest + packaging project), slice 6 (the full-trust recording invariant comment), slice 7 (disqualifier re-check), slice 8 (the pre-submission gates) — and slices 4/5 are the creator's (Certification Kit, Partner Center listing, the demo account).
  • The previous session (HA lights) produced NO ytLive code — it was spent 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; the script was rewritten twice, the alert path broke, and the day was burned. The HA work landed OK in the end (recipes + measurements now in MyMistakes.md). Records below so the next session does not re-hunt.

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) — Units 1+2 shipped 2026-10-21

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

What shipped in Unit 1 (2026-10-21) — do not re-hunt

  • Geometry only — NO render-path change. The tier switch swaps the element's LIVE geometry; the preview and the compositor read X/Y/W/H + ClipShape exactly as before.
  • Models/VerticalCameraLayout.cs (new): the pure math — band x 656.25, w 607.5, h 1080; two 607×540 areas; six spots; default tile 270×152 master px (= 480×270 in the 1080×1920 output), bottom-right spot; inset 32 master px.
  • Models/WebcamSceneConfig.cs: the vertical placement is persisted in seven additive columns (VerticalX/Y/Width/Height/VerticalClipShape/VerticalRectWidth/VerticalRectHeight, NULL = "this scene has no vertical placement yet"); the 16:9 layout stays in the old columns and is parked in the transient Landscape* fields while the vertical tier is live. BeginVerticalLayout / EndVerticalLayout / CommitLiveLayoutToVertical do the swap.
  • Models/SceneElement.cs: X/Y/Width/Height are now virtual so the webcam clamps EVERY write (drag, resize, typed fields) into the band — outside the band = invisible in vv.
  • ViewModels/MainViewModel.Webcam.cs: IsVerticalTier/VerticalBand + ResolveVerticalCameraLayouts (the tier swap; the Live scene gets its tile automatically on the first vertical switch) + MoveWebcamInVerticalTier/SnapWebcamInVerticalTier (the six-spot snap, by the tile's CENTRE). MainViewModel.Streaming.cs ApplyStreamQuality is the tier-change hook.
  • Controls/LeftPanel.xaml: the webcam properties gained a Geometry section (X/Y/W/H) bound to the live placement, gated on the VM's IsWebcamSelected (NOT SelectedElement.IsWebcam — the TASK 51 test finds that panel by binding text and would match twice).
  • Controls/PreviewPane.xaml.cs: dragging/resizing a webcam under the vertical tier routes through the VM's snap instead of free-floating over the master.
  • Test seam: the drag lives in a VM method, so the test drives it without synthesising mouse input.

What shipped in Unit 2 (the Chat scene, 2026-10-21) — do not re-hunt

  • Rect only, and the lock is on the MODEL, not the UI. WebcamSceneConfig.VerticalShapeLocked (set per scene by the VM) overrides the ClipShape property → a locked camera cannot become Round by any writer (the toggle, the Shape button, the placement swap). SceneElement.ClipShape and SceneElement.ToggleClipShape() are virtual for this. The lock is cleared before the 16:9 layout comes back, so the desktop shape is restored.
  • The circle is not OFFERED: MainViewModel.CanToggleClipShape is false for a Chat camera in the vertical tier → the Shape button in the webcam's properties disappears (not just disabled). MainViewModel.cs raises it on the selection change; MainViewModel.Streaming.cs on the tier change.
  • Two sizes, snapped by the nearer one: VerticalCameraLayout.SizeFor(band, requestedWidth) → the small tile (270×152) or one whole area (607.5×540). The resize handle therefore has two detents instead of any size in between.
  • An enlarged camera fills the area its centre is in — top or bottom (VerticalCameraLayout.AreaFor).
  • The Chat camera is auto-tiled like the Live one when the vertical tier is picked (otherwise the vertical chat stream has no camera at all). ResolveVerticalCameraLayout now auto-tiles Live and Chat; Starting/BRB/Ending keep their 16:9 placement.
  • The preview's resize routes through MainViewModel.ResizeWebcamInVerticalTier (the Chat camera's discrete size + the snap); the drag routes through MoveWebcamInVerticalTier (assign → clamp → snap, so the enlarged camera can be dragged from the top area to the bottom one).
  • Test: ytLive.Tests/VerticalChatCameraLayoutTests.cs — PASSES (in Chat under the vertical tier, enlarging fills the full top area and the circle option is not offered).

Units (each: ONE Good Dog integration test, own commit, memory in the same commit)

  1. ✅ vv camera layout (Unit 1) — shipped 2026-10-21. 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: ytLive.Tests/VerticalWebcamLayoutTests.cs — 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 exactly; both placements survive a save + reload. PASSES.
  2. ✅ vv · Chat (Unit 2) — shipped 2026-10-21. Rect enforced with the circle option unavailable, plus enlarge-to-one-area (607×540) filling the top or the bottom area by where the camera is. Test: ytLive.Tests/VerticalChatCameraLayoutTests.cs — in Chat under the vertical tier, enlarge sets the full top area and the circle option is not offered. PASSES.

Historical next step (2026-10-22; superseded by Current state above)

  • ✅ TASK 63 + popup-click fix verified by creator (2026-10-22) — clicking a colour in the Border Color YtComboBox dropdown now stays inside LeftPanel (IsDescendantOf crosses PopupRoot → PART_Popup via LogicalTreeHelper.GetParent), updates the webcam border colour, and does not exit the properties listing.
  • Creator check (needs the creator's hands) — the last piece of the vv feature: switch the resolution dropdown to "Vertical 1080p60", confirm the Live camera tile lands inside the band and the Circle option (TASK 59 turned the Shape button into a Rect | Circle choice) turns the tile into a circle there, open the Chat scene and confirm the Circle option is gone (rect only) and that dragging the tile up and enlarging it fills a whole 607×540 area, then switch back and confirm the desktop layout is untouched. The unit tests cover the geometry, not the eyeball.
  • ⏸ Distribution & packaging is DEFERRED (creator ruling 2026-10-26) — do not pick it up until we are close to v1. The creator's reasons: the remaining programming tasks are far from release, and a complete UX redesign is about to start — so packaging/signing/updater/route decisions would chase scope that is about to move. Nothing distribution-related is urgent now. Frozen: TASK 48 items 6-8, the signing decision, the updater choice, and the route contradiction (ai.md says Store route DEAD → direct + Steam; TASKS.md/TASKS/task-48-…/this file still say Store MSIX + Store IAP). That contradiction is to be settled in ONE distribution sweep at the revisit, not patched piecemeal in the meantime. Detail: TASKS.md → Open items → the ⏸ TASK 48 bullet.
  • Nothing else is queued for llamacasty — the creator queues work.

Open (operational)

  • Follow-up (not fixed — out of scope for TASK 61): the web source block's geometry rows in Controls/LeftPanel.xaml (the SelectedElement.IsWebSource panel, ~lines 387-402) have the identical shape and the identical defect as the webcam's did — the Y/H fields stretch to fill the row. Same one-line-per-field fix as TASK 61, when the creator wants it.
  • ✅ FIXED in TASK 63: the border-colour swatches now carry a 1px BorderBrush="#2a3a5e", so the black (#000000) and dark swatches are visible against the dark menu (#16213e).
  • Follow-up spotted while doing TASK 63 (not fixed — out of scope for that change): the theme has no implicit Button style, so every plain <Button> in the app still renders with the light WPF system template (Controls/LeftPanel.xaml ×7, Controls/CameraPickerDialog.xaml ×2). The border picker's ... button was one of them and is gone; the rest are still there. A theme-level implicit Button style would fix them all at once — that is a creator-queued task, not a silent edit.
  • GOG Galaxy launcher shows "offline" (2026-10-21) — GOG's own overnight outage, NOT Windows. GOG put www.gog.com behind a maintenance page (503) and their Fastly services for auth.gog.com / api.gog.com / remote-config.gog.com return 500 "Fastly error: unknown domain"; the page itself says "Galaxy Launcher will also be down." Window: 00:00–08:11 local on 2026-10-21 — the Wayback snapshot of www.gog.com/en/ at 06:56 UTC is HTTP 200 with the full live storefront. status.gog.com is NXDOMAIN globally. Local exoneration chain: genuine GOG sp. z o.o → DigiCert cert (no MITM), local DNS == Google's authoritative answers, real Fastly POP headers, and GOG's own non-Fastly servers still answering. Nothing to fix locally — wait for GOG. Galaxy's logs (incl. the rotated ones) show no API-status failures between Oct 10 and Oct 20. Diagnosis recipe + the webfetch-is-not-an- independent-egress trap: MyMistakes.md → 2026-10-21 GOG Galaxy "offline". Galaxy 2.0 logs live in C:\ProgramData\GOG.com\Galaxy\logs\ (NOT %LOCALAPPDATA%). ⚠️ that folder also holds a 2.7 GB cef.log (since Jul 13) — disk hygiene, see TASK 55.
  • 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 — DONE 2026-10-22, CLEAN. 432 reachable commits (all branches, 35 tags, reflog, stash) + 63 dangling commits + the worktree: 0 real secrets. 4 rule hits, all false positives (README.md:79 = the your-client-secret doc placeholder; TokenStoreTests.cs:22 = a 9-char test dummy). CREDENTIALS.md/MARCOM.md/ Helpers/OAuthCredentials.cs were never tracked. ⚠️ the repo was already public (anonymous GET → 200, API private = false) when the scan ran — the gate came late, but nothing leaked. Method + verdict: TASKS/task-56-secret-scan.md.
  • TASK 55 disk hygiene: slice 1 (log rotation) shipped 2026-10-22 — see the At-a-glance bullet. Slices 2 (temp alert-clip cleanup) + 3 (low-disk guard before recording) are open. (The GOG Galaxy cef.log at 2.7 GB is NOT ours.)

Tests

  • Last full run: 438/438 passed, 0 warnings (2026-10-22 — after TASK 48 slice 2's manifest guard; the run before was 437/437 after slice 3's StorePackagingTests, then 436/436 after TASK 55 slice 1's AppLogRotationTests and 435/435 after TASK 63). The one failure seen earlier in the session was LayerReorderPersistenceTests.RealMouseDrag_OnTheLayerList_PersistsTheReorder, which passes in isolation (re-run: 3/3) — the known real-mouse flake, not a regression.
  • Known flaky-by-environment (all pass in isolation): AudioPipelineTests.Mix_HonorsProviderGains…, MasterLimiter_CapsTheLiveMix_OnThePipe, LayerReorderPersistenceTests.RealMouseDrag…, Round_Clip_Corner….
    • ⚠️ LayerReorderPersistenceTests.RealMouseDrag_OnTheLayerList_PersistsTheReorder is NOT "passes in isolation" any more. During this session it FAILED ALONE on a clean tree at 58b9a7d (the vv work stashed) with the same "Expected: ImgC / Actual: ImgA" — i.e. it is an environment/real-mouse flake, not a regression from the vv work — and it PASSES in the full-suite run (429/429). Treat it as environment-dependent, and don't chase it as a regression without stashing first.

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 — now CAPPED at 5 MB with one rolled copy, TASK 55).
  • 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.