From d95a23c6fb9de6883c5806ec57ba117ed4ca96f2 Mon Sep 17 00:00:00 2001 From: gramps Date: Tue, 29 Sep 2026 08:28:33 -0700 Subject: [PATCH] =?UTF-8?q?docs:=20the=20handoff=20was=20lying=20about=20t?= =?UTF-8?q?hree=20things=20=E2=80=94=20push=20state,=20TASK=2050,=20test?= =?UTF-8?q?=20count?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correcting the handoff against the repo, per the rule that a stale map is worse than no map. Three facts were wrong or missing, and the first two would have made the next session's first action wrong. 1. PUSH STATE. "Last pushed: e7cded6" with two commits listed as unpushed. main was actually 9 commits ahead of origin/main. The line under-reported unpushed work by 7 commits, which is the optimistic-by-construction failure MyMistakes.md already names for a handoff whose heading promises the work is live. Now recorded as caught up. 2. TASK 50 WAS ABSENT, AND IT CARRIES A LIVE BUG, NOT A QUEUE ITEM. The task was carved 2026-09-28 and its mechanism section was CORRECTED the same day against the creator's own channel: 20+ private videos, all content-less placeholders. That is not a deferred feature, it is the real explanation of the 2026-09-26 "I cannot get private test recordings saved" report the map had been carrying as a closed item. liveBroadcasts.insert succeeds and creates the placeholder; the RTMP push / LIVE transition / archive chain is what fails, so no video content is ever produced. Added as an OPEN entry with the single diagnostic question that localises it (does ffmpeg reach a.rtmp.youtube.com, and does the broadcast reach LIVE), plus the sequencing constraint: do NOT flip enableAutomaticArchiving before TASK 50 ships, since archiving is currently the only route a recording takes to YouTube. It also carries an open 11.12 re-check — a publish feature makes the app PUSH creator content to a third party, so the IARC answers must not describe an app that cannot publish. That is a certification-ordering constraint, not a code detail, and it belongs where the next session will read it. 3. TEST COUNT WAS STALE. Recorded 379; the suite is 380 (the force-ssl scope test added one). Re-verified on a clean test-project build. Also recorded a new flake honestly rather than leaving it for the next session to rediscover as a regression: MasterLimiter_CapsTheLiveMix_OnThePipe failed once on a full-suite run with Expected 0.891 / Actual 0, then passed 27/27 as a class run and 380/380 on an immediate re-run. It reads the live mix off the named pipe, so a ZERO is the pipe not being fed yet, not the limiter misbehaving — the same whole-suite scheduling family as the RealAppHost STA landmine. Recorded with "re-run before believing it". Next list: the RTMP diagnostic sorts first because it is an observation rather than a build and it gates a queued task; the packaging unit remains the next CODE unit, which is not a reordering of the creator's priorities. verify.sh: clean build, 0 warnings, 380/380, scope check passed. --- HANDOFF.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index ea1e696..f1010b2 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -1,8 +1,9 @@ # HANDOFF — current state **Branch:** `main` (pre-1.0, no feature branches — creator ruling 2026-08-24). -**Last pushed:** `e7cded6` (pricing/Store fee docs). **Local, unpushed:** `536676f` (recording -filename ms) and the Change Account fix in this unit — ask before pushing. +**Caught up 2026-09-28:** `main` is pushed to `origin/main` (was 9 commits ahead — the handoff +line below used to under-report the unpushed work by 7 commits, which is exactly the failure +`MyMistakes.md` warns about: a stale handoff makes the reader's next action wrong). ## 🚨 FIXED 2026-09-27 — "Change Account" no longer signs you out before the browser opens @@ -143,7 +144,8 @@ gitignored `ffmpeg/` from a **SHA-256-verified** pinned month-end BtbN artifact; copies it to output *and publish* and **fails the build** if it's missing; `FfmpegLocator` lost its downloader, its zip extraction and the `%APPDATA%\ytLlive\tools` cache, and now resolves **bundle → PATH** with a loud, actionable failure. The pin that 404'd is gone, so the -2026-09-01 failure class cannot recur. Suite **379/379**, 0 warnings; 16 locator facts including an +2026-09-01 failure class cannot recur. Suite **379/379 at that point** (380 now — see Test +state); 16 locator facts including an integration test that **executes the bundled binary** (which is what proves the sibling DLLs resolve). `THIRD-PARTY-NOTICES.txt` corrected — it still named the *stale* tag `autobuild-2026-08-09-13-03`, i.e. the one that 404'd. @@ -185,6 +187,42 @@ Carried over from the research unit, still open: the 11.12 certification answer. No chat history, moderation log, analytics, or crash payload may be added without re-arguing 11.12 first. +## 🚨 OPEN 2026-09-28 — the RTMP push never lands: recordings reach YouTube as EMPTY placeholders + +**This is a live bug, not a queued feature**, and it reframes a complaint the map previously +treated as closed. It was found on 2026-09-28 while scoping TASK 50, and the handoff had no +entry for it at all — corrected here. + +**What the creator observed:** the channel carries **20+ private videos, all content-less +placeholders** (creator-inspected, 2026-09-28). This is the real explanation of the +2026-09-26 report "I still cannot get private test recordings saved" — it was never true that +the app could not *find* an archived VOD. **No video content is ever produced on the channel.** + +**Mechanism (verified against the code AND the channel):** `liveBroadcasts.insert` succeeds and +creates the placeholder; everything after it is what fails. Content only exists if all three of +these land, and at least one does not: +1. broadcast reaches **LIVE** via `liveBroadcasts/transition`, +2. ffmpeg actually pushes RTMP to the bound stream key, +3. the broadcast ends and YouTube transcodes it into a VOD. + +`enableAutomaticArchiving` is **never set**, so YouTube's `true` default applies — the archiving +route exists but has nothing to archive. Broadcasts are inserted `private` +(`Services/YouTubeStreamService.cs:49`), so the orphans are not public, and the app has **no +delete path** — the creator clears each one by hand in Studio. + +**⛔ The one diagnostic question, worth answering before anything else queued:** during a real +test stream, **does ffmpeg reach `a.rtmp.youtube.com`, and does the broadcast reach LIVE?** +That single observation localises the failure to one of three steps. Do not go hunting beyond +it until it is answered. + +**Sequencing constraint — do not flip the flag early.** `enableAutomaticArchiving: false` is the +correct end state (TASK 50 will upload the local file deliberately), but archiving is +**currently the only route a recording takes to YouTube** — flipping it before TASK 50 ships +would leave test streams with nothing at all and re-create the 2026-09-26 complaint in a worse +form. Ship the upload, flip the flag in the same task, never before. + +Detail and the open 11.12 re-check: [`TASKS/task-50-publish-recording.md`](TASKS/task-50-publish-recording.md). + ## Landmines - **Stale fact inside `TASKS.md` (left alone, flagged here per the Scope Lock).** The "1.0 gates" @@ -209,9 +247,18 @@ Carried over from the research unit, still open: ## Test state -**379/379, 0 warnings, as of the ffmpeg-bundling unit (2026-09-28).** Build the **test** project, +**380/380, 0 warnings, re-verified 2026-09-28 on a clean test-project build** (the count is 380, +not the 379 recorded earlier — the `force-ssl` scope test added one). Build the **test** project, not just the app project, or VSTest runs a stale DLL. +**⚠️ New flake, do not chase it as a regression:** on the *first* full-suite run, +`AudioPipelineTests.MasterLimiter_CapsTheLiveMix_OnThePipe` failed with `Expected 0.891, +Actual 0` — a **zero**, not a slightly-off value, which is the signature of the pipe not being +fed yet rather than the limiter misbehaving. It passed 27/27 as a class run and 380/380 on an +immediate full-suite re-run. It reads the live mix **off the named pipe**, so it is a +whole-suite scheduling artifact of the same family as the `RealAppHost` STA landmine below — +**if it ever goes red, re-run before believing it.** + ## Uncommitted / untracked - `ffmpeg/` — the 9 bundled binaries (~135 MB), **gitignored by design**. Populated by @@ -223,29 +270,39 @@ not just the app project, or VSTest runs a stale DLL. ## Next -1. **The packaging project + `Package.appxmanifest`** (TASK 48 items 2–3) — the next code unit. +1. **Answer the RTMP diagnostic — an observation, not a build** (see the OPEN entry above). + One test stream, then read `startup.log` for whether ffmpeg reached YouTube and whether the + broadcast went LIVE. **Cheap, and it gates a queued task**, which is why it sorts first. It + does not reorder anything below — the packaging unit is still the next *code* unit. +2. **The packaging project + `Package.appxmanifest`** (TASK 48 items 2–3) — the next code unit. Full trust, `webcam`/`microphone`, English only; Velopack deleted. Add the `DefaultRecordFolder()` comment in the same unit, and the WebView2 framework dependency + graceful-failure path. -2. **Declare the IAP products in Partner Center** — the price is **settled** ($10/mo, $400 +3. **TASK 50 — one-button "Publish this video"** (`TASKS/task-50-publish-recording.md`). Queued + behind the Store submission by its own precedence note ("MSIX first, publish second — unless + the creator reverses that"). Scoping is done; the build is not. ⛔ Do **not** flip + `enableAutomaticArchiving` until it ships. It also carries an **open 11.12 re-check**: a + publish feature makes the app *push* creator content to a third party, so the IARC answers + must not go to certification describing an app that cannot publish. +4. **Declare the IAP products in Partner Center** — the price is **settled** ($10/mo, $400 lifetime, no annual, 15% verified), so this is unblocked. **Blocks:** the Store listing and the `OverlayHost.xaml` copy. ⛔ The Individual-vs-Company account question is still unanswered — get it right before enrolling. -3. **Polar teardown** (TASK 48 item 0) — `PolarLicenseService`, `PolarLicense`, +5. **Polar teardown** (TASK 48 item 0) — `PolarLicenseService`, `PolarLicense`, `MainViewModel.License.cs`, the `OverlayHost.xaml` string, the `csproj`/`App.xaml.cs` Velopack sites. `IsPremium` ← Store entitlement. **Do this as one unit** — a half-torn-down licensing path is worse than either end state. -4. **Vertical recording verification** — the compositor tier is proven by +6. **Vertical recording verification** — the compositor tier is proven by `Render_VerticalTier_Outputs_1080x1920_From_The_Center_Crop`; the *record* path has never been run. `FramePump.cs:645` flags off-size tiers as a known follow-up. -5. **WACK + certification notes + the privacy policy** (TASK 48 items 4–5) — the policy must +7. **WACK + certification notes + the privacy policy** (TASK 48 items 4–5) — the policy must state camera/mic is OS-gated, nothing is retained, and **nothing is fetched at runtime** (now literally true — the ffmpeg bundle is what makes that sentence defensible). -6. **Post-session efficacy report** — roll up `CurrentHealth` (dropped frames, duration, health +8. **Post-session efficacy report** — roll up `CurrentHealth` (dropped frames, duration, health message) when a stream or recording ends. `SessionTeardownTests` is the natural home. -7. **Measure whether the Windows camera toggle gates DShow** — gates all privacy-forward copy +9. **Measure whether the Windows camera toggle gates DShow** — gates all privacy-forward copy (`MARCOM.md` guard). Not a certification risk; a trust risk. -8. **TASK 36:212 stale "shipped" line** — one-line fix, needs a hand. +10. **TASK 36:212 stale "shipped" line** — one-line fix, needs a hand. **Dropped from the list** because the ruling made them moot: multi-instance's ffmpeg tools-dir race (item 1 deleted the tools dir entirely), `scripts/publish.sh` + the `LlamaCasty.exe` rename