Skip to main content

docs truth pass

Every checkable claim in the user-facing docs, walked against the build and marked βœ” or ✘ (#233). This file is a dated record of a pass, not a live status page: it says what was true on a given commit and what was done about what wasn't. The live enforcement is tests/unit/docs-truth.bats, which turns each ✘ found here into a test so the same drift fails CI instead of a reader.


Pass 1 β€” 2026-09-02, against 94025c5​

Scope: README.md, docs/getting-started.md, docs/user-guide.md, docs/manual-testing.md, docs/branded-walkthroughs.md, docs/branding.md, docs/branding-and-distribution.md, docs/RELEASING.md.

Method: static β€” every claim checked against the shipping source (Go, frontend JS, workflows, images.json, brand.json), with the two channel-dependent behaviours confirmed by running the real resolvers (effectiveBranding(), GetSupportPolicy(), GetImages()) rather than reading them. Not a VM walk; see Still open below for what that leaves.

✘ Found and fixed (9)​

#WhereClaimedActually
1getting-started.md Β§4first screen reads "Try Linux alongside Windows β€” no repartitioning, nothing deleted, and fully undoable"reads "Bring Windows to Linux β€” keep everything." The quoted string is the JS fallback in launchpad.js, and defaultBranding() always sets a tagline β€” so the fallback is unreachable in every build
2manual-testing.md bug-report tableinstaller state at C:\wootc\install\state.jsonC:\wootc\state.json (app/state.go). C:\wootc\install\ does exist (wifi/, slurp/), which is why the wrong path read as plausible
3manual-testing.md Β§Before you start"The app refuses to start on battery"the app opens; it disables Install with "Plug in the power adapter first" β€” and only when a battery is actually detected (onBattery && batteryKnown), so a desktop is never blocked
4user-guide.md footerloop "verified end-to-end on real hardware (UEFI + Secure Boot + TPM 2.0)"evidence is the KVM VM rig (status.md). Real-hardware evidence is the unmet v0.2.0-alpha gate in ROADMAP.md
5RELEASING.md Β§User instructionsinstructions shipped in "the release notes / INSTALL.md"no INSTALL.md exists anywhere in the tree
6RELEASING.md"The published artifact is wootc.exe"release.yml publishes one exe per brand plus deployer-vmlinuz, deployer-initramfs.img, shimx64.efi, grubx64.efi, mmx64.efi, best-effort wubildr.efi, and SHA256SUMS
7README.md "What you get", user-guide.md Β§1 and Β§7"BitLocker-safe", "BitLocker is fine too", "wootc offers to put Linux on an unencrypted partition"BitLockerSupported: false on alpha and beta; gateScenario() hard-refuses and the Install button is disabled. manual-testing.md and RELEASING.md already said so β€” the user guide contradicted them, and a BitLocker reader would have downloaded and hit a wall the guide said was not there
8user-guide.md Β§2"The default (Yellowfin GNOME)"main.js pre-selects images[0]; in alpha GetImages() returns green images in file order, so the default is Bluefin LTS β€” which RELEASING.md Β§Alpha already named
9user-guide.md Β§4the "Bring your setup over" dashboardthe app calls it "Bring Over From Windows" (wootc-manifest.desktop, wootc-manifest-gui). That label existed nowhere in the product

Also aligned, having found the docs disagreeing with each other and with the code: the free-space figure. The launchpad gates on maxDiskSizeGB() < 20 with DISK_HEADROOM_GB = 15, i.e. 35 GB; user-guide.md and RELEASING.md both said "~40 GB" while manual-testing.md said 35.

βœ” Checked and correct (spot-check, not exhaustive)​

Paths β€” C:\wootc, C:\wootc\disks\root.disk, C:\wootc\logs\, C:\wootc\logs\deployer.log, C:\wootc\logs\deployer-last-journal.log, C:\wootc\channel.txt, C:\wootc\brand.json, C:\wootc\brand.css, C:\wootc\bundle\oci.

Registry β€” the Add/Remove entry is TunaOS (wootc) for the generic build (displayName = b.Name + " (wootc)"), as getting-started.md, user-guide.md Β§9 and manual-testing.md all say.

Commands and env β€” wootc.exe uninstall, winget install TunaOS.wootc, WOOTC_PRELOAD=1, WOOTC_CHANNEL, wootc.debug, just test, just build, npx playwright test.

Channel behaviour β€” default channel alpha; alpha offers green images only, no custom OCI refs, no BitLocker; the alpha image is ghcr.io/projectbluefin/bluefin:lts; images.json carries "status": "green" | "experimental" as RELEASING.md describes.

On-screen strings β€” "Restart into <distro> β†’", "Also delete my Linux data", "Make it feel like Windows", the disabled-Install reasons.

Exe names β€” Bazzite-Installer, Bluefin-Installer, Aurora-Installer, TunaOS-Installer all match their brand.json exeName, and the docs advertise no exe that no brand builds.

Links and images β€” every relative .md/.png link in the scoped docs resolves; all 20 branded walkthrough screenshots and all 12 GUI walkthrough screenshots are present.

Catalog β€” GNOME / KDE Plasma / Niri / XFCE on el10 / fedora / arch / debian, as README and the user guide describe.

Still open β€” needs the RC build and a VM​

These are not βœ” and were not claimed as such. They cannot be settled from a checkout, and the issue's done-when depends on them:

  • Walk each doc against an actual RC build in a Windows VM.
  • Timings: "5–15 minutes on a fast line", "30–60 minutes on a slow connection", "a few minutes". Measured, not asserted.
  • SmartScreen behaviour post-signing. Every SmartScreen and "unknown publisher" paragraph is written for unsigned binaries. Signing is a 1.0 criterion in ROADMAP.md; when it lands, getting-started.md Β§2–3, README.md and RELEASING.md Β§1 all change together.
  • Add/Remove rendering β€” that TunaOS (wootc) is what Settings shows, not just what the installer writes.
  • Regenerate every screenshot from the RC SHA. Deliberately not done here: the GUI and branded sets regenerate from the Playwright suites and the timelapse comes from the nightly, so regenerating them from main would date them to the wrong build. They must be dated from the RC.

Code observation, left alone​

launchpad.js renders state.brand?.tagline || '<long fallback>'. No build can reach that fallback β€” defaultBranding() sets a tagline and every brand.json overrides it β€” and finding ✘1 means it has already misled a reader once, via a doc that quoted it. Removing it is a frontend change and was out of scope for a docs pass; docs-truth.bats now pins the doc to the real brand.json tagline instead, so the two cannot drift again.