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:
+3
-2
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user