docs(distribution): Steam is the only channel — the zip, winget and the Store are dead

The site said "Coming soon to Steam" while the app docs still said direct download plus
winget primary with Steam parked. One of them had to move, and the creator's ruling is
Steam exclusive: a free app on Steam with the paid edition as a Steam DLC, and the
$10/month plan sold off-Steam by Polar.

Records the constraint that shapes the code, not just the prose:
- Steamworks requires in-app purchases to use the Steam Wallet (Microtransactions doc,
  quoted in commercial.md), so the monthly is *stated*, never *sold*, inside a Steam
  build; the lifetime is plain DLC bought on the store page and read with BIsDlcInstalled.
- Entitlement is `steamDlcOwned || polarKeyValid`, both resolving to one OutputProfile.
  steam_api64.dll ships beside the exe and is a functional dependency, not the rejected
  "IP protection" native DLL — without it DLC ownership cannot be read. Launched without
  Steam, the app falls back to the free profile rather than refusing to start.
- Signing is moot: Steam installs never meet SmartScreen. Artifact Signing stays on the
  shelf for the day a non-Steam download exists. Year-one fixed cost is ~$115.
- The exe rename must land before the first depot upload — Steamworks warns about
  renaming a live exe.

Distribution.md is rewritten to SteamPipe mechanics (publish output, depot, steamcmd,
DLC wiring, clean-account purchase/refund test). product.md, decisions.md (a new
"Steam exclusive" entry with every dead vector), TASKS.md (Steamworks entitlement row,
Steam packaging row), ai.md, index.md and the TASK 48 banner follow. MyMistakes.md gains
the Steam rules that cost real time today: installs skip SmartScreen, updates are free,
the Wallet rule, and the recurring-billing caveat.
This commit is contained in:
2026-10-31 11:05:53 -07:00
parent 57ef9e7a5e
commit 8f79b20a18
10 changed files with 271 additions and 263 deletions
+22 -24
View File
@@ -1,37 +1,35 @@
# HANDOFF — 2026-10-31 (commercial settled; the surge week starts at the artifact, not the Text layer)
# HANDOFF — 2026-10-31 (Steam is the only channel; the site says so)
## State
- Branch `main`, level with `origin` through `7827d23` + `0b41b7d`; this doc unit is local.
- **Commercial is settled and written down**: freemium (free = whole app at a 921,600 px / 30 fps
profile, stream **and** recording), Pro $10/mo or $400 lifetime through **Polar with no server at
all** — the client calls the customer-portal API with the key, and channel binding rides in
`conditions: {channel_id}`. Signing is **deferred until two subscribers**; the Store account is
now free; binaries live in `llamacasty-releases` push-mirrored to public GitHub.
- **Support policy recorded**: email, best effort, no SLA, refunds on request; no training service;
a repeated question becomes a training video on `@llamacasty`. `MARCOM.md` holds the loop.
- `www.llamacasty.com` resolves and 301s to the apex (CNAME + YunoHost domain + LE cert + nginx
`.d` include). Recipe in `MyMistakes.md`.
- Branch `main`, level with `origin` through `57ef9e7`; this unit is local.
- **Distribution is Steam-exclusive** (creator ruling 2026-10-31): a free app on Steam with the paid
edition as a **Steam DLC**; the **$10/month** plan is sold off-Steam by Polar and *stated, never
sold*, inside a Steam build. Winget, the direct zip, the Store and the certificate that served
them are retired. `commercial.md` → Channels owns policy, `Distribution.md` the depot mechanics,
`decisions.md` the cause of death.
- **Entitlement is `steamDlcOwned || polarKeyValid`**, both resolving to one `OutputProfile`.
`steam_api64.dll` ships beside the exe; the app must start without Steam and fall back to free.
- **Site updated and deployed** (`a9d07ce`): "Coming soon to Steam" ×6, zero Microsoft references,
privacy page says Steam bills the paid edition. The CTA gains a wishlist button only when the
store page is public.
- `www.llamacasty.com` resolves and 301s to the apex. Recipe in `MyMistakes.md`.
## Next action
**Surge week, day 1: artifact shape.** `LlamaCasty.exe` rename (three pack URIs:
`MainWindow.xaml:14`, `OverlayHost.xaml:96`, `RenameRecordingDialog.xaml:5`), `scripts/publish.sh`
(self-contained win-x64, no test artifacts), `portable.txt` via `LayoutPathOverride`. It ends when
the zip runs on a clean profile.
Then: OutputProfile gate + TASK 53 geometry tests → entitlement seam + system messages → licence UI
and a real test broadcast. Day 5 if all four land: the visibility picker.
1. **Steamworks onboarding** (creator is in it now): NDA → identity → company details → tax
interview → payout bank → **$100 Steam Direct** → create the base app, note the App ID.
2. Then the surge slice: artifact shape (rename + publish + `steam_api64.dll`) → OutputProfile gate
+ TASK 53 geometry tests → entitlement seam → licence UI + a Steam-less launch test.
## Landmines
- **Nothing may gate a feature.** The only paid delta is the output profile. `ShowBrandFlash` stays
- **Nothing may gate a feature.** The only paid delta is the output profile; `ShowBrandFlash` stays
`false` and entitlement must never enable it.
- **The org access token never ships.** `organization_id` is public; the token is not. No claim
page, no callback endpoint, no key database — `conditions` does the binding.
- **The site publishes the model, never the numbers**, and its CTA stays "Coming soon to the
Microsoft Store" until the creator says the download exists.
- **No self-updater, by policy**: `winget upgrade` + a version banner. `StorePackagingTests` asserts it.
- **No checkout inside a Steam build** — the Wallet rule. The monthly is named, never sold, in-app.
- **The org access token never ships.** `organization_id` is public; the token is not.
- **The site publishes the model, never the numbers**, and never takes payment or links a checkout.
- **No self-updater and no version banner**: Steam updates the app.
- Pre-existing: the **full test suite hangs** (WASAPI teardown). Per-class runs are the way.
- Not every hex is a theme colour — `BorderColorPalette`/chat defaults are USER DATA; on-stream
graphics come from `OutputPalette`. A red settings control is still a bug.