HANDOFF: vv webcam plan locked; drop the unverified vertical-preview landmine

Planning-only session: no code, no build, no test run. The creator's vv
(9:16) webcam feature is now specified, and HANDOFF carries the locked
rules plus the code facts needed to build it without re-hunting:

- vv Live: small tile, circle OR rect (creator's choice), snapped to one
  of six spots (top/bottom x L/C/R). vv Chat: rect only, plus enlarge to
  fill one 607x540 area (exactly 50% of the frame), top or bottom.
  16:9 and Starting/BRB/Ending unchanged.
- Placement by tap/click-drag with snap, like the socials, plus manual
  entry in properties. vv keeps its own camera layout per scene, so the
  16:9 layout survives switching modes (creator-confirmed).
- Geometry only: preview and compositor both read the element's own
  X/Y/W/H + ClipShape, so the two-tile look falls out of the camera
  covering half the band - no capture, chat-box or blit-path change. The
  existing per-scene clamp already permits 607x540.

Withdraws the HANDOFF landmine "vertical-format regression ... no longer
shrinks the capture border in the preview": never verified, and wrong as
stated - the creator confirms vv dims the two bands astride the centre
band. It cost this session a pointless question.

MyMistakes.md records the session-history search recipe (the creator's
turns live in session_message, NOT part - a hit in part can be my own
text echoing the phrase) and the ask-don't-check lesson plus the
creator's standing reply-format directives.
This commit is contained in:
2026-10-17 09:02:59 -07:00
parent cdf82f688d
commit 2a15be21bd
2 changed files with 139 additions and 54 deletions
+85 -54
View File
@@ -1,53 +1,84 @@
# HANDOFF — 2026-10-16 (work committed locally; NOT pushed — push at the next milestone)
# HANDOFF — 2026-10-17 (PLANNING ONLY session; nothing pushed — push at the next milestone)
## At a glance
- **Branch** main, tracking `origin/main`. **origin/main = `931ab46`; HEAD = the tip commit
"Read the first instrumented take: the judder did not reproduce, no element is slow"** —
**4 ahead, 0 behind** (nothing pushed this session; per the commit/push policy, push only when the
creator says so). This file cannot record its own commit's hash — amending a commit changes that
hash — so the tip is named by subject.
- The four local-only commits: `3cb29ea` (**previous session's HANDOFF refresh — the old handoff
claimed it was pushed; it never was**), `a3a4681` (per-element composite timing + scene dump),
`84cbec2` (FramePumpTests thread-safe log sink), the tip. Always check
`git log origin/main..HEAD` — never a handoff's own "0 ahead" claim.
"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.
- **The creator's first take of the instrumented build happened today** (18:40–18:44, Release
recording). **The judder did NOT reproduce and no element is slow** — full reading in `ai.md` →
"✅ What the first instrumented take said". Nothing is queued to fix from it.
- **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.
## This session (2 commits — both unpushed)
1. **`84cbec2` — FramePumpTests race fix (own commit, creator-approved).** A full-suite failure
(`Stats_ReportRealRendersAndDistinctWebcamFrames…`, "Collection was modified") was a **test-side
data race**: a plain `List<string>` enumerated by the test while the pump logged from its own
thread. Fixed with `ConcurrentBag<string>`. **Proof: full suite 428/428 passed, 0 warnings.**
Lesson recorded in `MyMistakes.md` → "known failure label" (2nd instance).
2. **The reading (this is the tip commit).** Take `ty-20261016-1841-559-0002.mp4` (174.5s, Release
`e95154d9`, 1920×1080 1:1, recording): **60 composites/s, avg render 1.0–1.1ms, biggest element =
webcam 0.4ms**, backdrop 0.2ms, other four under the 0.1ms floor, `cache 151R/150H`, webcam 30.0/s
at the resolver (longest gap 50ms), and the FILE holds **29.6 distinct webcam images/s with 82% of
images held exactly 2 frames**. No culprit element exists in this take.
- **The historic slow numbers are different configurations:** Oct 9 19:48 (still on disk) was the
**vertical** tier (`comp=608x1080`, 45ms, 92 renders/5s); Oct 5 12:01's geometry was never logged
(the `scene=/comp=` suffix didn't exist) so the map's 21:9 story stays a hypothesis. Every slow
window shows `cache xR/0H`; one Oct 5 take latches fast→slow (1.5ms → 45ms) within 15s.
- **Corrected in the map (not appended):** "it was never Debug-vs-Release" is withdrawn (same
1920×1080 tier: Oct 9 = 10.4ms vs today's Release 1.0ms, and `Build <hash>` records no
configuration), and the "same scene shape" 10:01/12:01 comparison is superseded.
- **Same commit ships the probe + its recipe.** `scripts/webcam-cadence.py` (new tool): the
ground-truth check for what the FILE holds. Its three traps (H.264 re-encoding defeats
exact-pixel comparison; a round-clip crop's corners leak 60fps background; a fixed crop across a
scene switch reads background) cost three wrong readings — all in `MyMistakes.md`, with an
ffmpeg-native cross-check (`tblend=difference` + `signalstats.YAVG`) that agreed (52.2%
duplicates / 28.6 distinct/s).
## vv webcam feature — locked rules (creator, 2026-10-17)
| 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. 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).
- 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)
- **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.
## 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".
## Next step
- **Creator take in the FAILING geometry — the vertical 1080p60 tier first** (creator's pick from the
two options offered). Then, if the creator is willing, the 21:9 display config.
- Read three lines in `%APPDATA%\ytLlive\startup.log`: `FramePump parts (N renders/5s): …` (which
stage/element eats the budget), the `FramePump scene dump:` block (the shape), and `cache NR/NH`
(0 hits = the slow state's signature). **No fix until that take names the stage** — the latch
hypothesis (a composite pushed past the camera period can never reuse the whole-frame cache again)
is unproven and the `parts` line is what decides it.
- **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.
## Open (operational)
- **verify.sh's known-failure whitelist is too loose (confirmed twice on 2026-10-16):** it passes when
@@ -55,22 +86,18 @@
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` +
`RealMouseDrag_OnTheLayerList_PersistsTheReorder` to the list. Not fixed here — `scripts/verify.sh`
was never in a declared file list.
- **A pre-existing stash from older work 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).
- **Vertical-format regression (STALE, not fixed):** 1080p60-vertical selection no longer shrinks the
capture border in the preview (`Controls/PreviewPane.xaml:319-322` + `MainViewModel.Streaming.cs`
`ApplyStreamQuality`). Root cause unknown — paused. Note the vertical tier is ALSO the only slow
take still on disk, so if the next take reproduces the 45ms there, this area gets touched twice.
`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).
- ⛔ 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).
## Tests
- Full suite **428/428 passed, 0 warnings** (2026-10-16, the gate run for `84cbec2`) — a completely
clean run, including the audio tests that usually flake.
- Last full run: **428/428 passed, 0 warnings** (2026-10-16, the gate run for `84cbec2`). **No run this
session (planning only).**
- 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
@@ -81,6 +108,10 @@
`%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 — the log's path and the file on disk can differ that way).
- **Conversation history (how to recover what was actually said):**
`~/.local/share/opencode/opencode.db`, table **`session_message`** (`type='user'`, text in
`data.text`). The `part` table holds only assistant-authored text — searching it for a creator
message returns nothing. Recipe + command in `MyMistakes.md`.
- LAN credentials: `CREDENTIALS.md` (gitignored). Google Cloud OAuth project number `198374416003`,
owned by `llamachile.shop@gmail.com` — verify at
`https://console.cloud.google.com/apis/credentials?project=198374416003`.
+54
View File
@@ -1645,3 +1645,57 @@ semantics* — anchored-capture vs follow-the-box — before building any "zoom"
captures ALL layers with an extra layer in the fixture and assert it appears; (3) "draw above
everything" is a compositor ordering property (skip in the layer loops + blit last), not a z-index
of the element among the others.
## 2026-10-17 — Your own conversation history is in `session_message`, NOT `part`
I was asked to repeat the creator's original query verbatim. After a compaction I had only the summary,
so I searched the session store and landed on the wrong table twice. In `part` my search for the
creator's phrases returned hits — but they were **my own reasoning text quoting the phrase back**, which
looks exactly like a real hit and sent me chasing roles (`message.data` role), then
`instruction_entry`/`instruction_blob` (which do **not** hold prompts at all).
The creator's turns live in **`session_message`**, one row per turn: `type='user'`, the text inside the
JSON `data.text`.
```bash
# find the session by any distinctive phrase the creator used
sqlite3 ~/.local/share/opencode/opencode.db \
"SELECT DISTINCT session_id FROM session_message WHERE data LIKE '%<phrase>%';"
# then dump that session's turns in order
sqlite3 ~/.local/share/opencode/opencode.db \
"SELECT seq, json_extract(data,'\$.text') FROM session_message \
WHERE session_id='ses_…' AND type='user' ORDER BY seq;"
```
Lessons: (1) when compacted and unsure *what was asked*, query the store — never reconstruct the
creator's words from a summary; (2) a phrase hit in `part` may be my own echo of it, so check the
table's `type` before trusting a match; (3) this is the fix for "I can't search my own history" — it is
one query away, and the creator found their own query manually while I guessed.
## 2026-10-17 — I asked the creator to verify a preview visual I could have looked at
Planning the vv webcam feature, I asked: "when you select the vertical tier, does the preview actually
dim outside the band?" The answer was, in effect, *of course — that's the standard*. Two failures
stacked:
1. **I propagated an unverified claim.** My only reason to doubt it was a `HANDOFF.md` landmine
("vertical-format regression … no longer shrinks the capture border", marked STALE/root-cause-
unknown). It had never been verified, and it was **wrong** as stated. A stale, unverified handoff
line is a question-generator, not a fact — check it against the code or the app before letting it
shape what I ask.
2. **It was checkable without the creator.** The crop rectangle and the dimming are wired in code
(`PreviewPane.xaml:319-322` + `DimRects`/`ApplyStreamQuality`), and the creator can see the result in
one glance. I spent the creator's scarcest resource on something one look would have settled.
Created 2026-10-17 and standing (the creator stated these explicitly, after being left unable to tell
my reasoning from my replies):
- **Every reply begins with the reply marker on its own line.** The creator will not read an unmarked
reply — reasoning and reply are indistinguishable in their UI. Do not drop it; do not rely on a
leading blank line instead (the renderer trims it).
- **One explanation and one question per reply.** No question batteries, no "three things I need"
lists, no blue-sky option menus (A-vs-B, clamp behaviour) — those read as derailing.
- **State the decision I would make, in one line, and let the creator veto** — rather than presenting a
menu of choices for them to sort out.
- **Ask the creator only what only they can decide** (product intent). Anything the code, the app, or a
single look can answer, I answer myself.