The paid delta is output quality, so the rule needs to be measurable rather than a word:
921,600 pixels and 30 fps, fail-closed. Models/OutputProfile.cs is that rule as pure
policy — a permitted tier passes through untouched (Pro, or the free tier's own 720p30),
a disallowed one resolves to the best tier the budget allows and carries ITS bitrate, so
a capped user is never offered an 8 Mbps budget for a 720p frame.
Applied once, in BuildEncoderOptions. That is genuinely one place: the stream and the
local recording are two output blocks of ONE ffmpeg process fed by one EncoderOptions,
so there is no second encoder to forget. (commercial.md claimed "both encoders — never
two checks"; the code is stronger than the doc, and the doc is corrected.)
Developer override, as asked: a "Developer mode — all resolutions" checkbox in App
Settings, bound to MainViewModel.DeveloperMode, which feeds HasProOutput. It is not
hidden in a release build — Controls/DeveloperPanel's Page and Compile items are removed
when Configuration != Debug, and OverlayHost adds it at runtime inside #if DEBUG, so a
shipped exe has no BAML for it at all. The setter also refuses the value when
DevBuild.IsDevelopment is false, which is now the single source for that question (the
scoreboard partial had its own duplicate const).
Two traps worth their lines: a `const bool` dev flag makes `if (!Flag) return;` an
unreachable-code warning in one configuration or the other (CS0162), so DevBuild uses
static readonly; and a Condition on an ItemGroup is invisible to a test reading
item.Attribute("Condition") — read the parent.
Tests: 14 pass across OutputProfileTests, AssemblyIdentityTests and StorePackagingTests.
The invariant test is the one that matters: iterate every shipped tier under a free
entitlement and assert none emits more than the budget, so a future 4K tier fails here
instead of shipping to everyone. App builds Debug and Release at 0 warnings.
8.1 KiB
TASKS — the active queue
One line per live item; the detail lives in
TASKS/task-*.md. Done work is inTASKS/archive.md(2026-10-29 snapshot of the old catalogue). Retired decisions are indocs/ai/decisions.md. Markers: ☐ queued · 🔶 in progress · ⏳ blocked · ⏸ deferred · ❌ retired.
Next up
The surge week (3 days, in this order). Not every row below — this slice only, because it is
what the first public release is waiting on. Day 1 (artifact shape) is done: the exe is
LlamaCasty.exe and scripts/publish.sh stages the depot folder.
- OutputProfile gate — ≤921,600 px / ≤30 fps for the stream and the recorder, greyed tier entries, plus the TASK 53 geometry tests that pin every tier.
- Then the entitlement seam (
IEntitlement, Steam DLC path behind a fake, Polar path) and the licence UI.
Detail: commercial.md → Output profile / Entitlement;
Distribution.md. After that: the visibility picker (a hard prerequisite for
any public build).
TASK 3·17 — the Text layer stays the first product row after the surge. The TextOverlay source
type exists as a placeholder and nothing else does: AddSource creates it 0×0, all four compositor
paths continue past it, FramePump's hash skips it, it is not draggable, and it has no
text/font/colour properties or persistence. The unit: text content, font family/size/weight/style,
colour, alignment, drag/resize, persisted; renderer mirrors Services/ChatBoxRenderer.cs. One Good
Dog test.
Queue
| Task | Status | Scope | Detail |
|---|---|---|---|
| 3·17 | ☐ NEXT | Text layer — content, font family/size/weight/style, colour, alignment, drag/resize, persisted | task-03 |
| 21 | 🔶 | Media source: acquisition wiring + file picker + loop/volume UI (decoder, manager, pacing, loop all shipped — no AcquireAsync caller exists) |
task-21 |
| — | ☐ | Transitions Move: per-layer carry-across-scenes flag, per-scene placement, fixed z band | ui-surface |
| 55·2–3 | ☐ | Disk hygiene: delete %TEMP% alert clips on close + sweep at startup; low-disk guard before REC (slice 1 shipped) |
task-55 |
| 40·A/C/D | ☐ | App Settings: active-camera picker; persist output resolution + surface transition defaults + confirm-before-End; accent consolidation | task-40 |
| 3·20 | ☐ | RewardEvent persistence: canonical RewardEvents table + superChatEvents.list 30-day backfill (the session report and journey read it) |
task-03 |
| 32 | ☐ | Stream resilience: blip retry → measured grace + amber "RECONNECTING" → one-click Back on air → fragmented MP4 → ingest pre-flight | task-32 |
| 33 | ☐ | Bandwidth auto step-down: pure policy over dropped-frame rate, one-way within a broadcast | task-33 |
| 34 | ☐ | Scheduled streams (Text-drawer version) | task-34 |
| 35 | ☐ | Scene-linked audio | task-35 |
| 37 | ☐ | Defaults vs current layout split (build-id); enables one-click revert to defaults | task-37 |
| 39·2 | ☐ | YPP slice 2: Analytics scopes, watch-hours/Shorts velocity + ETA | task-39 |
| 49 | ☐ | Chat profanity filter: local, opt-in, non-persistent, user-supplied word list | task-49 |
| 50 | ☐ | One-button publish of the local recording (resumable upload) | task-50 |
| 53 | ☐ | Output-format contract: pin every tier with a geometry test, prove 9:16 end-to-end, recorded file matches output | task-53 |
| 54 | 🔶 | Freemium: EULA + privacy shipped; no licence path built — needs the entitlement seam, the output-profile cap and the licence UI below; site copy still says free forever | task-54 |
| — | ☐ | Steamworks entitlement — steam_api64.dll + SteamAPI.Init, BIsDlcInstalled(dlcAppId) behind IEntitlement, free profile when Steam is absent |
commercial |
| — | ☐ | Entitlement seam — Polar customer-portal path for the monthly (org ID public, org token never in the app), conditions: {channel_id}, 7–14 day lease, --activate CLI. No claim page, no server |
commercial |
| — | 🔶 | OutputProfile gate — resolver + EncoderOptions wiring done (Models/OutputProfile.cs, one ffmpeg/two outputs, dev override); remaining: greyed tier entries in the dropdown, entitlement wiring |
commercial |
| — | ☐ | Licence UI — four states, 7/1/0-day notices, "monthly is on the website, not Steam" line, portal link, licence ID in About | commercial |
| — | ☐ | System messages — SystemMessage + MessageCenter, strip above the dock, dedupe by key, short history, never composited |
ui-surface |
| — | ☐ | Steam packaging — rename, publish output + steam_api64.dll, depot, steamcmd upload, store page + assets, DLC app |
Distribution.md |
| — | ☐ | Training-video series — capture the first 8–10 recurring questions as videos on @llamacasty; each is documentation, channel content and monetization at once |
MARCOM → support→content loop |
| 9·5 | ☐ | Webcam identity key reconciliation | task-09 |
| 14 | 🔶 | Creator feedback batch — branch 3+ | task-14 |
| — | ☐ | Small: StreamConfig defaults (TargetBitrate=6000, 1920x1080) are stale — the dropdown drives StreamHealth |
this line |
| 36 | ☐ | Gold pass — the v1 gate, always the last unit (see 1.0 gates) | task-36 |
| 48 | ⏸ | Distribution & packaging — route settled 2026-10-31 (winget/portable first; Steam + Store parked). Build steps: Distribution.md; starts after the entitlement seam |
task-48 |
| 10 | ❌ | Retired 2026-10-08; superseded by the TASK 54 rows above — the Polar design it described is rebuilt as a lease (commercial.md), not revived as written |
task-10 |
Pending the creator's hands (not programming)
- ✅ App Settings grouping + right-click gear — reported working 2026-10-29.
- ✅ Transition picker/durations, Wipe, preview + program transitions — reported working 2026-10-29.
- ✅ Brand logo layer — reported working 2026-10-29.
- ⏳ Vertical-tier camera check (Live tile inside the band, Chat rect-only) — outstanding.
- ⏳ Webcam cadence: a Release take in the failing geometry (vertical tier first) blocks Units 1–2. No fix until a reading names the stage.
1.0 gates (before the first shipped build)
- Visibility picker — replace the always-Private lock, hide the TEST button, and wire
UpdateBroadcastin the same unit (it is the only code that can change a broadcast's privacy). - Kill the dev multi-instance affordance —
Helpers/InstanceProfile.csis already#if DEBUG; re-prove it on a Release build. - Release engineering —
scripts/publish.shdone (self-contained win-x64,ffmpeg\guarded, no test artifacts),LlamaCasty.exeassembly rename done, full license texts besideTHIRD-PARTY-NOTICES.txt(TASK 4 req 9). Outstanding: Debug-onlyInternalsVisibleTo. - Gold pass (TASK 36): the screens/layers audit, native-Windows verification, and the branding-flash decision.