Changelog
Server updates, fixes, and new features.
May 28, 2026
World map: goto destinations now visible
- New Bright-yellow goto lines. The World Map now draws a yellow arrow from each unit with an active goto order to its destination tile. Toggle on/off with the new Goto checkbox next to Trails. The arrow takes the wrap-shortest path through the map torus, same as movement trails.
- New Fog-of-war respected. You only see goto lines for your own units and your shared-vision allies' units — same scope as Trails. Enemy units that happen to be in line-of-sight don't reveal where they're headed.
May 26, 2026
Rankings & history now handle eliminated nations
- New Fallen civilizations are marked, not hidden. Once a nation has no cities and no units left, its Rankings row shows a 💀 Dead · turn X badge in place of live stats. Gold, science, cities, units and government are blanked out (they no longer mean anything), but the nation's final score is kept and it stays ranked by that score.
- Improve History charts stop at the moment of death. A dead nation's lines now end at the turn it was eliminated instead of flat-lining across the rest of the game. Score is plotted through the death turn; gold / science / cities / units stop at its last living turn. All pre-death history is left untouched.
May 21, 2026
New: Advisors Report — an AI cabinet per nation, every turn
- New Every nation now gets a strategic cabinet brief after each turn change. Six ministers (Military, Treasury, Science, Foreign Office, Interior & Culture, Bureau of Intelligence) plus a Chief of Staff roll-up, generated by Claude Opus 4.7. Each nation has its own consistent cabinet names (Andrew's Australia gets General Walters / Lady Ashbury / Director Vesper; Shogun's England gets General Pelham-Wentworth / Lady Marlborough / Director Stillingfleet; Tankerjon's Rome gets Legatus Aurelius / Quaestor Cornelia / Frumentarius Otho; etc). Names stay the same turn-over-turn.
- New Two surfaces. The Intelligence Briefing dashboard shows a compact inline summary: Chief of Staff banner + one-line headline per minister + per-advisor read more → links. The dedicated
/advisors.html page shows every minister's full diagnosis + recommendations + watch-list, with a turn dropdown for browsing earlier reports.
- New Strict fog-of-war. Each advisor only references what that player's actual game client would surface — own everything, ally data via embassy or shared-vision, public broadcasts (wonder builds, revolutions), met civs only. A player who hasn't met someone never sees their name in the brief. Embassy intel is extended through Alliance partners but not through peace+shared-vision pacts — that matches stock Freeciv 3.2 rules.
- Improve Calibrated analysis, not naive reads. Two hard rules baked into the prompt: (1) a "War" in your diplomacy panel is not a threat without combat events or visible enemy units nearby — old grudges with no troops on the map are correctly labeled "paper" and don't trigger mobilization advice. (2) Economic health is graded on income/turn trend, not absolute gold balance — 22 gold at +3/turn is healthy; 200 gold at −5/turn is the crisis. No tax-rate panic on a healthy treasury.
- Improve Wonder-race awareness. Embassy intel now includes each rival's in-progress wonders. The advisor computes finish-turn math (our shield_stock + surplus vs theirs) and won't push a wonder you can't reach in time without Caravan support — if the math doesn't work, it says so plainly and suggests an uncontested alternative.
- Improve Continuity across turns. Each minister sees their own previous-turn full advice plus the trail of their last two headlines. If a minister reverses course they must name the trigger (combat event, embassy reveal, price signal); otherwise the position holds. No more turn-to-turn whiplash.
- Improve Top nav cleaned up. All pages now share the same nav: Game Status · Correspondence · Intelligence Briefing · Advisors · World Map · Sign out. Admin-only links (View as, Map admin toggle, Admin) moved to a separate sub-bar below the main nav so it's the same nav for every user. Page widths unified to 760px across home, correspondence, dashboard, advisors, and changelog.
- Improve Cost discipline. The advisor pipeline uses Anthropic prompt caching on the static persona / FOW-rules system prompt — first call per turn pays cache creation; the remaining 15 player calls reuse the cached prefix. Roughly $2-3 per turn at current cadence (~$60/month), logged to
/data/saves/advisors.log per call.
May 21, 2026
Stability: No More Lost Moves on Deploy
- Fix Deploys and restarts were eating up to 5 minutes of moves every time — Fly's default
kill_signal is SIGINT, but start.sh only trapped SIGTERM, so the "save before shutdown" handler silently never ran. The container would die mid-turn and resume from the last 5-min autosave. Now: fly.toml sets kill_signal=SIGTERM + kill_timeout=15s; start.sh traps both INT and TERM; freeciv-server runs backgrounded under wait so the trap fires while the server is still alive and can actually process the save command; the trap polls for the new save file to land before exiting.
- Improve VM bumped to 1 GB / 2 CPU (was 512 MB / 1 CPU). The python dashboard builder was OOM-killing on 512 MB whenever it overlapped with a freeciv-server save flush.
- Fix Dashboard builder can no longer trample itself — turn-watcher and the periodic loop both call
generate_dashboard.sh, and on the old VM two concurrent runs would OOM-kill each other. The script now takes a flock (skips if a run is in flight) with a 120-s timeout so a wedged process can't hold the lock forever. The periodic loop also drops from every 5 min to every 30 min — turn-watcher already regenerates on every turn change, so the loop is just an idle-stretch fallback.
- Fix World Map link finally appears in the dashboard nav — the May 8 release shipped the renderer, the CGI, and the admin toggle logic, but the
dashboard.html edit that adds the actual "World Map" link to the top nav never made it onto the server. It does now. Per-player map renders are also cleared on every container start and after every turn change, so post-deploy hits get fresh HTML instead of stale cache.
May 20, 2026
Bulbs / Turn Everywhere + Per-City Stats
- Feature New "Bulbs" column on the home rankings — shows each player's science output from last turn, alongside Score / Cities / Units / Gold. Sourced from each player's
research.bulbs_last_turn in the save. A matching Bulbs tab is added to the History chart, and historical data is backfilled — every turn since turn 1 has the field in every save, so the chart looks like it was always there.
- Feature Intelligence Briefing cities table now shows more per-city detail — Size, Shields/T (last turn's output), Food (banked toward next growth), Build (banked toward current production), Age (turns since founded), plus existing Building and Improvements. Trade / gold / bulbs per city are not available — Freeciv doesn't serialize those, they're recomputed each turn from worked tiles + buildings.
May 20, 2026
Intelligence Dashboards: Unstuck After 8 Days
- Fix Per-player dashboards had been frozen at turn 66 since May 13 — the python builder that replaced the old bash version (turn ~64) pre-loaded every save file into memory at once. A fully-parsed
Save is ~10 MB; with 70+ saves accumulated it crossed the 1 GB VM's OOM threshold and got SIGKILL'd every run (rc=137). The flock guard added on May 13 stopped concurrent OOMs but didn't help the single-process kill. build_dashboards() in python/lib/dashboard.py now streams one save at a time and fans out to all 16 players inside each load — peak memory drops from ~760 MB to ~15 MB, and a full rebuild runs in <30 s. Output is byte-identical to the old version.
May 19, 2026
Editor + Gazette: Upgraded to Claude Opus 4.7
- Improve All Anthropic calls bumped from
claude-opus-4-6 to claude-opus-4-7 — Anthropic's current flagship Opus, same price as 4.6 ($5/$25 per MTok). Affects the editor's correspondence replies (respond_to_editor.sh), the Chronicle generation (generate_gazette.sh), and the streaming helper (anthropic_complete.py). Opus 4.6 is moved to "legacy" in Anthropic's docs but has no announced retirement; this is a pre-emptive freshen-up, not an emergency.
May 19, 2026
Editor: Replies Now Read Your Latest Letter
- Fix The Chronicle editor was responding to old context, not your most recent message —
build_messages() selected conversation history with ORDER BY created_at ASC LIMIT 30, which returns the oldest 30 messages. Any player with more than 30 messages on file (Minikeg, Kroony, Andrew, Peter, Shogun) had their newest letters silently dropped from the API call, so the editor would riff on themes from weeks ago instead of replying to what was actually written. Now selects the most recent 30 and feeds them in chronological order.
- Fix Case-sensitive name match could orphan a thread — if a message got stored with a different capitalisation (e.g.
Andrew vs andrew), it would split into a separate conversation. History lookup is now case-insensitive.
May 15, 2026
Chronicle: Lone Sidebar Spans Full Width
- Fix Rumour Mill no longer leaves a half-empty column — sidebar kinds (rumour mill, etiquette, looking back, lottery) are normally half-width so two can sit side by side. But when one ends up as the only column-flow section on its page (every other section already spans full-width), it used to render at half width with blank space beside it. The layout engine now detects that "lone sidebar" case and promotes the section to span all columns.
May 13, 2026
Dashboard Refresh Throttled (Server Slowness Fix)
- Fix Server was getting unresponsive after ~17 hours uptime — the dashboard JSON rebuild was running every 5 minutes on top of the per-turn rebuild, and on the 1GB VM the OOM killer started reaping it. When that happened repeatedly the box ran out of headroom for the HTTP server and SSH, so the game kept running but the status page and dashboards stalled.
- Improve Dashboard refresh cadence dropped to every 30 minutes — turn-change still triggers an immediate rebuild, so per-turn data is just as fresh. The periodic loop is now only a fallback for long idle stretches.
- Improve Dashboard rebuilds can no longer overrun each other —
generate_dashboard.sh now takes a flock on /tmp/dashboard.lock, so if the turn-change rebuild is still running when the periodic loop fires, the second invocation skips instead of stacking up memory. A 120s timeout kills any wedged run so the lock auto-releases — no silent permafailures.
- Fix Restarts now actually save before exiting — the SIGTERM-save trap in
start.sh was never firing because Fly's default kill signal is SIGINT, not SIGTERM. Every restart was silently skipping the save and falling back on the 5-min auto-save (so up to 5 min of player moves could vanish on each reboot). Now fly.toml requests SIGTERM with a 15s grace period, and the trap catches both SIGTERM and SIGINT defensively.
- Fix Shutdown save actually requests a fresh save — even with the trap firing, freeciv-server was previously running as a foreground pipeline, so bash deferred the trap until freeciv had already died. The trap's
echo save > FIFO was hitting a dead pipe. Now freeciv runs backgrounded with wait, so the trap fires immediately, freeciv processes the save command, and we poll the save file's mtime (up to 10s) to confirm the new bytes hit disk before exiting. Player moves made right up to the moment of the reboot now persist.
May 8, 2026
World Map: Per-Player Intelligence Briefing
- New World Map link on the dashboard — a full hex-grid render of the world built from the latest save. Each player gets a fog-of-war view: tiles you've never explored render black; tiles you've seen show your last-known terrain; tiles you (or an ally) currently see are bright. Hover any tile for terrain, owner, city, and unit details.
- New Stale intel on enemy cities — cities you've previously seen render with a "T<turn>" badge showing when you last saw them, dimmed to indicate the intel is old. If you're allied with someone who has fresher intel on the same city, their data is used instead.
- New Movement trails — the last 10 turns of unit positions are drawn as fading lines in each unit's owner colour (own/allied units only — no peeking at enemy patrols). Wrap-aware: a unit crossing the world's edge takes the short path, not a line all the way back across the map.
- New Admin (see-everything) toggle — admins get a "Map admin: ON/off" link in the top nav. Toggle persists per browser; the server re-validates on every request, so non-admins can't bluff into it.
- Improve Authentic in-game graphics — terrain, cities, units, roads, irrigation, mines, fortresses, and resources all use the actual hexemplio + amplio2 sprite sheets from the freeciv tileset. Coast tiles use proper matched-corner shoreline rendering.
April 30, 2026
Chronicle Polish: Marketplace Layout, Q&A Styling, Letter Discretion
- Fix Marketplace no longer leaves a half-empty column — the commodities ledger now spans full-page width with a proper two-column grid (commodity name flexes, price right-aligned). Long names like "Tiger Piss (200L barrel, Antarctic grade)" wrap inside their own row instead of crashing into the price.
- Fix Interview emphasis no longer hijacked as a Q&A label — italic phrases at the start of an interview paragraph used to render as a brown small-caps block (the "asking a newspaper for intelligence" line on its own line in turn 60). The Q&A label styling now requires explicit opt-in via
<em class="q">; plain <em> stays italic and inline.
- Improve Letters column more discriminating — the gazette prompt now distinguishes "letter material" (public-facing rhetoric meant to be read by other leaders) from "inquiry material" (private DMs to the editor asking for info or favors). Inquiry material gets paraphrased in the editorial body if newsworthy, not reprinted as a letter. Also: no double-publishing the same correspondence in both an interview AND letters.
April 30, 2026
Civ Chronicle v2: Multi-Page Broadsheet
- New Multi-page newspaper layout — the gazette renders as a broadsheet with a lead story, columns, opinion pieces, breaking news, sports, classifieds, corrections, and more. Sections flow into each other in a magazine-style two-column layout instead of one long article.
- New Per-region World Weather + Hazard Watch — every edition now has a weather almanac with cartoon emoji icons and a per-nation forecast grounded in each capital's actual map terrain (Forest, Plains, Hills, etc.). A Hazard Watch ledger tracks war smoke, alliance strain, siege fatigue, and other game-driven omens with severity badges (LOW / MODERATE / WATCH / SEVERE).
- New Real crossword puzzle — the AI provides 8–12 era-appropriate words and clues; a JS solver lays them out into a real intersecting grid. Each clue has a "reveal" button (1 reveal per hour, enforced via local storage). Clues reference real game state and won't repeat words across editions.
- New AI-generated illustrations per article — up to 6 freshly-painted, era-appropriate images per edition (Egyptian frescoes in the Bronze Age, illuminated manuscripts in the Medieval, lithographs in the 19th century, etc.) at 16:9 wide aspect.
- New Editor mailbox + classifieds + letters to the editor — players can write to the editor directly; their messages may appear (paraphrased or quoted) in future editions. Every issue includes 6 era-appropriate classifieds, a letters column, and an in-character corrections & retractions block.
- Improve Streaming AI generation — chronicle generation now streams response tokens live to the terminal instead of going dark for 2-3 minutes. Failed calls dump full response bodies for diagnostics.
- Improve Email preview now handles v2 schema — turn-change emails were previously empty for v2 editions because the script only knew the v1 shape. Now correctly extracts the lead story + image and renders an email-friendly teaser block with the headline, byline, and a "Read the full issue →" link.
April 30, 2026
Status & Dashboard Builders Rewritten in Python
- Fix No more 30-minute lock-stalls on turn change — the bash
build_diplomacy and build_attendance functions iterated all save files and forked jq per relationship per turn, which on a 53-turn game took 30+ minutes and held the status-json lockfile the whole time. Cron runs every 5 min, so when the rebuild stalled, every subsequent run hit "Another instance is running, skipping" and status.json went stale for hours. The countdown timer would lock to 0:00 and the page reported a save_mtime from many hours back. Diplomacy and attendance rebuilds now happen in a python module (python/lib/) and finish in ~1.2s on the same input — a ~1500x speedup.
- Improve Per-player dashboards build in 1.6s instead of 9-24 minutes — same root cause (forks
jq per player per turn). Ported to python with proper dict-diffs.
- New pytest test suite — 64 tests covering save parsing, diplomacy, attendance, history, status, and dashboard building, against 53 real save fixtures committed to
python/tests/fixtures/. Runs in a Debian-bookworm Docker image so the dev environment matches prod (no mac-specific date/find surprises).
- Improve Always full rebuild, never incremental — at <2s per build it's not worth the bug surface of incremental state-replay logic. Self-healing: any corruption fixes itself on the next cron tick.
April 29, 2026
Chronicle Retries + Turn-Change Pipeline Logging
- Fix Chronicle retries when the AI hands back malformed JSON — turn 51's edition failed to publish because the model returned JSON with an extra closing brace and there was no retry. The generator now makes up to 3 attempts with 5s/10s backoff before giving up, which covers the most common transient failure (one bad sample at temperature 0.9). Turn 51's missing edition was regenerated manually.
- New Single timeline for the turn-change pipeline — every script that participates in a turn change (turn-watcher, status-json, gazette, dashboard, editor outreach, turn notify, auto-saver) now writes timestamped BEGIN/END events with elapsed seconds to
/data/saves/turn-pipeline.log. Logged through a shared helper (lib_log.sh) so all entries share an ISO-8601 UTC format. This is in service of diagnosing reports of the countdown sticking at 0:00 for hours after a turn change — next turn the log will say which stage stalled (lock contention, hung API call, slow archive cleanup, etc.).
April 24, 2026
No More False Turn-Reminder Emails
- Fix "Hey, your turn is due!" emails to players who'd already finished — the reminder script was forcing a save snapshot to read
phase_done for each player, then sleeping a fixed 4 seconds before reading the file. Freeciv writes saves directly to the target path with no temp+rename, so when the save took longer than 4s (it took ~5s on turn 47), the script read a partially-written gzip stream. Players whose section happened to land past the truncation point — like Ihop on turn 47 — were silently misread as having an empty phase_done, which the slacker check treated as "not done." Now the reminder writes to a -pending filename, polls the server log for the specific "Game saved as" confirmation of that save, then atomically mvs into place before reading. The status-page snapshot had the same race (its log poll matched any save, so a concurrent auto-save could unblock it early) — fixed in the same way.
April 23, 2026
Chronicle Accuracy & "In Print" Banner
- Fix No more phantom peace treaties — the Chronicle's diplomacy filter was keying off a field name that never existed (
.state), so the AI saw zero wars and zero alliances in every issue. That produced hallucinated headlines like "PEACE BREAKS OUT" when the world was, in fact, at war. Fixed to use the real .status field.
- Fix No more "Year 0 AD" emails — when
status.json was unreadable (usually a save-file race), turn notifications fell back to a wildly wrong linear year estimate that happened to land exactly at 0 on turn 81. Dropped the fake fallback; emails now omit the year entirely if we can't determine it rather than making one up.
- New "Stop the presses — in print" banner — while a new edition is being generated at turn change, the Chronicle page now shows a publishing notice instead of silently displaying a stale or in-flight edition. Prior editions stay navigable via the arrow buttons.
- Improve Emails wait for the gazette — turn notifications now refuse to attach the Chronicle block when the publishing marker is still set, when the latest entry doesn't match the expected turn, or when
status.json is inconsistent. A plain rankings email goes out instead of a broken-looking one.
- Fix No more phantom treaties — the Chronicle had been counting freeciv's automatic diplomacy transitions (Armistice → Peace maturing after a cease-fire period, Contact → Armistice as the default post-contact state, first-contact initializations) as if each were a newly signed treaty. Turn 45's "Andrew signs five treaties" headline was an artefact of this — in reality zero treaties were signed that turn; five automatic state maturations took effect. Events are now classified with a
negotiated_this_turn flag and the AI is told explicitly to distinguish matured states from new agreements.
April 19, 2026
Rankings: Turn-over-Turn Deltas
- New Change since last turn — Score, Cities, Units, and Gold columns now show a small green or red delta next to each value (e.g.
+12, −3) reflecting the change since the previous turn's on-disk snapshot. Deltas stay stable through the in-progress turn rather than jittering as players act.
- Improve Dropped "No-login" and "Last Seen" columns — these were noisy and not especially useful. Miss% already captures activity. The underlying data sources (
last_seen.txt and the idle_turn_streak / last_seen_epoch fields in status.json) are no longer generated or captured.
April 19, 2026
Chronicle PDF Export & Better Illustrations
- New Download any edition as PDF — each Chronicle edition now has a
PDF button next to the turn navigator. Click to save the issue as civ-chronicle-turn-N.pdf — a single-page newspaper sheet, perfect for archiving or sharing.
- Improve Front-page illustrations stay on topic — the gazette system prompt now requires the illustrator's scene description to depict a specific concrete moment from the lead story (named subjects, identifiable action) rather than abstract era imagery. Image prompts now lead with the headline and that scene description instead of diluting focus with the full front-page text.
April 19, 2026
Fix Chronicle False-Catastrophe Bug
- Fix Partial save reads no longer poison history — the status generator could accept a truncated gzip while freeciv was still writing the turn save, producing a history entry with only a handful of players. That's what gave us the turn 41 Chronicle headline "THE WORLD VANISHES: FOURTEEN NATIONS FALL SILENT". Decompression now checks gzip's exit code and requires a complete
[game] + player section before writing.
- Improve Chronicle preflight check — before generating an edition, the gazette now verifies the target turn's history entry has a plausible player count versus the previous turn. If it looks corrupt it rebuilds the entry directly from the save file, retrying up to 5 times with sleeps. If the data still can't be trusted, the edition is skipped rather than printing a false narrative.
April 11, 2026
Fix Gazette Generation for Large Games
- Fixed a bug where the Civ Chronicle gazette failed to generate when game data grew too large for shell command-line argument limits
- Gazette data and API request bodies now use temp files instead of inline arguments, preventing ARG_MAX overflows
March 26, 2026
Editor Chat Line Breaks
- Fix Player message line breaks — messages from players in the editor chat now preserve line breaks and paragraph spacing. Previously, newlines were collapsed into a single line. Contributed by peter.
- Improve HTML escaping — editor chat now reuses the existing
esc() helper for HTML escaping, replacing inline regex chains.
March 23, 2026
Intelligence Briefing Fix
- Fix Dashboard loading — the Intelligence Briefing page now loads correctly for all players. Non-admin accounts were seeing "Failed to load dashboard" due to a shell scripting bug in the API endpoint.
March 22, 2026
Write to the Editor
- New Write to the Editor — players can now log in and correspond with the AI editor-in-chief of The Civ Chronicle. Share tips, make proclamations, complain, or just chat. Everything is on the record.
- New Proactive outreach — each turn, the editor reaches out to 1-3 players for comment on newsworthy events. Targeted questions based on game state.
- New Email notifications — players receive an email when the editor replies or requests comment, with a link to continue the conversation.
- New Gazette integration — player correspondence is woven into the newspaper. The editor has full discretion to quote any on-the-record statements.
- Improve Editor context — the editor sees all player conversations (confidentially), the last 2 gazette issues, full game state, and diplomacy data.
March 22, 2026
Upgrade to Freeciv 3.2.4 (security fix)
- Fix CVE-2026-33250 — upgraded from Freeciv 3.2.3 to 3.2.4 to fix a recursive jumbo packet denial-of-service vulnerability.
March 22, 2026
Gazette v2: Richer context, dual AI providers, layout improvements
- New Dual AI provider — gazette can now use either Anthropic Claude or OpenAI. Set
GAZETTE_PROVIDER in .env.
- Improve Richer game data — gazette now receives wonders, culture, pollution, literacy, population, military casualties, spaceship progress, government changes, and public events from save files.
- Improve Multi-turn trends — 5-turn rolling data for score, cities, units, pollution, culture so the AI can identify trajectories.
- Improve Story-driven writing — revamped prompt produces analytical journalism instead of repetitive stat summaries.
- Improve Letters from citizens — letters now come from specific in-game cities and nations.
- Improve Classifieds — 3-6 detailed classified ads per issue with contact info, in a 3-column grid layout.
- Improve Front page layout — proper 2-column grid with illustration panel instead of float.
March 21, 2026
The Civ Chronicle redesign
- New Newspaper layout — the gazette is now a full newspaper with masthead, multi-column layout, serif fonts, and parchment styling.
- New Newspaper sections — Front Page, Economy, Military, Society columns with bylines and quotes from in-game leaders.
- New Opinion column — written in the voice of a real historical figure from the game's current era.
- New Letters to the Editor — fictional citizens react to events.
- New Classifieds — era-appropriate ads.
- New Corrections & continuity — each issue references the previous one, with staff continuity, running threads, and corrections when past rumors prove wrong.
- New Standings — player rankings table embedded in the newspaper.
March 21, 2026
Disk space fix & archived save cleanup
- Fix Disk full broke status page — archived saves from the auto-saver filled the 1GB volume (4,896 files). Status page, gazette generation, and game saves all failed silently. Cleared old archives and restored everything.
- New Automatic archive cleanup — on each turn change, archived saves from previous turns are pruned down to just the most recent one per turn. Prevents disk from filling up again.
March 19, 2026
Diplomacy: Contact vs War
- Improve Contact vs War — diplomacy now distinguishes between "Contact" (just met, no hostilities) and "War" (actual combat detected). War status is only shown when units have fought.
- Fix Status generation speed — diplomacy data is now rebuilt incrementally instead of from scratch every 5 minutes. Fixes status page going stale when the full rebuild took too long.
March 18, 2026
Open source & reliability fixes
- New Open source — the server code is now public at github.com/ndroo/freeciv.andrewmcgrath.info. PRs welcome!
- Fix Turn Done checkmarks — fixed a race condition where the status page snapshot could time out, causing all players to show as not done. Now polls for up to 10 seconds instead of a fixed 3-second wait.
- Improve Credentials cleanup — moved all secrets (SES, API keys, player credentials) out of the codebase into environment variables and gitignored config files.
March 17, 2026
Attendance tracking
- New Missed turns percentage — the rankings table now shows what % of completed turns each player missed (didn't click Turn Done). Color-coded: green <25%, amber 25-49%, red 50%+.
- New Idle turn streak — shows how many consecutive turns a player has been idle, right in the rankings table.
- New Attendance API —
/attendance.json tracks per-player missed turn counts and which specific turns were missed. Rebuilt automatically from save files.
March 15, 2026
Turn emails now read from the same data as the status page
- Fix Email rankings match the status page — turn notification emails now read from
status.json instead of parsing save files independently. Rankings, scores, and stats in emails are guaranteed to match what you see on the website.
- Improve Status page updates before emails send — on turn change, the status page is regenerated first, then emails go out. Previously they raced each other.
- New Test mode for emails — admins can send a test email to a single address with
--to=email@example.com.
March 14, 2026
Reliable status page, faster generation, and health monitoring
- Fix Status page stopped updating silently — a signal handling bug was killing the background generator process. No way to detect or recover until someone noticed the page was stale.
- Improve Switched to cron scheduling — status page now regenerates every 5 minutes via cron instead of a fragile background loop. If a run fails, the next one picks it up automatically.
- Improve Split status and history data — per-turn player stats (score, cities, units, gold) are now in a separate
history.json file that only appends new turns. The generator now parses just the latest save file instead of every save from turn 1, keeping it fast as the game goes on.
- New Health endpoint —
/cgi-bin/health returns whether both data files are fresh, with details on which file is the problem if something goes wrong. Ready for uptime monitoring.
- Fix Concurrent run race condition — added file locking so cron and turn-change triggers don't step on each other. Also fixed a bug where temp file cleanup could wipe files from other running instances.
- New Recovery tools —
--rebuild-history flag re-parses all save files to reconstruct history from scratch. Corrupted history files are automatically detected and recovered.
March 13, 2026
UncleS joins the game
- New 16th player added mid-game — UncleS (British) joined via save file editing with starting units placed on the map.
- New Mid-game player add command —
manage_players.sh add handles DB auth, save file editing, and welcome email in one step.
March 13, 2026
JSON-first status page
- Improve Rebuilt around a JSON API — the status page is now a static HTML file that fetches
/status.json and renders everything client-side. Makes it easy to build tools on top of the game data.
- Fix Stale "Turn Done" data — fixed a bash 5 bug where associative arrays weren't being cleared between runs, causing old phase_done values to leak through.
- New Test suite — 67 assertions covering every JSON field, idempotency, stale state regression, corruption recovery, and more. Uses real production save files as test fixtures.
March 11, 2026
Reboot-resilient turn timer
- Fix Turn timer survives reboots — on resume, the server reads elapsed time from the save file and sets the timeout to the remaining time. No more lost hours after deploys.
- New Manual timer override —
fix_turn_timer.sh lets the admin set a custom turn end time (e.g. extend to 4am for a slow day).
- New Email toggle — flip
email_enabled.settings to disable all emails without redeploying.
- New Gold editor —
change_gold.sh adjusts player gold via lua command.
March 11, 2026
Turn reminder and email fixes
- Fix Turn deadline calculation — was using save file mtime which got overwritten by the auto-saver every 5 minutes. Now tracks the actual turn start time in a dedicated file.
- Fix "Connected this turn" tracking — was counting all connections in the log instead of just connections since the current turn started.
- Fix "Last saved" display — now shows actual save file time instead of turn start time.
March 10, 2026
Initial release
- New Freeciv 3.2.3 longturn server — 23-hour turns, 10-hour unit wait time, running on Fly.io.
- New Live status page — rankings, countdown timer, phase_done indicators, history charts, mobile-responsive design.
- New Email notifications — turn change emails via SES with rankings and deadline info. Reminder emails 2 hours before deadline.
- New Auto-save and shutdown protection — saves every 5 minutes, plus SIGTERM-triggered save on deploy so no progress is lost.
- New 15 players configured across unique nations.