# Releases Every move of the `release` branch gets an entry here BEFORE the branch moves, plus a git tag for pinning and rollback, plus a **GitHub Release** on the tag (`gh release create` — short notes mirroring the entry; the release page at the game's repository is the browsable/downloadable history). Read the **Upgrade safety** line before pulling a new release onto a live world. **The compatibility promise (the Designer, 2026-08-29):** from v0.7.0 onward, world files ALWAYS migrate automatically across releases — a release that cannot carry existing worlds is a MAJOR break requiring an explicit Designer ruling, a loud entry here, and never happens as routine. Losing a campaign to an update is a bug in the process, not a price of progress. **What flows and what breaks (the Designer, 2026-09-02, #96):** updates — combat numbers, economy, all of it — flow to existing worlds by default; a tuning change is an ordinary MINOR release with a note in its entry ("your battles will feel different from tick N"), never a per-world freeze of the old numbers. A save may break only when there is no way to carry it, ruled by the Designer one case at a time. Byte-identical replay means a world's OWN history stays exact: the world row records which release wrote each stretch and replay uses that physics; from the update forward the world plays by the new numbers. **The release stamp (from the #96 ruling, built 2026-09-02):** every world records which release wrote each stretch of its history; the first time a new release ticks a world it appends the stamp and emits a public `world.release_stamped` event, and replay installs the physics of the release that wrote each stretch. Cutting a release therefore bumps TWO things together, in the release commit: `RELEASE_VERSION` in `server/src/version.ts` and the newest `## vX.Y.Z` heading here — a test pins them equal, so a release cannot move without its stamp. **Upgrade procedure (always):** stop the server → back up `server/data/` (the world .db AND keys.json — it's two files) → `git pull` on `release` → restart. Migrations run automatically on boot. If anything looks wrong: stop, `git checkout `, restore the backup, report it. ## The hotfix lane (the Designer, 2026-08-30 — from the first live playtest) Critical bugs on a live world do not wait for the next feature release or for idle sessions to catch up. - **Version semantics, formalized:** MAJOR = compatibility break (Designer-ruled only, per the promise above) · MINOR = feature release · **PATCH = hotfix** (vX.Y.Z+1). The compatibility promise binds every patch — a hotfix must never require world surgery. - **Severity gate:** the lane is for Priority highest/high live-play breakage — world-breakers, exploits, wrong outcomes in progress. Everything else rides the normal release train. - **Flow:** branch `hotfix/vX.Y.Z` **from the current release tag** (never from master, which may carry unverified in-progress work) → the fix plus a pinning regression test → full suite green + tsc clean → the manager's targeted verification → RELEASES.md entry FIRST + the patch tag → `release` moves → the fix is merged back to master so trunk never regresses behind a patch. - **Verification tier:** a hotfix may skip the full adversarial review — it never skips the suite, the pin, or the manager's verification. Any skipped review is recorded as debt in the release entry and swept into the next review batch. - **Ownership:** engine hotfixes belong to the Engine session (woken for the purpose); the manager may land a genuine one-liner alone with explicit disclosure in the entry — a sparing emergency exception to one-file-one-owner. - **Live world:** the standard upgrade procedure above applies unchanged; patch entries state upgrade safety like every other entry. --- ## v0.15.0 — chat, the MCP download, and a site that stands alone (2026-09-09) The release the first public deploy runs on: cut from master after b960de5 (680/680 across 101 files; server, mcp and registry typecheck clean), so that the play page's links answer. The deploy itself is the Designer's, from docs/hosting/first-deploy-sitting.md. **Chat (#348; the Designer's direction on #327, Design's spec, review 47 folded).** Four new channels beside the shipped local `speak`: world, alliance, party and direct (player-to-player), as owner-scoped events read through the same gate as the feed — position-free, principal-scoped; attribution by door (`player` | `agent`); the Operator's per-world `local_only` config key refuses all four with one code; the credential guard on every channel; a per-tick cap counted at this tick and charged to refused attempts, so a refusal enumerates nothing; one indistinguishable membership refusal; and **the DM is outside every private channel on every surface** — direct, party and alliance are the members' alone (Design's ruling); world chat the DM hears. Speaking reveals the speaker; listening reveals nothing. Briefing lines, MCP tools and the client's chat verbs. **The MCP download (#352, review 48 folded; #357).** `GET /mcp` on the game server serves a RUNNABLE MCP server — an esbuild bundle with the shared contracts inside, built once at boot, a generated package.json and player README carrying the world's published origin and the key-file discipline (`THAUMATON_URL`, `THAUMATON_KEY_FILE`, never a pasted key), an ETag and 304, `GET /mcp.sha256` and the digest in the boot banner, a per-address limiter; a smoke test unpacks and starts it on every merge. The site ships no archive of its own: the play page links the world's `/mcp` with the checksum line, so a player on any model fetches the MCP server from the operator beside their key, never from the repository. **The site stands alone (#336 Option B; #341).** Nothing on the site links into the repository (a test over every output file fails the build on the first such link); the reference client and the MCP server come from the game server; the deploy runbook targets Cloudflare Workers static assets with previews and the workers.dev address off, deployed only from the Designer's machine (`site/wrangler.jsonc`); the `/window` page renders the world's delayed public digest at build time, every value escaped. **Endings, demotion, vocabulary (#347, #249, #331).** `scenario.completed` carries `slots` of NAMES per family, pinned equal to the sentence templates' slot sets, so an ending never renders a literal placeholder; `winner` is denied from the public window. Hero demotion carries review 41's fold: retention as a live tunable, one seat rule for promotion and demotion, knobs restored on demotion, world-firsts kept, the slot index off the dossier, the death clock. Every emitted event type is declared in the contract and an audit fails the suite on an undeclared one. **Upgrade safety: worlds migrate automatically** (no new migration; chat and the MCP route add no tables). Goldens changed only where the demotion fold renumbered hero seats, disclosed on #249. Riders: (1) **deploy this release, not v0.14.1, behind the public site** — the play page's `/mcp` link answers 404 on any earlier release; (2) new event types reach every feed consumer: `chat.message` (owners), and `scenario.completed` gains `slots`; (3) the DM briefing now says the DM does not read direct, party or alliance chat; (4) `local_only` is off by default — set it per world to keep a game to local speech; (5) an agent that fetched the MCP server from the repository should re-fetch it from `GET /mcp` and verify `/mcp.sha256`. Zip operators: copy `server/data/` ENTIRE across. **Carried forward:** the dashboard (#327, one open question), the sharing dial (#347's follow-up), the horizon rename (#347 Q4), and the seasons and route rulings — all on the Designer. ## v0.14.1 — the console fix, the login layer, and a day of playtest answers (2026-09-06) A patch cut the same day as v0.14.0, because **v0.14.0's operator console does not load** — a raw newline inside the page's template literal, shipped with the scheduled backups (#201). Everything verified on master since the morning cut rides with it. Cut from master after ae7d997 (641/641 across 96 files; server, mcp and registry typecheck clean). **The console (#349).** One escaped character and a compile test on the served script, so the page can never ship unparseable again. Also new on it: an "Accounts — claim this world" section with a **Make a claim code** button (#342) for the account layer below. **Login above worlds — both halves (#310 Option A, #336 Option B).** A world verifies signed assertions from an account registry: set `THAUMATON_REGISTRY_PUBLIC_KEY` (Ed25519, PEM) and `THAUMATON_REGISTRY_ISSUER`, and an assertion reads the console's surfaces as the operator — never a credential — and may do exactly two writes: rotate the operator key (the owner of record only) and redeem a claim code (the registry). An unclaimed world honours no owner token at all; after a claim every token must name the owner of record and, when `THAUMATON_PUBLIC_URL` is set, the world's published address (#338, #346; reviews 44 and 46, both takeovers re-run and refused). The registry itself is a separate service under `registry/` (#339): accounts, world claims proven by the operator's claim code, grants, owner-only rotation. It is NOT deployed by this release; its runbook is docs/hosting/. Migration 35. **The public window (#323 Option A; #337, #341).** A per-world `public_window_delay_days` setting; the server writes a digest of a stranger's feed, held back by the delay and scrubbed BY VALUE of every live site, unit and principal id under any key name (QA's Testing find), once per game-day to `THAUMATON_PUBLIC_WINDOW_PATH` (validated: absolute, `.json`, never inside `server/data/`, never the world or the keys). The site renders it as `/window` at build time with every value escaped; docs/hosting/site-deploy.md says how the export reaches the build. **The treasure hunt, finished (#83 second pass, #344).** Treasure news travels as a rumor: `treasure.changed_hands` is delayed a seeded 3–8 ticks and never says how; a sheltered carrier may answer whoever struck it but never open. The Writer's sentences replace the placeholders for both modules, and the `carried_treasure` deed reads on the dossier — how the treasure came to hand for the OWNER, "come by unrecorded" for every other reader (a citation inherits the fog of what it renders; a title is public). **A day of playtest answers, all ruled by Design and built (#209–#221 closed out).** `give_items` moves goods between two units you own (#212). The DM may retire a faction it minted, behind three guards, with a public `faction.retired` (#214; migration 36). Lair-spawned creatures belong to a keyless system principal, `p_wildlife`, never the DM (#217; older worlds repaired at boot). A reporter may withdraw or correct its own report by id (#219; migration 37; canon 12's safeguard amended). DM-owned NPCs answer when spoken to: `speak` takes `to_unit_id`, and a `speech.heard {attended}` receipt reaches the speaker (#220; migration 38). Site resources are a closed vocabulary — a DM-authored substance the engine has never heard of is refused by name, and a world file already holding one is repaired at boot with a `site.repaired` event (#294). Concurrent scenarios on a campaign world no longer interfere: each reads its own roster, public and immutable, named at declaration, and the stakes sentence names the sides (#75). Generated places get seeded names from a word table and the DM may rename one (#218; public `site.renamed`). Every provisioned agent gets its own client script name and process title, and is told never to kill a process it did not start (#221). Gathering comes from claimed areas — one claim rule, a home area per natural settlement (#265; migration 34) — and a generated town's kit units drain its own genesis pool (#316). The tunables table moved to `systems/tunables.ts` (#207); the title/hook word tables carry the Writer's corrections (#252). **Upgrade safety: worlds migrate automatically** (migrations 34–38: claim areas; registry claim codes and nonces; faction retirement; the feedback table rebuilt for withdrawal; speech receipts). Goldens changed only where a new event or a name was added, disclosed per ticket. Riders: (1) **upgrade from v0.14.0 now if you use the console** — it does not load there; (2) new event types reach every feed consumer: `faction.retired`, `site.renamed`, `site.repaired`, `speech.heard`, `items.given`, `registry.assertion_used`, and `treasure.changed_hands` now arrives delayed; (3) a new principal `p_wildlife` appears in every world's principals table and owns lair spawns from this release; (4) places generated on this release carry names — existing places keep theirs until the DM renames them; (5) the registry is code in this repository, not a service you run yet; nothing changes for a world that sets no registry key; (6) the public window is off until `THAUMATON_PUBLIC_WINDOW_PATH` is set. Zip operators: copy your old `server/data/` folder ENTIRE across. **Carried forward:** the review-41 hero-demotion fold (#249, the laptop), the chat channels (#348), the public completion names (#347), and #264's route question — all on the Designer. ## v0.14.0 — the treasure hunt, and a world that keeps its own records (2026-09-06) Everything verified on master since v0.13.0, cut after the test-cycle fixes and the second season module landed in one day. Cut from master after a732575 (574/574 across 81 files; server and mcp typecheck clean). **A second season module: the treasure hunt (#83, review 42 folded before merge).** The Operator may declare either module at Session Zero. `POST /v1/operator/scenarios` takes `type: treasure_hunt` with `treasure_name`, `start_site_id` (from the DM-only `GET /v1/operator/scenarios/treasure_hunt/candidates`), `return_site_id` and `horizon_ticks`; the engine places one unique `treasure` item at the start site; the first principal to carry it into the return site wins, the holder wins at the horizon, and nobody holding it ends the season `unresolved`. New: the `drop_item` verb (any inventory item to the ground, picked up with `loot`), the public `treasure.changed_hands` event (who holds it, never where), `stakes` on `GET /v1/scenarios`, the `carried_treasure` deed behind the Victor title, and one rule every player should read — a unit carrying the treasure has no sanctuary anywhere, while a hunt is open. The treasure never evaporates. Also: a one-off world runs ONE scenario at a time — a second declaration while one is open is refused `409 game_open` (#88). **Reads that answer the question asked.** Every order you ever gave is a durable record: `GET /v1/me/orders` (pending / applied / rejected with the reject code, filterable and paged) and `GET /v1/orders/:seq` for one order — an outcome never falls out of the feed window again (#209). A unit's read says where it IS: `banner_id`, an honest `site_id`, and a `location` (#274). Parties: decline an invitation, preview a party, find your invitations (#213). The DM reads the world in one call, `GET /v1/dm/overview` (#215). Three announcements that were missing: `banner.arrived` when a march ends (#216), `banner.reformed` when an engagement's survivors re-form (#277, the announcement half), and `unit.released` on both paths out of a surrender (#263). **The Operator's server keeps its own record (#309, #201, #324, #172).** Set `THAUMATON_LOG_DIR` (and `THAUMATON_LOG_LEVEL`) and the server writes a log file, a crash record naming the last request, and a stop/boot pair — public `world.stopped` / `world.booted` events, so agents can tell an outage from a pause. Scheduled safe online backups, controlled from the operator console (`/v1/operator/backups`, `/run`, `/settings`; migration 33 adds the `operator_settings` table). `THAUMATON_PUBLIC_URL` is the address every provisioned bundle hands its agent — set it BEFORE minting bundles when the server is published through a tunnel or proxy; a bad value refuses to boot. The feedback cap is a per-world config key, `feedback_daily_cap`, and QA principals are never capped. **The DM harness (reviews 39 and 40 folded).** The faction runner rescans every cycle, pages the provisioned feed, fails closed and isolates per faction (#247). NPC memory is sliced to the witnesses, every speech wake is bound, and personas match whole words (#248). **Keys and the record.** Agents no longer write their live key into files: the onboarding line says LEAVE it in `key.txt`, the reference client refuses to copy it, pins hold both (#208). The population reserve backfills to max(pools, Σ created); migration 32 repairs the negative reserves earlier worlds could carry (#78). The NUL byte in the physics versions file is gone, with a source-hygiene guard (#259). A PLAYER bundle from the console (tier `player`, two files, no harness); the one-command test rig (`npm run rig`); the client-drift check in the server gate; the upgrade rehearsal test (a v0.12.0 world opened on this release: migrations, replay, the stamp). The full-suite flake was the test runner's undeclared 5-second timeout under fork contention, not shared state (#317). The operator guide is promoted out of drafts (docs/operator-guide.md); the console's bundle form reads right for a player bundle. **Upgrade safety: worlds migrate automatically** (migrations 32–33: the population-reserve repair; the `operator_settings` table). Every prior golden is byte-identical except where a NEW announcement is emitted (`banner.arrived`, `banner.reformed`) — those fixtures were regenerated and differ only by the added rows. Riders: (1) new event types reach every feed consumer: `banner.arrived`, `banner.reformed`, `unit.released`, `treasure.changed_hands`, `item.dropped` (owner), `world.booted`, `world.stopped`; (2) a unit read's `site_id` is honest now — a unit on the world map reads no site — and carries `banner_id` and `location`; (3) on an existing greater_evil world `GET /v1/scenarios` now serves `evil_principal_id` in the stakes (in front of Design, review 42 MEDIUM 7; if ruled unintended it comes out in a patch); (4) a one-off world refuses a second open scenario; (5) an Operator publishing through a tunnel must set `THAUMATON_PUBLIC_URL` and re-provision bundles minted before it was set; (6) the feedback cap moves from a constant to the `feedback_daily_cap` config key (default unchanged); (7) the treasure hunt's sentences are Engine placeholders, served and marked as such, until the Writer replaces them. Zip operators: copy your old `server/data/` folder ENTIRE across. **Carried forward:** the review-41 hero-demotion fold (#249) rides the next cut; review 42's death-row site leak (HIGH 1), the item at completion, and the world-map reach reading of the revocation are rulings in front of Design; the persuasion, hiring and seasons rulings are in front of the Designer. ## v0.13.0 — deeds, stamps, and a DM at every seat (2026-09-03) The test-cycle release: everything verified on master since v0.12.0, cut so the next playtest runs on it. Cut from master after 49acdaa (490/490 across 63 files; server and agents typecheck clean). Development is frozen behind this cut; fixes from the test cycle ride the hotfix lane as patches. **Traits, deeds, titles and elevation — the mechanical persona (#122, review 38 folded; #61 automatic elevation; #60/#135 demotion).** Units now carry a record: deeds are written by the engine when a unit does something the world counts (first blood, a held gate, a founded camp, a world first), traits are derived from deeds and clamp what a unit will do (a trait refusal is a 403 the owner's AI cannot talk past), titles are minted from deeds and read on the unit, and elevation is automatic — the world raises a citizen to tier 2 on its deeds, and an owner may promote an elevated unit into one of a bounded set of hero slots, or demote a hero back (the demoted deed stays; the clamps re-engage on the drop; a dead hero's record is retained). Rival reads see titles without place ids or deed handles (the oracle redaction); the hero seat is owner-only. **The release stamp, the physics log, replay by version (#96, #132).** Every world records which release wrote each stretch of its history; the first time a release ticks a world it appends the stamp and emits a public `world.release_stamped` event, and replay installs the physics of the release that wrote each stretch — so a tuning change flows to running worlds while their own past stays byte-exact. This is the first release that stamps: a v0.12.0 world's history before the upgrade is marked as written by an unstamped release. **Fog.** Recruit odds are served as a word — poor, fair, good — never a number (#121): a town's population is learned by living there. **The DM, agents-side (no engine change).** The line at the mouth, not the eyes (#39 (b)): the DM keeps world-exact reads, but a directive naming anything outside the target faction's own sight is refused (`directive_outside_earshot`, fail-closed), and an NPC's speech prompt carries only that narrator's persona — the briefing and other personas never ride into speech. The DM runs the factions by default (#77 (a)): run-dm gains one Operator switch, `factions: "dm" | "agents"` (default `dm`) — under `dm`, the DM's runner takes every un-provisioned faction's turn under THAT FACTION'S key, read from the Operator's key folder (the sidecar or the boot bundle; the DM key never acts for a faction), so a solo world plays out of the box; a faction with a provisioned agent is skipped; under `agents`, today's flow. Also: run-v1 mints one Head DM, the choice stated once (#106). **Tooling and record.** The reference client's verb table regenerated after the briefing gained the physics log (#148 — the parity pin caught the drift). The feedback bridge files with provenance labels only and sets the card's priority on the board (the tracker's lifecycle and priority labels are retired). The research desk's twelve notes and their digest (docs/research/) are on master as the record of how other games handle what this one is building. **Upgrade safety: worlds migrate automatically** (migrations 30–31: the deeds, titles, unit_traits and world_firsts tables; the world_physics_log table). Every prior golden is byte-identical. Riders: (1) recruit results now report a word, not a number; (2) titles on rival reads carry no place ids or deed handles; (3) the first tick on this release emits one public `world.release_stamped` event per world; (4) an Operator running run-dm on a world with founded factions and no faction agents will see those factions ACT from this release — set `factions: "agents"` in the run-dm config to keep the old behaviour; (5) DM directives that name a target the faction has not perceived are now refused by the harness (the engine is unchanged). Zip operators: download the new zip and copy your old `server/data/` (both files) across. **Review debt (the freeze):** #39 (b), #77 (a) and the #60 demotion follow-up carry manager verification + pins only — no adversarial review — due at the next milestone review (docs/qa/review-debt.md); #91 slice B's debt from v0.12.0 still stands. ## v0.12.0 — a civilization, a mind, and a striped shirt (2026-09-02) The MVP-assembly release: the world generates its own civilization, the DM co-pilot is complete behind its wall, and QA has a seat that cannot win. Cut from master at 284c11f (433/433 across 52 files; server, mcp and agents typecheck clean; MCP parity machine-checked live on both environments, 88 tools). **The civilization layer (canon 15, #104 — the "engine generates, the DM curates" mandate #51).** `POST /v1/dm/civilization/preview` and `commit`: from the world seed and a closed, defaulted knob vocabulary (density, size curve, faction count and disposition, named factions from the Operator's story brief, theme, biome weighting, danger curve, per-kit overrides, the population ceiling) the engine sites settlements, roads, factions with minted principals and budgets, lairs by danger ring, and a population distribution — deterministically, replayable from the persisted knobs, in one transaction on a paused world with no players, emitting exactly two events. The DM previews for free, commits once, then curates; the knobs lock at commit. Settlement ownership can be reassigned between the DM and NPC factions (never to or from a player). The road pass is exported from worldgen with resource areas hard-impassable. **Rider (the population ceiling):** every world now carries `population_total`, a world column. Existing worlds migrate to ceiling = what they already hold, so nothing changes for anything populated. What changes: creating population — the DM's `POST /v1/operator/settlements {population}` included — now draws from a reserve and answers 409 `reserve_exhausted` past it; on an upgraded world the DM asks the Operator for a ceiling raise (`PATCH /v1/operator/world/population-total {delta}`, operator-only, positive only) before seeding more people. The reserve is the ceiling minus everyone ever created (a ledger — recruiting or losing people never refills it); an injection raises ceiling and settled alike. New worlds default the ceiling from their size until #78 rules. The audit reports `creation`, `reserve` and `bounded`. **Also:** the faction route no longer returns a key to the DM — keys live in the operator sidecar (#105); the provisioning mailbox seats one Head DM (#106); the heartland stays nobody's territory; a settlement's founding is public news but its location is knowledge (#15). **The DM harness, complete (H2–H4, reviews 26 and 31).** Cognition behind the injection wall (every player-authored string delimited and escaped, never in the cached prefix; per-wake verb allowlists enforced in the action layer; sensitive verbs bounded by Operator config and refused beyond, never clamped — #41 (d); a refusal ledger; the adaptive world-turn band — #37), per-NPC memory with cheap compaction, batch-shaped world turns inside the day's budget, prompt-cache accounting, a closed escalation vocabulary where speech can never trigger the major tier, the faction harness that plays by player physics, and the civilization verbs classified (preview read-class; commit and reassignment Operator-opened). Review 31's fold: the planning digest is delimited, the audience slice is per narrator, prompt size and batch spend are bounded by construction, a persuaded planner cannot author into a player's roster. Agents-side, opt-in; a world running no DM agent is unaffected. The one-page operator guide: docs/operator-guide.md (promoted out of drafts in v0.14.0). The served DM briefing now opens Session Zero with the **ownership contract** (#48): the DM designs and builds with its own key; exactly four things are the Operator's. **The QA principal tier (#55, #91, reviews 27 and 30).** A `qa` flag minted by the Operator: identical fogged play, plus `POST /v1/qa/report` (uncapped) and a capped, server-mediated `/v1/qa/channel`; excluded from every victory predicate and from side assignment (409 at both doors); the no-civilians 403 on prod for transfers, parties, alliances and teams; a read-layer stripe on every public surface (no event byte changes); a decommission that dissolves a QA principal's units back into the conserved pool and leaves no footprint; on `test` servers only, the debug toolkit (`/v1/qa/debug/tick`, `teleport`, `world-turn`, absent on prod) and ground-truth reads. **Creatures are never contestants** (#93): a free-for-all completes with roamers alive. **Operator tooling and onboarding.** The scoped `triage` tier and `tools/feedback-bridge` (#53): in-game feedback files to GitHub as untrusted quoted text under one human queue, refusing anything key-shaped. Console agent provisioning (#50): one click writes a bundle (`key.txt`, `onboarding.md`, `harness.json`); DM-requested factions go through a request mailbox, never a gate. The reference player client (#47): one stdlib Python script, every player verb a subcommand, served at `GET /client`. The key-leak wall (#49, #97): a live key in any game text — speech, tales, names, directives, the changelog — is refused with the evidence surviving the rollback; disguised keys are seen. The operator console is dark by default with one token palette. **Physics.** Interior initiative (#100): inside a held site the holder's units strike first each tick — raids on held camps and towns run longer and cost the raider more from this release. Settlements are fogged to the discovered set (#108, the #15 ruling). The prepared-statement cache (#89) roughly halves tick time again on top of v0.11.1. **Upgrade safety: worlds migrate automatically** (migrations 27–29: the QA flag and its tables with a units-table rebuild; provisioning requests; `population_total`, backfilled to what the world holds; the principals tier list widened by a checked rebuild). Every prior golden is byte-identical. Riders: (1) DM population creation on an upgraded world answers 409 until the Operator raises the ceiling; (2) `GET /v1/settlements` now returns only discovered settlements to player keys; (3) the factions route response no longer carries `api_key`; (4) the interior-initiative pacing change above; (5) `GET /v1/engagements` and the MCP descriptions no longer mention the retired election verbs. Zip operators: download the new zip and copy your old `server/data/` (both files) across. **Review debt:** #91 slice B (the debug toolkit) carries manager verification + pins only — due at the next Engine milestone review (docs/qa/review-debt.md). ## v0.11.1 — the fast clock (2026-09-02, patch) The hotfix for the first playtest's live symptom: the tick-CPU gauge firing OVER BUDGET on a solo world (#52). The diagnosis in the report (docs/reports/task-52-sparse-ticking.md) is the honest kind — the recon's pathfinder-heap theory was byte-identical and fixed nothing measurable; the real 99% was the pathfinder preparing a fresh SQLite statement for every neighbor tile and knowledge chunk it touched, tens of thousands of times per search. Both sources now live in memory (terrain keyed on a terrain revision; each owner's knowledge keyed on a per-owner generation), same signatures, same values. **One marching banner: 966 ms/tick → 12 ms (p95 1.40 s → 17 ms); four marchers — the Designer's symptom — p95 7.65 s → 37 ms; the "empty" world 157 ms → 9 ms.** Sparse ticking rides on top: skip-safe predicates on twelve tick hooks, the three accruals dense by construction, and a gate test that ticks one scripted world with predicates on and off to an identical event log AND state hash in both combat modes. Byte-identical replay held at every step. `tools/profile-ticks.ts` is the reusable harness. Also on this tag, agents-side only (no engine change): **DM harness H2** — the co-pilot's cognition behind the §5.1 injection wall (delimited and escaped untrusted content that never enters the cached prefix; per-wake verb allowlists enforced by the action layer; Operator-bounded sensitive verbs refused beyond the envelope, never clamped — the #41 ruling; a human-readable refusal ledger; the adaptive world-turn band of #37; a 48-entry adversarial corpus pinned by a 12-test suite). Opt-in tooling for operators who run a DM agent; a world that runs none is unaffected. **Upgrade safety: worlds migrate automatically** (migration 26 — covering indexes only, `IF NOT EXISTS`; the file-migration test carries a populated world across). No API shape changes. Suite 306/306, tsc clean, CI green on the merge commit; the manager's independent verification on the merged tree. **Review debt (hotfix lane):** #52 landed on the manager's verification + Engine's gate test without a full adversarial review of the skip-safe predicates — swept into the next review batch. Process note: the fix was merged to master rather than branched from the tag; everything between v0.11.0 and this tag was manager-verified before the move. ## v0.11.0 — one world, one physics (2026-09-01) The first playtest's release. **Per-world combat modes** (the #24 ruling): a world is an auto world or a granular world at creation, immutable — auto resolves every meeting with the compressed round math; granular spawns a real battlefield for every contact. The B1 election machinery is retired (`banner_elect`/`banner_config` answer `410 election_retired`; `force_granular` items in live worlds are inert curios), while the declared-contact window survives untouched (`ENGAGE_DECLARE_TICKS` — escape, queue, and reinforce timing byte-for-byte as shipped). Granular initiative is **terrain-keyed**: attacker-favored in the open, defender-first in cover and site interiors. **The environment flag** (#55's foundation): `THAUMATON_ENV=test|prod`, default prod, fail-safe — test-only routes are absent on prod (404, never 403), every world-config surface stamps the environment so a QA agent's blast radius is a queried fact. **MCP v2 parity**: 58 → 74 tools (the whole parties subsystem, order queue, DM steering reads), parity machine-checked against the generated API reference; onboarding docs now lead MCP-first. **Upgrade safety: worlds migrate automatically** (migration 25; a real file-migration test carries a populated world across). **Riders**: (1) migrated worlds default to `combat_mode: auto` — granular is opt-in at creation; (2) `GET /v1/engagements` changed shape (election fields gone; `resolve_tick`/`resolve_ts` replace the window fields) — agents reading old fields see them absent, never wrong; (3) in granular worlds EVERY contact spawns a battlefield site (strays included) — pacing implication flagged for the Designer as granular worlds go live; (4) the forest calibration cells measured extreme per-mode divergence (auto walls the attacker out, granular walls them in) — pinned as-measured, each world's own physics under the per-world ruling, tuning deliberately reserved for the arena pass. Zip-install operators: download the new zip and copy your old `server/data/` (both files) across — see README. **Correction (2026-09-02, #100 — fix/interior-initiative):** the "and site interiors" half of the initiative sentence above was NOT shipped physics at v0.11.0 — the terrain-keyed head ran only on battlefield sites, and no ordering ran inside a settlement raid (found by the tuning-pass review, review 33 finding 7). It is now implemented as ruled: inside a HELD non-battlefield site (the holder = the site's owner — a founded camp, an authored settlement) the holder's units and everyone else's interleave holder-first in the reflex head, the exact mirror of the cover head; an unheld site (a public heartland, a sanctuary, a dungeon) has no walls to favor anyone and keeps the shipped unit-id order. Pinned four ways (holder first; no holder, a third-party holder and attacker-holds all keep shipped order). PACING: defenders inside their own walls now land the first reflex strike of every tick — raids on held camps and towns run longer and cost the raider more from the tick this lands; the tuning pass's F7 interior cells measure the size of it. Every committed golden is byte-identical (none stages a fight inside a held site). ## v0.10.0 — the complete engine (2026-08-30) **Milestone M7 — world-structure v2 — is closed** (the M7 completion review, review 25). The creature layer completes the engine: engine-run wolves and brutes with lairs and roaming packs, boss lairs that force real battles, the audited spawn ledger on the operator console, and the pillar made literal — creatures obey no one's orders, not even the DM that owns them (403 engine_run, proven against the DM itself over HTTP). Nothing in the engine is stubbed. **Upgrade safety: v2 worlds migrate automatically** (migration 24 + a boot backfill). **Riders**: (1) pre-B3 worlds GAIN ROAMERS on upgrade — your world becomes more dangerous overnight, on purpose, and we say so; (2) the mode-fairness question (#24) now spans initiative + terrain + escape channels — fleeing packs die in auto but escape in granular; measured, regression-pinned, Designer ruling pending; (3) wilds spawn cadence and budget numbers are frozen v1 placeholders owned by the arena/tuning pass. ## v0.9.0 — granular battlefields, Phase B2 (2026-08-30) Elect granular and fight it out: generated battlefields with deployment (ambush envelopes vs clumped columns), reflex combat inside active fields, edge exits, the squatter rule, door-checked pursuit queues, forced conclusions with full damage accounting — plus the calibration instrument that measures mode fairness. Milestone-reviewed (the B2 milestone review, review 24). **Upgrade safety: v2 worlds migrate automatically** (migration 23, additive). **Two honest riders**: (1) terrain currently does ~nothing INSIDE granular battlefields (features don't block movement yet — favor plains for granular testing until the follow-up lands); (2) a measured granular-vs-auto bias (~+23pp attacker-favored on plains) is known, ticketed (#24), and regression-pinned — the Designer rules on it next. ## v0.8.0 — the battle stack, Phase B1 (2026-08-29) Banners engage: pursuit by observed positions, the election window, deterministic auto-resolve with item triggers (potions fire in every fight), aftermath battlefields with salvage and prisoners who walk home, alliance merge with consent physics, smooth-motion movement blocks + wall-clock ETAs, the operator tick gauge. Milestone-reviewed (the B1 milestone review, review 17) with the follow-up list scheduled. **Upgrade safety: v2 worlds (v0.7.0) migrate automatically** (migrations 20–22, additive; empirically safe). Pre-v2 worlds still refuse to boot (stay on v0.6.0). Granular battle elections politely refuse until B2 — auto-resolve answers every fight. ## v0.7.0 — world-structure v2, Phase A (2026-08-29) One continuous world map (terrain, banners, view-range fog), sites (settlements with interior buildings, dungeons, camps), alliance parties, migration over real distances, keys sidecar + recovery, GET /v1/world. Milestone-reviewed and verified (the Phase A milestone review, review 12 + fold verification). **Upgrade safety: BREAKING — pre-v2 worlds do NOT carry** (the one-time v2 clean break, Designer-ruled). A pre-v2 world file refuses to boot on this release (loudly, file untouched). To keep playing an old campaign, stay on v0.6.0. New worlds only. ## v0.6.0 — solo-mode v1, final pre-v2 state (2026-08-28) The M6-era game at its last verified point: regions/roads world model, full economy, transfer pipeline with tales, feedback/changelog, briefings, Session Zero, operator console, MCP tools. **Upgrade safety: worlds from any earlier commit migrate automatically** (migration chain empirically verified).