docs(commercial): one source of truth for the money — prices, entitlement, channels

The commercial plan was spread over five documents written in five different weeks,
and they contradicted each other: product.md sold the Store, decisions.md called the
Store dead then re-opened, Distribution.md (736 lines) still described Polar as a
download host, MARCOM.md quoted "no subscription" next to a paid tier, and README.md
promised "free forever". An outsider could not tell what ships.

docs/ai/commercial.md is now the only place money is decided: free = whole app at a
921,600 px / 30 fps output profile covering the recording as well as the stream; Pro =
$10/mo or $400 lifetime through Polar, key bound to the buyer's YouTube channel ID via
a claim page, 2 activations, 7–14 day lease with offline grace, fail closed, never
downgrade a running stream; one portable zip + winget primary, Steam and the Store
parked; Azure Trusted Signing (~$9.99/mo), no EV; Founding 200 promo; ~$135/yr costs;
anti-piracy posture and what is permanently rejected.

Everything else now points at it instead of restating it:
- product.md — money sections replaced with pointers; packaging rewritten to
  winget-first, Store parked; signing updated to Trusted Signing.
- decisions.md — graveyard with cause of death for free-forever, the Store ordering,
  the updater, and the 2026-10-30 reversal of the quality-ceiling rejection.
- Distribution.md — rewritten to release mechanics only (artifact, GitHub Releases,
  winget manifest, signing, checklist, takedown): 736 → 120 lines.
- TASKS.md — TASK 54 rewritten, TASK 48's route settled, TASK 10 superseded, five new
  rows (entitlement seam, output-profile gate, licence UI, system messages, packaging).
- README.md — "free forever" replaced with the real split.
- capture.md — obs-backgroundremoval is GPL-3.0 and so licence-INCOMPATIBLE since the
  proprietary EULA; the old "compatible" line was falsified by that change.
- TASKS/task-10, task-48, task-51, task-54 — superseded-banner at the top of each, so
  none of them reads as current policy.
- HANDOFF.md — rewritten: plan settled, next code unit is the entitlement seam.

MARCOM.md and MONETIZATION.md (gitignored) were corrected in place: policy pointer at
the top of each, the flash removed from every live claim, the Polar fee break-even
corrected to ~$900/mo, and the projections flagged as written against a dead model.
This commit is contained in:
2026-10-31 08:32:25 -07:00
parent 90d5140906
commit 7827d239e2
14 changed files with 445 additions and 854 deletions
+3 -2
View File
@@ -312,8 +312,9 @@ This replaces the old five-seeder cluster (`Seed{Starting,Brb,Ending,Chat}Backgr
`verify_against_mediapipe.py` feeds the same frame to MediaPipe's `ImageSegmenter` (original
.tflite) and onnxruntime (our .onnx): max |diff| 5e-5, 100% binary agreement on two images.
⛔ Do NOT swap in PINTO model-zoo #109 (it's ML Kit's model, extracted — not Apache provenance).
obs-backgroundremoval is GPL-3.0 — license-compatible since LlamaCasty went GPL-3.0 (2026-10-09),
but none of its code is used; if any is ever borrowed, it needs its copyright notice kept.
obs-backgroundremoval is GPL-3.0 and therefore **licence-incompatible since the app went
proprietary (2026-10-30)** — none of its code is used, and none may be borrowed into this
codebase without a licence ruling first. Google's model is the provenance that matters.
- **Contract:** input `[1,144,256,3]` RGB /255 NHWC → output `[1,144,256,1]` person probability. The
whole frame is stretched (not cropped) to 256×144, so the mask maps back by normalized coordinates.
- **Shipping:** `Assets/Models/selfie_segmenter_landscape.onnx` is an **EmbeddedResource** (in git,
+152
View File
@@ -0,0 +1,152 @@
# Commercial: pricing, entitlement, channels
The single source of truth for what LlamaCasty charges, what a licence entitles, and how it
ships. Read before any pricing, licensing, distribution, storefront or promo work. Cause of death
for every retired path: [`decisions.md`](decisions.md).
## Model
- **Free tier — every feature, every scene, every overlay**, free forever, no account, no
watermark, nothing nagged inside the output. It is not a trial.
- **Pro — $10/month or $400 lifetime.** No annual tier.
- **The only delta is output quality.** Features are never gated; a payment buys pixels.
- **No watermark, ever**, in either edition. The branding flash is retired as a paid delta and
stays off (`ShowBrandFlash`, default `false`).
- **Clean numbers, no `.99`**, no discount codes, no countdowns, no fake scarcity.
- **The site publishes the model, never the numbers** — "free forever, every feature unlocked, a
paid edition with higher output quality at launch". Price, tier name, cap and frame rate are
published by the **app**, at the point of sale, not by the page.
## Output profile — the one entitlement rule
The cap is a pixel budget plus a frame rate, not the word "720p":
| | Free | Pro |
|---|---|---|
| Pixels | ≤ **921,600** | any shipped tier |
| Frame rate | ≤ **30 fps** | any shipped tier |
| Landscape | 1280×720 @30 | 1280×720 @60 · 1920×1080 @30 · @60 |
| Vertical 9:16 | 720×1280 @30 | 1080×1920 @60 |
- **Records too.** The cap governs the file the creator keeps as well as the stream; otherwise
free 1080p recording is a re-upload hole. One `OutputProfile`, resolved once per session and
consumed by **both** the stream encoder and the recorder — never two checks.
- **Fail closed.** Unresolved, unreadable or unvalidated entitlement = free tier. Never Pro.
- **Never downgrade a running stream.** The gate applies to the next start; pulling quality out
of a live broadcast is a worse bug than one free 1080p session.
- **The greyed menu entry is the sales surface.** It stays clickable, says what it costs, opens
checkout, and is labelled ("720p30 · free tier") — never silently missing, because silence
reads as broken.
- **Activation is live**, not restart-gated: activating enables the high tiers and a lapse
(cancel, revoke, sign-out, channel switch) greys them again on the next refresh.
- **Bitrate follows the profile** — a capped user is not offered a 1080p bitrate.
## Entitlement
**Polar is the merchant of record and the only source of truth.** It takes the money, remits
VAT/GST, handles refunds and chargebacks, and holds the keys. Nothing of ours sits in the middle.
- **Key** — `LCYT-` prefix; org `c05fb364-…` and the endpoint are in `CREDENTIALS.md`. No
product is created yet.
- **Bound to the creator's YouTube channel ID** (`UC…` from `channels.list?mine=true`) — the
**active** brand account's channel, never the `@handle`. Written once through a **claim page**
after purchase (OAuth), not prefilled at checkout: the buyer's browser may be signed into a
different Google account, and that is manual reconciliation forever.
- **Two activations**, any machine, one channel. A second channel is a second key. Two keys for
one channel is never sold — it doubles the support surface and invites "give one to a friend".
- **Runtime rule:** Pro requires `licence.channelId == connected.channelId`. Equal → Pro.
Anything else → free tier, working normally, with *"This licence belongs to another channel"*
and a link to the Polar customer portal. Never an error wall, never a blocked stream.
- **Lease, not a permanent cache:** validate on launch and daily; **7–14 days offline grace**;
no network past grace = free tier until Polar answers. Never lock a paying user out on a DNS
failure.
- **Four states, and nothing else:** valid → Pro · expired → free with a banner · activation
limit reached → "manage devices" portal link · mismatch or offline → free, explained.
- **CLI activation** — `--activate LCYT-…` so silent and fleet installs never meet a dialog.
Interactive entry in Settings is the secondary path.
- **Notice cadence** — 7 days out, 1 day out, and on the day, inline in the go-live panel with a
date and a portal link. Recording gets the banner only. Never modal, never blocking a Start,
never orange (orange is the dev-only label colour).
## Channels
**One artifact, three ways to get it.** A self-contained single-file `LlamaCasty.exe` plus the
bundled `ffmpeg\` folder, zipped. No .NET install, no admin, no installer framework. Trimming
stays off (WPF reflection), so expect ~110–150 MB.
1. **Direct download** — `llamacasty.com` links the zip; the binaries live on **GitHub Releases**,
not the droplet (free CDN, durable URLs, release notes).
2. **winget — the primary channel.** Manifest in `microsoft/winget-pkgs`, `InstallerType:
portable`, pinned SHA-256. That hash pin is the anti-tamper wall: the official channel delivers
exactly the published artifact or fails. One `wingetcreate update` PR per release. Optional:
Scoop and Chocolatey manifests over the same zip.
3. **Steam — parked at $100.** Lifetime Pro as DLC only (Steam has no subscriptions), page public
two weeks before release, 30% cut, and price parity with the site.
4. **Microsoft Store — parked.** $19 Individual account; the only storefront that bills a
subscription natively and installs without a warning. Bans self-updaters, so a Store build
ships without one.
**Not channels, ever:** Patreon or any subscription platform of our own, paywalled early access,
a paid beta, a Discord. Support is a public GitHub issue tracker. Content is the funnel; the
channel is only the checkout.
**Portable mode:** a `portable.txt` marker beside the exe keeps the layout DB and settings in
`.\data\` instead of `%APPDATA%\ytLlive` — the USB-stick case, hung off `LayoutPathOverride`.
## Signing
- **Azure Trusted Signing, ~$9.99/month**, is the intended certificate: Microsoft-issued, accrues
SmartScreen reputation, enrols individuals after identity verification.
- **No EV certificate** — Microsoft removed the SmartScreen instant-bypass in March 2024.
- Until it is in place, builds ship unsigned and the "unknown publisher" line is accepted. winget
spares the browser prompt, not the publisher warning.
- Every release: same signing pass, SHA-256 in the manifest, licence ID visible in About.
## Founding 200 promo
Cash cost **$0**; it is priced in support time and forgone list revenue.
- **90 days free** — a 100%-off Polar coupon, `duration = repeating, months = 3`.
- **Founder price lock** — their $10/month stays $10 permanently.
- **Credits + in-app Founder badge** (opt-in channel name on the site).
- **30-day passes** — unique keys carrying the issuer's channel, issued **one per 30 active days,
max 3 held**, activation limit 1–2, expiring 30 days **after activation**. Earned, never handed
out: a pass nobody uses teaches nothing.
- Optional **$250 lifetime** window in the first 90 days — converting a founder beats three
months of free.
- Reminders at day 75 and 85; the renewal cliff is where founders churn.
- Terms, one paragraph: one per person, passes expire 30 days after activation, no cash value,
revoked for resale or abuse, price lock void if the subscription lapses.
## Costs
| Item | Cost |
|---|---|
| Azure Trusted Signing | $9.99/month (~$120/yr) |
| Domain | ~$15/yr |
| Droplet | $0 — serves the existing site |
| GitHub Releases, winget, Scoop, Chocolatey | $0 |
| Polar | 5% + 50¢ per sale → $10 nets $9.00, $400 nets $379.50 |
| Steam Direct (optional) | $100 once, recoupable after $1,000 AGR |
| Microsoft Store (optional) | $19 once |
Fixed year one ≈ **$135**, and the same every year after. **Break-even is two subscribers**
(15 subscriber-months ≈ $135); one $400 lifetime sale covers nearly three years.
## Anti-piracy posture
**Any check that runs on the user's machine can be removed.** The goal is a crack that is
pointless and a leak that is traceable — not an unbreakable binary.
- **The free tier is the real defence.** If the only delta is pixels above 921,600, a cracked
build buys almost nothing and forfeits updates, support and the publisher's signature.
- **Hash-pinned delivery + signed builds** — a patched build cannot arrive through winget, and a
forged one is not signed as us.
- **Short leases** — a revoked or refunded key dies inside the grace window.
- **Licence ID in About** — a leaked build traces back to a purchase.
⛔ **Rejected, do not re-propose:** a native helper DLL for "IP protection", obfuscation, hardware
locking, remote code that downloads and executes, and gating asset downloads as an auth check.
None of them make a licence enforceable; the first three add failure modes without buying
anything, the fourth needs the server this plan exists to avoid, and the fifth is Store policy
10.2.2.
+50 -25
View File
@@ -1,15 +1,18 @@
# Decisions log — retired paths, kept so they are not re-litigated
One dated line per decision that **no longer governs**, plus the reason it died. Read only when
you are about to re-open one of them. Live rules live in the subsystem files; this is the
graveyard with cause of death.
you are about to re-open one of them. **Live commercial rules (prices, entitlement, channels,
signing, promo) are in [`commercial.md`](commercial.md)**; the other live rules live in the
subsystem files. This is the graveyard with cause of death.
## Monetization
### 2026-10-30 — freemium replaces free-forever (creator ruling)
Free tier caps output at **720p30**; **$10/month** or **$400 lifetime** unlocks 1080p. Reverses the
2026-10-08 free-forever ruling below, which was a *current decision*, not an absolute.
Free tier caps output at **720p30**; **$10/month** or **$400 lifetime** unlocks the higher tiers.
Reverses the 2026-10-08 free-forever ruling below, which was a *current decision*, not an absolute.
The live detail — pixel budget, stream + recording, channel binding, lease, notice cadence — is in
[`commercial.md`](commercial.md); do not re-derive it here.
**The website publishes the model, never the numbers** (free forever, every feature unlocked, a paid
edition at launch) — the terms may still change. The real plan is recorded internally in the site's
@@ -33,23 +36,41 @@ edition at launch) — the terms may still change. The real plan is recorded int
- **Rejected**: always-on watermark (obscurable — replaced by the flash), hard stream-time cutoffs
(a stream dying mid-broadcast reads as broken), soft-limit nagging, freemium feature tiers,
donation-only, and any resolution/quality ceiling. Auto step-down (TASK 33) is a *protect the
stream* feature, never a monetization penalty.
- **Polar** — $50 already paid, 5% + $0.50 Starter, merchant of record. Dormant, not
deleted-in-principle: no product, org ID, key prefix or discount code exists
(`d105dfa1-…`, `c05fb364-…`, `LCYT-`, `LLAMAFOUNDER`/`LLAMA50`, the portal-validate endpoint and
the 14-day offline-grace machine are all gone). `Distribution.md` §4.2/§4.5 keeps the design.
stream* feature, never a monetization penalty. ⚠️ **The quality-ceiling and feature-tier halves
were reversed on 2026-10-30** (freemium, output-quality delta); the watermark, cutoff and
nagging rejections still stand.
- **Polar** — $50 already paid, 5% + $0.50 Starter, merchant of record. **Live again as of
2026-10-31** (`commercial.md`). The org ID `c05fb364-…`, the `LCYT-` key prefix and the
customer-portal validate endpoint are recorded in `CREDENTIALS.md`; no product, licence keys or
discount codes exist yet. The old `PolarLicenseService`/`Helpers/PolarLicense.cs` are still gone
— the 14-day-grace design has to be rebuilt (as a lease, not a permanent cache).
- **Store IAP** was never implemented — `Windows.Services.Store` appears nowhere in the repo.
- ⚠️ **Two obligations any future subscription would create** (ADA §6(h)): fulfil the whole period
as marketed (breach → Microsoft may refund in full at its discretion), and **raising the price
disables auto-renew** — the launch price is effectively locked for the product's life.
## Distribution — Store route RE-OPENED 2026-10-30 (Individual account)
## Distribution — Store PARKED as the third channel (2026-10-31)
**2026-10-30:** the Store is the route again, via a **Microsoft Individual developer account**
(not Company), so no legal entity is needed and the publisher line shows the verified individual
name. The creator will open the account; distribution work stays parked until then. The site copy
("Coming soon to the Microsoft Store") is therefore accurate again, and the 2026-10-22
"Store is dead / direct + Steam" ruling below is superseded.
**2026-10-31:** **winget over a portable zip is the primary channel** — one self-contained
`LlamaCasty.exe` + bundled `ffmpeg\`, zipped, hosted on GitHub Releases, manifest in
`microsoft/winget-pkgs` with a pinned SHA-256. Steam is second and parked at $100 (lifetime Pro as
DLC only — Steam has no subscriptions). The **Microsoft Store is third and parked** until the
creator opens the **$19 Individual** developer account: it is the only storefront that bills a
subscription natively and installs without a SmartScreen warning, and it bans self-updaters.
Channels, costs, artifact and signing: [`commercial.md`](commercial.md).
**Why the ordering inverted:** winget has no discovery, but neither does the Store for utilities,
and winget costs nothing, needs no account, no certification and no MSIX pipeline — while the
audience installs Windows tools from a command line. The site and the YouTube channel are the
funnel in both cases.
## Superseded: Store was "the route again" — 2026-10-30 (ordering only)
**2026-10-30:** a **Microsoft Individual developer account** (not Company) removed the legal-entity
blocker — the publisher line shows the verified individual name, and Partner Center does not
convert Individual → Company later. That finding stands; what it no longer implies is *primary*.
The site copy ("Coming soon to the Microsoft Store") stays true until the download page lands, then
the Store line becomes the secondary note.
## Superseded: Store route withdrawn 2026-10-22
@@ -58,20 +79,19 @@ name. The creator will open the account; distribution work stays parked until th
New Mexico with a ~2-week SOS backlog, ~$143 Wyoming). Partner Center does **not** convert an
Individual account to a Company account later, and an Individual account publishes under the
verified legal name. The creator will not fund an entity for a nameplate.
- **2026-10-22 Velopack deleted** — it downloaded and executed, which Store policy 10.2.2 forbids.
The Store was going to update the app, so that premise died with the route: **the app now has no
update path**, and `StorePackagingTests` currently asserts that no updater exists — rewrite that
guard with the chosen updater, never leave it to veto one.
- **The MSIX package still builds** (159 MB `artifacts/LlamaCasty.msix`, submitted nowhere). The
route contradiction between `ai.md`'s older text and the TASKS files is settled in one sweep at
the distribution revisit, not patched piecemeal.
- **2026-10-22 Velopack deleted** — it downloaded and executed, which Store policy 10.2.2 forbids
(and which the 2026-10-31 plan keeps forbidden). The app has **no self-updater by policy**:
`winget upgrade` plus an in-app "newer version exists" banner is the update path, and
`StorePackagingTests` asserts that no self-updater returns.
- **The MSIX package still builds** (159 MB `artifacts/LlamaCasty.msix`, submitted nowhere) — it
is the parked Store channel's artifact.
- **Signing**: Microsoft removed the EV instant-bypass for SmartScreen in March 2024, so EV buys
what OV buys; the 2026-10-22 ruling is **ship unsigned** and accept the "unrecognized publisher"
warning until download reputation accrues. Deferred, not rejected.
what OV buys. The 2026-10-22 ruling was *ship unsigned*; **2026-10-31 supersedes it with Azure
Trusted Signing (~$9.99/month)**, which is Microsoft-issued and accrues reputation.
- **Steam when $100 exists**: Steam Direct $100/product (recoupable after $1,000 AGR), categories
*Audio/Video Production* / *Player Tools* (OBS precedent), developer/publisher name self-chosen
(no entity needed), 5+ 1920×1080 screenshots + capsule art, a build Valve runs, a 2-week live
page, 30% cut.
page, 30% cut, and no subscription support.
## Product surface — retired
@@ -91,6 +111,11 @@ name. The creator will open the account; distribution work stays parked until th
Do not build these; each was explicitly ruled out.
- **Anti-piracy theatre (2026-10-31)**: a native helper DLL for "IP protection", obfuscation,
hardware locking, remote code that downloads and executes, and gating asset downloads as an auth
check. None make a licence enforceable; see `commercial.md` → "Anti-piracy posture".
- **Commercial structures (2026-10-31)**: Patreon or any subscription platform of our own, paid
early access, a paid beta, a gated Discord, and a Pro trial (the free tier is the trial).
- D3D11 swap compositor (superseded by the software compositor).
- OBS-style source expansion — game capture, browser-source zoo, media playlist, VLC, colour-key,
MIDI. The minimal source set is deliberate; creators who need more have graduated to OBS.
+3 -2
View File
@@ -13,10 +13,11 @@ Read the file whose row matches the task. There is no required reading order.
| [`capture.md`](capture.md) | The locked Background layer (screen/game/window capture, WinRT GraphicsCapture interop), the webcam seam + `CameraManager` sessions, MediaPipe background effects, and the vertical 9:16 tier's per-scene camera placement | Touching any frame source, the Background row, camera acquisition/conflicts, background effects, or vertical-tier camera geometry |
| [`output.md`](output.md) | The bundled `ffmpeg.exe` and the encoder subprocess (args, probe order, seams), local recording (REC/ON-AIR, filenames, private-broadcast close-out), and the WASAPI capture → filter → mix → named-pipe audio chain (TRAX, sync offset, ducking, limiter) | Touching ffmpeg args/bundling, encoder or recording behaviour, REC/ON-AIR, the audio mix and its meters, or loudness/sync problems |
| [`environment.md`](environment.md) | LAN hosts/IPs/SSH and the Gitea push recipe, the Windows `dotnet.exe` build + run commands, the test suite map, and the hermetic real-`MainWindow` test rule | Before building, running, adding a test, or reaching any box on the LAN |
| [`product.md`](product.md) | Brand/naming split, AI transparency, the GPL licensing prohibitions, the free-forever monetization posture, auth/account assumptions, and packaging/distribution | Branding, marketing, pricing, licensing, or packaging decisions |
| [`product.md`](product.md) | Brand/naming split, AI transparency, the licensing prohibitions, the freemium posture, auth/account assumptions, and packaging behaviour | Branding, naming, packaging, or a legal/third-party obligation |
| [`commercial.md`](commercial.md) | The live commercial policy: model and prices, the output-profile cap (stream **and** recording), Polar entitlement and channel binding, the channels (winget, Steam, Store), signing, the Founding 200 promo, costs, anti-piracy posture | Any question about money: pricing, licence keys, what free gets, how it ships, what a sale costs |
| [`youtube-api.md`](youtube-api.md) | Go-live ordering + the broadcast-binding fix, the private-only lock, health parsing, end-stream pre-flight, Test mode, and chat-insert shape | Touching go-live, broadcast lifecycle, health polling, streaming close-out, or the chat service |
| [`overlays.md`](overlays.md) | The social bar, the native alert box (six animations, alert clip, ticker) and the chat box conventions — everything composited over the frame | Adding or changing anything drawn on top of the output |
| [`decisions.md`](decisions.md) | Retired paths with cause of death: the paid tier and pricing, Polar, Store IAP, the Store route, the deleted updater, the rejected monetization ideas, and the permanent out-of-product list | You are about to re-open a decision that was already settled |
| [`decisions.md`](decisions.md) | Retired paths with cause of death: the paid-tier history and pricing, the free-forever era, Store IAP, the Store ordering, rejected monetization and anti-piracy ideas, and the permanent out-of-product list | You are about to re-open a decision that was already settled |
| [`ui-surface.md`](ui-surface.md) | The control surface, scene strip, preview rail, hotkeys, broadcast drawer, toasts, transitions, brand logo, launch geometry, and the theme/properties-panel conventions | Changing anything the creator sees: layout, controls, theming, properties panel |
## Split-out yet to come
+56 -61
View File
@@ -56,7 +56,9 @@ collaboration, not autonomous code generation.
## Licensing — proprietary since 2026-10-30
**LlamaCasty is closed-source commercial software.** `LICENSE` is the EULA; the paid tier exists
because the free tier caps output at **720p30** (creator ruling 2026-10-30, superseding free-forever).
because output quality is the paid delta — the free tier is capped at a 720p30 profile (creator
ruling 2026-10-30, superseding free-forever). Prices, entitlement and channels:
[`commercial.md`](commercial.md).
- **Every GPL build already published stays GPL for that snapshot.** Attribution/§7 terms
(`ADDITIONAL-TERMS.md`) are deleted and were GPL-only; the files are gone.
@@ -88,18 +90,21 @@ Apply this to every UI decision:
stream, not both; one reusable stream; one webcam; two mixer inputs). If a feature only sings on
a high-end chassis, it doesn't ship — the OBS escape hatch is open by design.
## Monetization — free forever, no watermark
## Monetization — free tier + Pro output quality
**All features are free and ungated** (creator ruling 2026-10-08, TASK 54): no feature lock, no paid
tier, no watermark. Money comes from gratuity and merch, not gating. **No licence chatter reaches a
user** — no keys, no expiry, no licence UI. Support is email + GitHub issues; an in-app bug reporter
is out of product. `IsPremium` gates nothing in v1.
**Every feature is free and ungated** (creator ruling 2026-10-08, TASK 54, kept by the 2026-10-30
freemium ruling): no feature lock, no watermark, and nothing licence-shaped in the output. The
paid delta is **output quality alone** — free is capped at a 720p30 profile, Pro unlocks the
higher tiers for **both the stream and the recording**. Prices, entitlement and channels:
[`commercial.md`](commercial.md). Support is email + GitHub issues; an in-app bug reporter is out
of product.
**The branding credit is OFF by default.** `MainViewModel.ShowBrandFlash` (internal static, default
`false`) is the master switch; `BrandFlashEnabled => ShowBrandFlash && !IsPremium` feeds the
presenter. The code is kept, not deleted — creator ruling: *"don't delete it, just make it
conditionally displayed."* `BrandFlashOutputTests` opts in by setting the switch before constructing
a `MainWindow`; `Credit_IsOffByDefault_EvenOnTheFreeTier` guards the default.
**The branding credit is retired as a paid delta and stays off.** `MainViewModel.ShowBrandFlash`
(internal static, default `false`) is the master switch; `BrandFlashEnabled => ShowBrandFlash &&
!IsPremium` feeds the presenter. The code is kept, not deleted — creator ruling: *"don't delete
it, just make it conditionally displayed."* Entitlement must never enable it.
`BrandFlashOutputTests` opts in by setting the switch before constructing a `MainWindow`;
`Credit_IsOffByDefault_EvenOnTheFreeTier` guards the default.
If it is ever enabled, the mechanics that matter:
@@ -117,14 +122,14 @@ If it is ever enabled, the mechanics that matter:
- **A mid-credit downgrade** cuts the advertisement on the next tick: the presenter re-checks its own
`Enabled` gate every frame rather than letting the credit finish.
Pricing, billing, the Store IAP plan and the rejected alternatives are history →
[`decisions.md`](decisions.md).
Live prices, entitlement and channels: [`commercial.md`](commercial.md). Retired pricing, the
Store IAP plan and the rejected alternatives: [`decisions.md`](decisions.md).
**Monetization awareness (built-in, ungated, free — 2026-09-01; v1 SCOPE per the complete-v1
ruling — build order: capture → report → journey → Alerts):** the app is monetization-aware by
design, for **every** creator, free and ungated (the only subscriber swap remains the branding-flash
removal above). It has three layers, all free — this is the product's differentiator, not a paid tier:
design, for **every** creator, free and ungated. It has three layers, all free — the capability no
competitor ships (the positioning order across features lives in `MARCOM.md`):
- **Reward-event capture (the data foundation).** The live-chat poll (`YouTubeChatService.Poll`)
receives every reward event over `liveChat/messages` and — since TASK 43 (2026-09-24) —
@@ -184,40 +189,32 @@ YouTube channel, they go to YouTube first. This assumption is explicit and must
replaced by an in-app account-creation step. Zero state = the Start Stream dialog's "Sign in to
YouTube" button; going live is unreachable until an account is connected.
## Windows packaging & distribution (direct + Steam; Store dropped 2026-10-22)
## Windows packaging & distribution (winget primary; Steam + Store parked)
**The Microsoft Store route is dead** — a brand on the publisher line needs a Company account and
a legal entity. Cause of death and the abandoned routes: [`decisions.md`](decisions.md).
Live channel policy, the artifact and signing costs: [`commercial.md`](commercial.md). Build
mechanics (publish flags, GitHub Releases, the winget manifest): [`Distribution.md`](../../Distribution.md).
Retired routes and cause of death: [`decisions.md`](decisions.md).
**The route now:**
1. **Direct download from `llamacasty.com`** — the app is **free forever** (TASK 54), so there is
nothing to bill in v1.
2. **Steam when $100 exists** — Steam Direct is $100 per product (recoupable after $1,000 AGR),
accepted categories include *Audio/Video Production* / *Player Tools* (OBS Studio is the
precedent), the **developer/publisher name is self-chosen** so the brand needs no entity,
5+ screenshots at 1920×1080 + capsule art, a build Valve runs, and a **2-week live page**
before release. Valve takes 30%.
3. **Polar is dormant, not deleted-in-principle** — chosen checkout/licence provider if a paid
tier ever returns; $50 already paid. `Distribution.md` §4.2/§4.5 holds the design.
4. **The Microsoft Store: not pursued.** The MSIX package stays as a working artifact and is
submitted nowhere. History: `TASKS/research-store-certification.md`,
`TASKS/task-48-distribution-msix.md`.
**The channels, in order:** direct download from `llamacasty.com` (binaries on GitHub Releases) →
**winget**, the primary install path → Steam (parked, $100, lifetime Pro as DLC only) → Microsoft
Store (parked, $19 Individual account — the only storefront that bills a subscription natively).
**Consequences that are architecture, not packaging detail:**
- **⛔ The updater is now MISSING, not deleted-by-design.** Velopack and its bootstrap were
removed on 2026-10-22 (TASK 48 slice 3) because the Store was going to deliver updates — that
premise is gone. An update path must come back, and
`ytLive.Tests/StorePackagingTests.cs` (which asserts no updater returns) must be rewritten
with the chosen updater rather than left to veto one.
- **The MSIX package still builds** via `scripts/package-msix.sh` (TASK 48 slice 2) — publish
- **⛔ There is no self-updater, by policy as well as by history.** Velopack was removed on
2026-10-22 (TASK 48 slice 3) because it downloaded *and executed*, which Store policy 10.2.2
forbids — and the same rule would close the Store for good if it came back. Updates arrive
through the package manager (`winget upgrade`) plus an in-app "newer version exists" banner read
from a version file on GitHub Releases. `ytLive.Tests/StorePackagingTests.cs` must keep asserting
that no self-updater returns.
- **The MSIX package stays buildable** via `scripts/package-msix.sh` (TASK 48 slice 2) — publish
`Release -r win-x64 --self-contained` into `artifacts/msix-stage`, copy
`Packaging/Package.appxmanifest` in as `AppxManifest.xml` + `Packaging/Assets/`, then
`makeappx pack` → `artifacts/LlamaCasty.msix` (159 MB, gitignored; `MSIX_PFX` signs it for a
local install). The manifest is a **full-trust `packagedClassicApp` at `mediumIL`** with
`runFullTrust` + webcam + microphone. `Square310x310Logo`/`Wide150x150Logo` traps are in
`MyMistakes.md`. Logos come from the app's own artwork via `scripts/make-store-logos.py`.
local install). It is the Store channel's artifact, unsubmitted until that account exists. The
manifest is a **full-trust `packagedClassicApp` at `mediumIL`** with `runFullTrust` + webcam +
microphone. `Square310x310Logo`/`Wide150x150Logo` traps are in `MyMistakes.md`. Logos come from
the app's own artwork via `scripts/make-store-logos.py`.
- **⛔ Bundle ffmpeg — no runtime downloads** (was Store policy 10.2.2; still right for a direct
download, and it fixes the 2026-09-01 404). See [`output.md`](output.md) → "FFmpeg locator".
- **⛔ 64-bit Windows only (creator ruling 2026-10-09).** Both csproj files set
@@ -226,10 +223,12 @@ a legal entity. Cause of death and the abandoned routes: [`decisions.md`](decisi
is the win64 build, ONNX Runtime 1.31 ships no win-x86 native (only win-x64/win-arm64), and a
32-bit address space can't hold the 1080p frame buffers. Windows 11 is 64-bit-only anyway.
Public copy says "64-bit Windows 10 or 11".
- **Portable mode is the distributable's shape:** `portable.txt` beside the exe keeps the layout DB
and settings in `.\data\` (hung off `LayoutPathOverride`), so a USB stick carries someone's
scenes. The `winget` install and the hand-to-a-friend zip are the same artifact.
**What does NOT change: the monetization posture.** The app is **free forever with no watermark**
(TASK 54, 2026-10-08), so `IsPremium` gates nothing in v1 and the branding flash is OFF by
default. `Monetization` above governs.
**What does NOT change: no watermark and no feature gating.** The free tier is the whole app at a
720p30 profile. `Monetization` above governs.
### ⛔ Durable invariant: full trust, or recording silently breaks
@@ -250,28 +249,24 @@ trust. No `broadFileSystemAccess` capability is needed, and none should be added
error.** A comment at `DefaultRecordFolder()` is owed **when the manifest lands** (TASK 48
item 6) — not before; a comment describing a manifest that doesn't exist is worse than none.
### Signing — do not buy EV
### Signing — Azure Trusted Signing, never EV
Microsoft **removed the SmartScreen instant-bypass for EV certificates in March 2024**. An
EV-signed file now accrues reputation exactly like an OV-signed one, so EV ($400+/yr) buys
what OV (~$150–300/yr) buys. Signing is **not** instant regardless — a valid cert stops the
*malware* warning immediately, but "unrecognized publisher" clears only as SmartScreen accrues
reputation from real download volume. Cert validity is capped at **460 days** (recurring
line item) and private keys must live on an **HSM or hardware token**. **The 2026-10-22 ruling
is to ship unsigned and accept the "unrecognized publisher" warning** until download reputation
accrues — buying a certificate is deferred, not rejected. `Distribution.md` §4.3 was corrected
2026-09-27 (it previously recommended EV).
Microsoft **removed the SmartScreen instant-bypass for EV certificates in March 2024**, so EV
($400+/yr) buys what OV (~$150–300/yr) buys; both need an HSM or hardware token and renew inside
**460 days**. The 2026-10-31 ruling is **Azure Trusted Signing (~$9.99/month)**: Microsoft-issued,
individuals eligible after identity verification, and it accrues reputation without a certificate
purchase. Until the profile exists, builds ship unsigned and the "unknown publisher" line is
accepted. Signing never clears the warning on day one either way — only download volume does.
Signing steps: [`Distribution.md`](../../Distribution.md).
### Distribution and licensing are independent — and the channel decision does not decide licensing
### Distribution and licensing are independent — the channel never decides billing
A **Store-distributed** app *may* still verify licences with **Polar** (Store policy 10.8.1
explicitly permits a secure third-party purchase API for non-game PC products), so "which
channel?" never implied "which billing?" — route B was a real option. The 2026-10-22 reversal
proves the point in the other direction: dropping the Store did not by itself restart Polar,
because the **2026-10-08 free-forever ruling** (TASK 54) had already removed the paid tier.
Polar is therefore *dormant*, ready if a paid tier ever returns, and nothing in v1 depends on it.
The lesson worth keeping: the licensing choice rides on a **monetization** decision, not on a
distribution decision.
channel?" never implies "which billing?". **Polar is the live provider** (2026-10-31) because the
2026-10-30 freemium ruling created something to sell; winget has no storefront at all, so the
licence path is entirely ours there. The lesson worth keeping: the licensing choice rides on a
**monetization** decision, not on a distribution decision.
### ⛔ "Only when the user says so" is enforced by Windows, not by us