OpenRiot v7.9.44 — The Seams Are Gone

“Report from Sector 7: user locked screen. Wall 37. Locked again. Wall 37. Locked again. Wall 37. Three locks, three identical walls, one very annoyed operator. We filed a bug. Then we filed a math paper. The Birthday Paradox is real — with 88 images, you’ve got a 90% chance of a repeat within 20 locks. The machine wasn’t broken. Statistics was broken. So we stopped trusting statistics. We built a shuffle that remembers what it showed you last time, and the time before that, and every time before that. No wall twice. Not until you’ve seen all eighty-eight. We also put a dash where a dash needed to go, taught the notifications to use capital letters, and removed an import that was dragging half the logging subsystem into a background goroutine. The Turing Police are still trying to figure out why their lock screen shows the same stock photo of a mountain. We’re on wall 71 and haven’t repeated once.” — The OpenRiot Crew, now showing wall 72 and counting, v7.9.44


Release Overview

Four seams. Four places where the machine was almost right but not quite — a binary name with a missing character, a lock screen that trusted randomness too much, a notification that spoke in lowercase, and a network checker that imported more than it needed. None of them crashed anything. But they made the machine feel like a prototype — the kind of roughness that whispers “someone didn’t finish this” every time you lock the screen and see the same wallpaper for the third time in a row.

We sanded the seams.


🔀 The Lock Screen Got a Memory

The old code was perfect, mathematically. crypto/rand. A fresh call every lock. True randomness from the kernel’s entropy pool. What it wasn’t was fair. With 88 walls in the rotation, true randomness clusters — hot streaks, cold streaks, the same wall twice in a row. The Birthday Paradox means you only need ~11 locks before a repeat becomes more likely than not. At 20 locks, it’s 90%. The code was doing exactly what we asked. The problem was what we asked.

The new system is a Fisher-Yates shuffle backed by crypto/rand. On first lock, the construct shuffles all 88 cached wallpapers into a random order, writes the order plus a position pointer to Locked/.cache/1920x1080/shuffle.state, and shows the first one. Each subsequent lock reads the state, advances the pointer by one, shows the next wall, and saves. When all 88 have been shown, the entire deck reshuffles — and the last wall of the old order is guaranteed not to be the first wall of the new one. No wall twice. No streaks. No statistical gaslighting.

The state file survives reboots, cache rebuilds, and image updates. If the cache changes (new walls added, old ones removed), the state invalidates and regenerates. Zero configuration. Zero user awareness. It just works.

We kept crypto/rand. We kept cryptoRandIndex. The randomness didn’t go anywhere — it just moved up one level of abstraction, from selection to ordering.


🪙 The Missing Dash (Thanks, scitesy)

Here’s how you know a machine is healthy: someone who doesn’t work on it can spot a bug from outside and send a fix. scitesy opened PR #5 with a one-character diff: the rofi blockchain menu was trying to launch zcashmini but the binary on disk is called zcash-mini. The menu failed. Every time. Because of a dash.

We propagated the fix to the i3 window rule and the icon table — two more places where the old name was hardcoded. Three files. Three dashes. The rofi menu now launches ZCash Mini on the first click.

The Turing Police would have renamed the binary to match the docs. We renamed the configs to match reality.


📡 The Network Checker Travels Lighter

CheckConnectivity runs in a background goroutine, pinging an external host to determine whether the polybar network icon should be green or red. When it couldn’t write its timestamp file, it called logger.Warn() — which pulled in the entire openriot/logger package for three lines of error output. On a cold path. In a goroutine. For a stderr write.

Removed the import. Switched to fmt.Fprintf(os.Stderr, ...). Also fixed the os.Remove error handling: it no longer warns when the connectivity timestamp file doesn’t exist, because a missing file on first boot is not an error — it’s Tuesday.

Three fewer warnings in the logs. One fewer import in the build graph. The polybar network icon works at init time without dragging a logging subsystem behind it.


📱 Capital Letters for Signal and Crush

runAppLauncher had a naming problem. When you launched Signal via the rofi menu or the --signal-launch command, the dunst notification said “signal already launched.” Lowercase s. The binary name. Not the app name. Same for Crush — “crush already launched” instead of “Crush.”

The fix was a third parameter: displayName. Two call sites changed. Notifications now say “Signal” and “Crush.” The kind of thing you’d never notice was wrong until someone fixed it, and then you’d never think about again. Which is the point.


📧 .mailmap: One Typo, Five Hundred Commits

If your git contribution graph looks empty despite months of work, check your email spelling. A .mailmap file now lives in the repo root. Single line. Maps CyphrRiot@protonmail.com to CypherRiot@protonmail.com. 516 commits. One missing e. Fixed.

The Turing Police would require a notarized name-change form filed in triplicate. We wrote eleven bytes.


🧾 Files Changed

File Change
source/lock/lock.go NEWshufflePick() replaces pure-random
  lock screen selection with shuffle-rotate;
  cryptoShuffle() Fisher-Yates via crypto/rand;
  state file persists order across reboots
config/rofi/blockchain.txt FIXzcashminizcash-mini in command
  and alacritty --class flag (thanks scitesy)
config/i3/config FIX — i3 window rule matches zcash-mini
config/window/icons.toml FIX — icon key zcashminizcash-mini
source/network/network.go FIX — Removed openriot/logger import;
  connectivity errors use os.Stderr directly;
  os.Remove skips ErrNotExist silently
source/commands/commands.go FIX — Signal/Crush launch commands pass
  displayName for proper notification text
source/commands/helpers.go FIXrunAppLauncher takes displayName;
  notifications use display name, not binary name
.mailmap NEW — Normalizes author email for git graph

🗣️ Final Words

“Lock three times. Three different walls. Lock eighty-eight times. Eighty-eight different walls. Lock eighty-nine times. A new order, and the last wall you saw before the shuffle is never the first wall after. The rofi menu launches what you click. The notifications say what they mean. The network icon turns green without importing a subsystem. The git graph shows one author for five hundred commits. None of this is flashy. None of it ships a new feature. But the machine no longer talks to itself in the wrong language. The seams are gone. The Turing Police would have shipped the bugs as ‘character.’ We shipped the fixes and called it a maintenance release — the kind that makes everything else feel possible.” — The OpenRiot Crew, after eighty-nine locks without a repeat, v7.9.44