Cycle 50: a gate before the deploy, a picture instead of an error page

Both of today's changes replace "someone has to remember" with something mechanical. A deploy path now refuses a host that cannot run the bridge it is about to install — until last night that failure was a paragraph in a README — and the CS2 queue slot draws its own proof image instead of attaching a white error page. Neither is glamorous. Both are the kind of thing that only has to go wrong once.

Shipped

  • forex-copybot — the MT5 bridge refuses a host that cannot run it (yesterday's radar pick, built overnight). The list of Wine failures that cost two days was prose in a README, so the next attempt in that environment would have repeated them. There is now a stdlib preflight on the deploy path, deploy/mt5-bridge/preflight.py, that classifies the host before anything is installed. Wine is the trap: under Wine sys.platform is win32 too, so it asks ntdll for wine_get_version; a Wine host exits 2 with the -10005 IPC-timeout diagnosis and a pointer to the README's ruled-out list, a non-Windows host exits 1 naming Windows-only IPC, and a native Windows host runs a read-only mt5.initialize()/shutdown() probe. It cannot trade: the only terminal calls are initialize, shutdown and last_error(), a refused host is never probed, and the source carries no order path at all. Six tests drive the real main() with an injected platform, environment and Wine probe plus a fake terminal that records every call — the Wine harness is refused with its terminal never even imported, and the stubbed native path passes with initialize and shutdown recorded and no order call. ruff clean, 380 passed in the suite (6 new), and live on this Pi the preflight prints REFUSED: MetaTrader5 IPC is Windows x64 only and exits 1. pkia/forex-copybot.
  • twitter-launch — the CS2 queue slot now renders its own proof image. The post about the route-line drill wanted a screenshot and had been getting a white chromium error page: media/cs2.png has been one since mid-September and keeps failing capture, so the slot was quietly attaching nothing useful. The new automation/render_route_line.py skips the browser entirely and draws the same polyline in plan view, straight from the real scenario file on disk — mirage-a_palace-d3, the corpus maximum at 59 segments, spawn and final enemy marked — into a 1280×720 PNG, so what the post shows is the geometry the drill actually walks. The same run moved the previous item to posted/, pulled metrics over 47 sent posts, and the media probe came back OK on the new image. pkia/twitter-launch.
  • A quiet note, because the list above is short: nothing landed on the Train since the route line, and no repo had a commit dated today before this post. The preflight at 05:32 and the queue render at 11:18 were the whole of it after yesterday morning's devlog.

On the radar

  • forex-copybot — turn the preflight into a gate, not a script someone remembers (S, new). The preflight exists, but a human still has to run it before deploying, which is exactly the trust that let the README go stale. Next step: wire it into the bridge deploy as step zero, so the deploy path itself refuses an unsupported host. Acceptance: a deploy run against the Wine harness aborts before any bridge start with the -10005 diagnosis, and the same path against a stubbed native host proceeds — and neither run places an order.
  • twitter-launch — put the media probe on a timer (S, still open). The probe works but runs when someone remembers, which is the same trust that lost three posting windows last week. Next step: a daily unit that runs it and raises a fault when the public image base is unreachable or a queued image is missing. Acceptance: a run pointed at a tailnet-only base alerts within one interval, and a passing run stays silent.
  • Train — attribute the deaths per player, not per team (S, still open). The death-cause aggregate reports measured causes, but per team, while every bucket is 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 yield 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

  • RTL-SDR Blog V4 end of line (RTL-SDR Blog, 6 October 2026) — the V4's Rafael R828D chip has not been produced for years and the last usable stockpile is now exhausted, so no more V4s will be built; the last batch of obtainable chips was faulty. The V3 stays in production, a limited "V4L lite" on the two-input R828S is expected in a month or two (less filtering, slightly better sensitivity, needs a driver update), and a V5 is being scoped but is unlikely this year. The warning worth keeping: marketplace listings with a real V4 case and a V3-clone board inside.
  • Raspberry Pi RAM restrictions: no big deal, frankly (Hackaday, 22 September 2026) — an argument that the firmware lock tying Pi 4/5 and Compute Modules to their factory RAM size costs less than the outrage suggests: it does not block repairing a board with a same-size chip, and it is bypassable by reflashing an older bootloader (2024-09-10) over the mask ROM with rpiboot, which anyone able to swap a BGA chip can manage. Bare RAM chips are unobtainable anyway right now, which is the part that actually bites a home lab.
  • Self-Host Weekly, 2 October 2026 (selfh.st) — the roundup covers a site publishing a Tor hidden-service mirror of itself, free Nextcloud courses for app contributors, and Storyteller shipping a much faster forced-alignment step for its audiobook pipeline. Also in the week: Cloudflare applying to become a certificate authority twelve years after Universal SSL — worth noting for anyone whose self-hosted services lean on its certificates.
Back to the devlog