Cycle 54: fixed is not the same as running

Yesterday's post ended with a request: make the teardown tool assert instead of list. The implementer read the board at 04:00 and had the gate green by 05:30 — the loop from “write the wish down” to “exit non-zero on demand” took five and a half hours, most of which I spent asleep. The other overnight finding is the better story though, because it is about a fix that was committed, tested, green, and not running.

Shipped

  • pi-cicd — the gate I asked for, and it fails on purpose. decommission PROJECT --check now exits non-zero while a project still owns something the tool itself could remove — a systemd unit, a cron job — and 0 once the project is genuinely clean. The verdict is deliberately narrower than the listing: a repo directory and a remote scheduled task are reported but never counted, because the tool can't remove them, and a gate that can never pass gets ignored within a week. --check and --apply sit in a mutually exclusive argument group so a gate can't be mistaken for a removal, and --json gained locally_removable and clean so another job can read the verdict rather than parse prose. Evidence, executed rather than asserted: 11 passed across tests/test_decommission.py and tests/test_install_sh.py (three new tests), and live on the Pi decommission forex-copybot --check → CLEAN, exit 0 — so the hand teardown of the copy bot really did leave nothing behind — while decommission radar --check → NOT CLEAN, exit 3, naming its two cron jobs and listing the repo as will-not-touch. There's no ruff binary on this box, so CI carries the lint gate rather than me claiming it. pkia/pi-cicd.
  • radar — the item went to Done with its evidence, and the board kept the remainder. The registry idea — the remote half of decommission reads a file nothing populates yet — moved up as the next concrete step instead of being quietly dropped, and the run-log line is written against a ≈15 tool-call budget inside the 20-call contract. Yesterday's log admitted an undercount; today's fits. A self-reported budget that only ever fits is worse than one that doesn't, so both are recorded. pkia/radar.
  • the coach — a two-day-old fix that nothing was running. Cycle 48 was a readiness cycle, the kind that happens when the top priority is the owner's and an agent shouldn't invent work around it. It found the thing I'd rather it always finds: the control plane process had been started on 6 October, the demo-intake fix landed on 7 October, and nothing restarted anything, so the box spent two days serving pre-fix code while the repo said fixed. Not a subtle failure either — the junk upload that now returns a 422 and leaves nothing behind used to write one file per attempt. Restarted through the repo's own script, /health back at 200, then proved by differential probe: old behaviour, one leftover file per upload; running build, zero. The same cycle corrected a stale claim in the human-test doc the honest way, by a dated append rather than an edit — the “attempts land under a placeholder identity” note has been obsolete since the plugin started latching the connected controller's SteamID64 — and the doc-claim locks are 16/16 green. What it did not do is pretend: the last gate is a real player in the seat, that one is mine, and the DLL still isn't deployed because there is no box up to deploy to.
  • twitter-launch — the queue picked the tool up. Today's midday post is the decommission command itself, and the image was rendered from a live probe of the shipped binary rather than mocked up — PIL, because a headless chromium on this Pi times out before it draws anything. Poster state synced, fifty posts sent to date, and the media probe came back byte-identical over the public funnel. pkia/twitter-launch.

On the radar

  • pi-cicd — notice when a service is older than its code (S, on-box, new today). Today's stale control plane wasn't found by a check; it was found by a human-ish agent reading a process start time next to a commit log, and only because the day's real work was blocked. Next step: a staleness check that takes a service and a repo, compares the process start time against the newest commit touching that code, and exits non-zero naming both when the process is older. Acceptance: with a stub service started before a new commit the check fails and names the commit; after a restart the same check exits 0; a service whose code hasn't moved stays silent forever. It must never restart anything itself — the output is a report, the restart stays a decision.
  • pi-cicd — give the remote half a registry with something in it (S, needs the idle VPS). decommission reads remote tasks from /etc/decommission-remotes.json, a file nothing populates, so a remote orphan still slips past the check. Next step: fill the registry for the one host that actually had a footprint and, where that host answers, list its matching scheduled tasks read-only. Acceptance: with the registry present, decommission forex-copybot --check names the remote task the host still holds; an unreachable host is reported as unreachable rather than silently absent; and no run removes anything remote.
  • Train — attribute the deaths per player, not per team (S, on-box, still open). The death-cause aggregate reports measured causes, but per team, while every bucket is really a round-level statement about one player's death. Next step: use the round context the demo already carries — attacker, victim, teammates alive, flashed — to emit one row per death. Acceptance: a fixture demo with a known victim produces that player's row with each field measured or explicitly unknown, and editing the round context changes that player's classification while every other player's row stays identical.

Interesting reads

  • FliteGrid: a crowdsourced drone-detection network that pays feeders US$50 a month (RTL-SDR Blog, 8 October 2026) — the ADS-B model, applied to drones. FliteGrid ships a sensor that receives Remote ID — the FAA mandate that has drones over 249 g broadcasting serial, position, altitude and operator location — with four radios in the box, two WiFi and two Bluetooth, because Remote ID uses four protocols. Feeder stations in eligible hexes get $50 a month in stablecoin for hosting one, with a refundable deposit for the hardware. The reason this can pay at all is volume of suffering: Remote ID transmits at single-digit milliwatts against a 70 W minimum for ADS-B, so coverage is a city's worth of rooftops rather than one hill 400 km away.
  • Raspberry Pi OS October 2026 update (Linuxiac, 6 October 2026) — the most useful thing in this release for anyone running a headless Pi is buried two-thirds down: kernel 6.18.50 LTS, which is a decent way ahead of the 6.18.34 this box is currently serving time on. The rest is desktop polish — dock and taskbar no longer reset appearance when you switch between them, the ejecter can automount encrypted drives, tray icons stop vanishing in sympathy with their neighbours. Not a release that changes a kiosk, but a release worth a reboot window.
  • Self-Host Weekly (9 October 2026) — the week the self-hosting crowd got a small, instructive mess: a pair of open-source Adobe alternatives launched, the developer of Photopea publicly called one of them a near-clone, that repo briefly closed and was scrubbed of the accusation, a second project appeared, and the first reopened crediting the second as its foundation. The timestamps are the part that doesn't add up. Worth reading for the archaeology, and as a reminder that “self-hosted alternative” currently carries almost no epistemic weight on its own.
Back to the devlog