brink/REBOOT-DESIGN-AND-REQUIREMENTS.md at main · JavaDerek/brink · GitHub
Skip to content

Latest commit

 

History

History
541 lines (450 loc) · 38.1 KB

REBOOT-DESIGN-AND-REQUIREMENTS.md

File metadata and controls

541 lines (450 loc) · 38.1 KB

Balance of Terror — Reboot: Design & Requirements

Working name: Balance of Terror (the name is open). This document is the portable brief for a fresh private repo that cannibalizes parts of the current BalanceOfTerror engine and builds on a public fork of DMCP (github.com/shawnrushefsky/dmcp). It is written to be self-contained — a reader in the new repo needs no prior context. Origin: a 2026-07-24 playtest + design session that concluded the current architecture is the wrong shape for the game we actually want.


0. The pivot, in one paragraph

The original build was a deterministic wargame engine designed as a reinforcement-learning substrate — a fortress of invariants so an AI could be trained to play, with the human driving a rigid parse-or-die command grammar. Playtesting proved the mechanics all work and the game isn't fun: you fight the parser, a weak local model rejects your plain-English intent, and a silent timer ratchets you to nuclear war while you try to engage. The reboot abandons the training goal and becomes a single-player immersive roleplay: you are the supreme executive of a great power, handling only the geopolitical brief — taking calls from world leaders, hearing your advisors, making decisions — in a persistent world grounded in current real-world geopolitics, presented cinematically (voice, faces, a globe, the situation room). Mechanics become an honest substrate that keeps consequences real; they are no longer the foreground.

Dropping the RL goal is the load-bearing decision. It is what lets the LLM become the game-master instead of a translator, and it retires ~90% of the invariant fortress as unnecessary.


1. Experience pillars (what the player must FEEL)

Pillar 0 — Show, don't tell (the through-line; every other pillar serves this)

The whole game hangs on this, and it is a hard rule, not a preference: if the UI ever states a disposition or a raw value, it is a bug. No DOCTRINE: HAWK, no cohesion 80.0, no hostility: TENSE, no (DOVE advisor). Every fact the old build printed becomes something the player deduces from behavior, dialogue, and consequence.

Worked example — the dovish advisor. You never see a "dove" label. Your intelligence chief simply keeps telling you things are fine — "Korea's stable, nothing to worry about" — and then Korea keeps deteriorating anyway. Three turns in, your own gut says "…she's always too rosy; I need to discount her," and you've learned to distrust your own intel — a real tradecraft feeling a (DOVE) tag can never give you. Same everywhere: you infer the hawk from how he presses; you read hostility in the premier's face and tone on the call; you see Korea redden on the globe. The number is never on screen; the inference is the gameplay.

This is the E20 "stats-into-persona" direction taken to its end, and it is why the globe, the call, the avatars, and the voice matter — they are how state is shown.

The six felt pillars (all in service of Pillar 0)

  1. Inhabit the role. You are the executive. The interface is conversation and decision, not a command line. You never see a NOT_UNDERSTOOD.
  2. Take the call. The signature moment: an INCOMING CALL — MOSCOW lights up on the globe; you pick up; the Russian premier's face and accented voice are right there. That single interaction carries more of the fantasy than any stat readout.
  3. Consequence with stakes, not a timer grind. The world must be able to hurt you and must not let you talk your way out of physics — but the drama lives in the fiction, not in a countdown you're babysitting.
  4. Grounded in the real board, now. Ukraine is hot because it is hot today. Iran sits in a different bucket than it did six months ago. The situation refreshes from reality.
  5. Persists. How the powers feel about each other, where everyone sits on the ladder, the running history — all survive between sessions and across a long campaign.
  6. Cinematic. Voice, stylized leader avatars, a living globe, the situation-room aesthetic.

2. Core architecture: LLM-as-Game-Master over an MCP referee/ledger

2.1 The division of labor (the whole design turns on this)

  • The LLM is the Game-Master. It does three jobs: (a) classification — mapping a fuzzy fictional action ("I move on Ukraine") to which mechanic fires (a flashpoint seizure → a prestige contest); (b) narration & persona — the voice of leaders, advisors, the room; (c) calling the server's tools.
  • The MCP server is the referee + ledger. It owns (a) authoritative resolution — the odds, the RNG, the conservation math, the ladder update; (b) persistence — the whole world in a database; (c) the handful of inexorable rules the GM cannot talk its way out of.

This is the same conceptual split the current engine already uses (text → structured action → engine adjudicates), with the two things that made it un-fun fixed: the translator is now a frontier LLM-GM doing flexible tool-calls, not a weak model forced to emit a rigid schema, and the same LLM also narrates, so it feels like a game-master rather than arguing with a form.

Rules placement (decided): all mechanical rules live in the server. The LLM never adjudicates — it only recognizes which rule applies and narrates the result the server returns. Analogy: in a tabletop session the DM notices a moment calls for a roll; the dice and the math are not the DM's to fudge.

2.1a Resolve-then-narrate (the anti-desync contract — non-negotiable)

The failure mode a frontier GM can still hit: it streams "a triumphant diplomatic victory" while the tool it fired registers a catastrophic prestige loss. The GM telling you that you won while the database records that you lost shatters the immersion instantly. The rule that prevents it:

The GM never narrates an outcome before the server returns it. It calls the resolve tool, receives an authoritative outcome payload, and narrates from that payload. The payload carries an explicit narration constraint — the handful of facts the prose must honor (e.g. prestige −3, DEFCON ↑, Russia gained, tone: humiliating) — and the system prompt forbids narration that contradicts it. So the fiction can be as florid as it likes about the how, but it can never lie about the what. Resolve, then narrate. Never narrate, then resolve.

Masking the round-trip (so this contract doesn't cost you the phone-call budget). Resolve-then- narrate adds a mandatory tool round-trip before an outcome can stream — a silent gap if handled naively. Three layers hide it: (a) most turns don't resolve at all — pure dialogue streams instantly; only state-changing actions hit the tool. (b) For action turns, split reaction from outcome: the GM streams an outcome-neutral reaction to your words immediately (the premier's face hardening, "You want to what?" — no tool call needed), fires the resolve tool during that reaction, and delivers the outcome from the payload once it lands. The round-trip hides behind speech already playing. (c) A diegetic beat ("hold on — let me reach my staff") as the backstop when resolution is genuinely slow. The floor only bites on state-changing turns, and even then it's masked.

2.2 Why DMCP

DMCP is this exact pattern, already built and generic: LLM-as-DM, MCP server as persistent state + tools, SQLite, pause/resume for context management, a web UI. It gives us the ledger, the cross-session persistence, the context-window mechanism, and a UI scaffold essentially free. Our job is to supply the geopolitical rules core (ported from the current engine), the GM persona, the current-events refresh, and the presentation.

One deliberate divergence from DMCP. DMCP hands 100% of adjudication to the LLM ("the agent designs rules… adjudication remains entirely in the agent's discretion"). That is perfect for collaborative D&D and fatal for a nuclear standoff — a benevolent GM lets you win, and the brink stops being a brink. We keep a thin sliver of enforced rules (§4.2). Real geopolitics, real consequences, fictional faces.

2.3 The GM runtime: Claude via subscription (CLI-under-Max), keyless-first

The GM brain is Claude (a frontier model — which is what makes the classification in §2.1 reliable and retires the weak-local-model failures of the current build). It lives behind a thin GMBackend adapter — one streaming method: given game context + player action, stream narration and return the tool-resolved outcome. The MVP ships on one implementation, with a second held in reserve behind the same seam:

  • PRIMARY (ship this): CLI-under-Max. The thick Tauri client drives Claude Code (the CLI) headlessly under a Claude Max subscription, reached over a private overlay network (Tailscale or equivalent) when the CLI runs on a different machine from the client. Chosen for two reasons, and the first now outranks the second:
    1. Money-safety (§2.4). It authenticates with the subscription's short-lived OAuth token, not a standing pay-per-token API key. There is no reusable metered credential to leak, and the worst case if something misused it is a rate limit, not a bill — the financial blast radius is capped at the flat subscription. Given this project's history (a coding agent once read a metered key from a .env and ran up a large bill), that is the deciding property.
    2. Flat cost + a ready-made agentic MCP harness — the GM does multi-step tool reasoning ("read state → resolve → update relationships → decide if a crisis triggers") in one turn without us rebuilding the loop.
  • FALLBACK (deliberate opt-in only): SDK/API. The Anthropic Messages API / Agent SDK — cleaner, versioned, lower-latency, but metered per-token, which reintroduces the exact key-leak risk we are engineering out. It is therefore not an automatic swap: turning it on is a conscious decision that carries the §2.4 credential guardrails as hard requirements. Use it only if the CLI's latency proves unfixable — and even then, Claude Desktop + connector (keyless, but no cinematic UI) is the safer degrade if UI can be sacrificed.

Nail the GMBackend boundary, stream narration through it, and instrument first-token latency from day one — so if the CLI misses the phone-call budget, the decision to accept the API's key-risk is made on measured numbers, not vibes.

Two honest risks this primary path carries (accepted for MVP):

  1. Brittleness. Claude Code is a coding agent driven off-label as a game backend; an Anthropic update could change its headless/stream contract. Mitigation: the GMBackend seam, and pinning the CLI version.

    VERIFIED 2026-07-24 (issue #7) — path KEPT, as a soft dependency. Headless claude -p does bill to the subscription, provided no higher-priority credential is present. Three findings change the build:

    1. The precedence trap. Documented: "In non-interactive mode (-p), the key is always used when present." A stray ANTHROPIC_API_KEY anywhere in the spawning environment silently wins, with no prompt — this project's original bill-shock failure mode, reachable by an inherited env var. The launcher must therefore assert those vars are absent and fail loudly (now a §2.4 requirement), and must never pass --bare, which cannot use the subscription at all.
    2. Flat billing is true today, not durable. Anthropic's docs now call claude -p "the Agent SDK via the CLI," and a change moving exactly that surface onto a metered credit pool was announced and then paused on its effective date — paused, not cancelled (medium confidence; corroborated secondary sources, no live primary page found). It could return with no code change on our side, undoing the money-safety property. Monitor; keep a kill-switch.
    3. Rate limits are a hard stop, never a bill — explicit error, reset time, no automatic fallback to API billing. Exact Max-tier figures are unpublished; a 60–120-turn hour is inferred to fit a session window, with the weekly cap the likely bite point under daily play. Graceful diegetic degradation is issue #24.

    ToS: solo play on your own subscription is very unlikely to be what the enforcement language targets, but it is not a documented safe harbor — the clause telling developers "building products… should use API key authentication" carries no solo carve-out. Distribution is different and unambiguous: other players' turns through one subscription is explicitly prohibited, which makes §8's "each player on their own Claude" a requirement, not a preference.

  2. Latency is the death condition (sub-2s to first mouth-movement). The CLI adds harness overhead; hitting the budget needs care (no extended thinking on dialogue turns, a warm streaming session) — plus the react-first masking pattern in §2.1a. Measure early.

(Max limits / ToS: solo/household use is squarely fine. Funneling other players through your subscription is a grey area — the clean multiplayer topology (§8) is each player on their own Claude, all pointing at one shared referee server.)

2.4 Credential safety (hard requirements — not an afterthought)

The money that burned this project was a metered API key an agent could read and spend. The architecture makes that impossible by construction, and these are requirements, not guidance:

  1. Keyless by default. The MVP uses subscription OAuth (§2.3), so there is no standing pay-per-token key anywhere. Worst-case misuse is a rate limit, not a bill.
  2. No metered credential in the working tree — ever. If the API fallback is ever enabled, its key lives in the OS keychain or an env var set outside the project directory, never in a .env or any file inside the repo a coding agent operates on.
  3. Hard spend cap + a dedicated low-cap key. Any metered key is a separate key with a hard monthly workspace spend limit, used for nothing else — so even a runaway loop stops at the cap.
  4. Build-time and run-time credentials never meet. The agent that builds the client works against a mock GM / stub (or a throwaway key the human caps), never the real credential. The human installs the real auth at the end, on their own machine, outside the agent's reach.

3. What to cannibalize from the current BalanceOfTerror repo

The current repo's genuinely valuable asset is its rules core — years of getting the conservation math and crisis model correct. Port that; discard the fortress and the parser.

PORT (this is the referee core of the new server)

From current repo What it is Becomes
bot/prestige.py, bot/escalation.py zero-sum prestige transfer/settlement, stake math the enforced prestige-conservation rule
bot/state_engine/ (the resolution logic, not the parse gate) DEFCON ladder, red lines, state application the ladder + bounds + shared-loss floor rules
bot/crisis.py, bot/eruption.py, bot/hooks.py peripheral-eruption model, forced-move countdown, blind-spot-weighted crisis selection the crisis/forced-move tool + fog-of-war seeding
bot/compellence_trigger.py (E21, just built) seizing a contested flashpoint raises a prestige demand the "deed-driven demand" mechanic
bot/schema.py powers, flashpoints, soft/hard state model the entity model (mapped onto DMCP factions/resources/locations)
bot/principal.py, bot/selfplay/policy.py (doctrine characterization only) HAWK/DOVE dispositions, advisor bias seeds for leader/advisor persona prompts
bot/advisor_hint.py, bot/advisory_board.py, bot/comms.py advisor voice, rival communiqués GM persona material
docs/GAME-MECHANICS.md the code-grounded mechanics reference the spec for the ported rules
docs/DESIGN-DIRECTION-situation-room.md, the docs/BRINK_* + Situation Room HTML mockups the globe / call / hidden-info UI direction the presentation brief (§6)

LEAVE BEHIND

  • The rigid parser / intent-schema-or-die front end (bot/llm/parse.py gate, bot/play, bot/ui TUI). This is the villain. Replaced by the GM.
  • The RL self-play harness + determinism fortress (bot/selfplay/ as a training substrate, seeded-reproducibility-as-invariant). Goal retired.
  • The injection-proofing / saboteur invariants as hard build gates. Single-player, LLM-as-GM, no adversary trying to jailbreak a demand out of the engine — relax from "build-failing invariant" to "sensible hygiene."
  • The 8 architecture invariants as build-failing constraints. Most dissolve. Only the conservation/inexorability sliver (§4.2) survives, now as server-enforced rules rather than whole-repo invariants.

4. The MCP server: entities, enforced rules, tools

4.1 Entity model (mapped onto DMCP so we inherit its persistence + UI)

CORRECTED 2026-07-24 by the DMCP survey. Two mappings below were wrong, and both were load-bearing. (1) Never use factions.resources. DMCP has four disconnected numeric write paths, and only the resources table has a change-history table and a single write choke point (updateResourceValue()). factions.resources is an unaudited JSON blob with no bounds that silently deletes a value when it hits ≤0 — catastrophic for a conserved quantity. Every invariant-bearing number lives in the resources table; factions carry identity and goals only. (Note: that table's owner_type currently allows only game|character, so admitting faction-owned resources is a schema migration.) (2) Fog of war is not "a strong out-of-the-box match." DMCP's per-entity visibility is an opt-in filter, not an enforced boundary — get_secret's own description reads "DM view - shows all info." Nothing stops a caller from reading another seat's hidden state. Harmless for single-player (the GM is legitimately omniscient), but §8's "fog per-seat from day one" insurance is net-new enforcement work, not something inherited.

  • Great powers → DMCP factions (identity + goals only — not factions.resources). Start US / RUSSIA / CHINA; the refresh (§5) can widen the cast.
  • Relationships (directed "how they read each other" — credibility, hostility) → DMCP relationships with history tracking (bonus: the history is the diplomatic timeline for free).
  • Prestige, DEFCON → rows in DMCP's resources table (custom numerics with change history). attention/hours — cut (§9.2).
  • Flashpoints (regions with alignment + cohesion) → DMCP locations + resources.
  • Crises / forced moves (countdown, pre-debit, defuse-with-a-rival) → DMCP timed status effects
    • scheduled events (advance_time, tick) — with real consequences on expiry (§4.2).
  • Fog of war (which seat sees what; the advisor who overstates cohesion) → DMCP secrets & knowledge with per-entity visibility — a strong out-of-the-box match.

4.2 The enforced rules (the "sliver of fortress" — the GM cannot override these)

Kept deliberately small. These are the things that make consequence inexorable:

  1. Prestige is zero-sum and conserved across the powers.
  2. DEFCON is bounded [1–5] and moves only by the rules; DEFCON 1 = shared-loss nuclear war (no winner) — a hard floor.
  3. A crisis countdown ticks and lands regardless of the fiction — its on-expiry consequence is real state change, not narration. (This is the "the countdown doesn't care about your feelings" property that gave tonight's loss its weight.)
  4. (candidate) the attention/hours economy — cut (§9.2). It was wargame texture and cuts against "inhabit the role." The enforced list stays at three.

Everything else — whether an action triggers a contest, tone, pacing, which leader calls, how a scene plays — is the GM's.

4.3 Tools the GM calls (DMCP-style, illustrative)

open_session / get_briefing (compact world-state, §7) · classify_and_resolve_action (the GM hands a classified action; server adjudicates against the enforced rules and returns the outcome) · adjust_relationship · raise_or_defuse_crisis · advance_turn · log_event · plus DMCP's stock character/faction/resource/secret/visibility tools. Exact surface is a design task, but it stays small and the GM never writes an enforced resource directly — it goes through a resolve call.


5. The current-events refresh (the differentiator)

The thing nobody else is doing, and the reason this is a simulation and not just "nuclear standoff with a chatbot." A research/ingestion agent periodically reads current real-world geopolitics and normalizes it into game state: which regions are live flashpoints, each power's posture, the relationship temperatures, emerging crises — written into the entity model with temporal versioning (so "Iran now vs. six months ago" is a diff on a history-tracked entity, not a rewrite).

  • Seam: DMCP's multi-agent collaboration tools ("external agents push lore/research updates") are the natural ingestion hook — partly supported out of the box. The pipeline behind it is ours.
  • Discipline — semi-automated, human-committed (hard rule). Writing an automated pipeline that turns chaotic, contradictory global news into a clean normalized entity-diff is a colossal effort masquerading as a feature, and an LLM will occasionally drop vital context or hallucinate a relationship. A bad ingest permanently poisons a campaign's foundational state. So the agent never writes game state directly. It reuses a deep-research pattern (fan-out search → verify → cite) to propose a diff, and a human hits commit on a review dashboard before anything touches the world. Build it as an editorial tool first, autonomy never. This also downscopes the MVP pipeline from "autonomous world-updater" to "diff-proposer + review UI."
  • Principle: real geopolitics, fictional faces. The situation tracks reality; the leaders are archetypal characters, not photoreal renders of named real people (see §6).

All three forced decisions are now resolved. Blast radius — DECIDED (§9.3): a refresh seeds only NEW games. A campaign in progress is never perturbed — no overnight ingest rewrites the board you are already playing against, because that breaks the continuity of the story you are living in. Cadence follows from that and collapses to on-demand at campaign start. Editorial trust is the human-commit gate above. Cheap insurance to take now regardless: write state as history-tracked entities from day one, so any future refresh is a reviewable diff rather than a rewrite.


6. Presentation layer

Everything here serves Pillar 0 (§1): the presentation is how state is shown instead of told. The globe is the disposition readout; the premier's face is the hostility gauge. No labels, no raw numbers on the player-facing surface.

6.1 The call & the room

The signature loop: the globe sits live (flashpoints glowing by heat — Ukraine hot, Taiwan simmering — your reach, rivals' postures); an INCOMING CALL — MOSCOW lights up; you pick up; the premier's stylized face and accented voice are present; you talk (typed or spoken, freely); the world reacts on the globe. DEFCON, prestige, and the commons read as diegetic war-room instruments, not floats. The situation-room aesthetic (existing docs/BRINK_* + Situation Room mockups) is the frame.

6.2 Voice

Streaming, characterful, accented TTS (ElevenLabs-class). Highest feel-per-effort win; do it early.

6.3 Faces — the fork, decided

  • Chosen: stylized / archetypal leaders driven by visemes/phonemes from the TTS onto a Live2D or lightweight 3D rig. Real-time, in-browser, cheap, and it sidesteps the deepfake problem entirely. It also composes with the refresh: real leaders change; archetypes are durable while the board stays current. Often more cinematic than uncanny-valley photoreal.
  • Rejected for now: photoreal lip-sync of named real leaders (MuseTalk/Wav2Lip onto an actual likeness). It is a deepfake of a specific real political figure — ethically/legally fraught and exactly the artifact you never want leaking. Kept only as a distant "someday-wow," never of a real named person.

6.4 Compute

Because the GM brain now lives on Anthropic's infrastructure (§2.3, Claude-via-Max), a local GPU is freed from LLM inference and becomes a dedicated media engine: streaming TTS + the avatar/viseme render. Developed against a 24 GB card (RTX 4090), which handles that comfortably alongside a resident small model for the turn reader. Reach it by a name that resolves from anywhere you play — an overlay hostname, never a raw LAN IP, which works at home and silently hangs everywhere else. Latency is still the governing constraint — "on the phone" dies with a two-second lag before the mouth moves — which is the strongest argument for the stylized-viseme route over heavy photoreal video, and the reason first-token GM latency (§2.3) is instrumented from day one.

6.5 Front-end — the stack (Vue is dead here; the render engine is the real question)

Two distinct surfaces, and only one of them is cinematic:

  • The cinematic client (player-facing) — a fresh build, not Vue. For a globe + Live2D + streaming audio, the "UI" is a canvas/WebGPU surface with a thin HUD, not a DOM tree — so the render engine is ~90% of the front-end and the DOM framework is ~nothing. Target WebGPU (the modern GPU API, not tired WebGL). WASM/Rust where the compute is (globe, viseme sync, render — a wgpu/ Bevy-style engine is a legitimately good fit, and it pairs with the Tauri shell); thin TS where the ecosystem is (Live2D's Cubism runtime is JavaScript; Web Audio is JS; iteration is faster there). Don't go pure-WASM-everything and refight the JS ecosystem for avatars and audio — go WASM where it earns its keep, JS where it saves you time.
  • The admin / debug panel (never player-facing) — keep DMCP's Vue. The state browser and the §5 ingestion review dashboard are document-like forms; Vue is fine there and nobody cinematic sees it.

Web app vs. "thick client" are one thing at two depths. The cinematic client is a web front-end; a "thick client" is that same UI wrapped in a native shell (Tauri — Rust, lightweight) that also gets to escape the browser sandbox: spawn the local Claude CLI (§2.3), open local sockets, and talk to the media engine directly. A pure browser SPA cannot spawn the CLI. So: web front-end for the render, Tauri shell to drive the local GM + media pipeline.

The media plane bypasses the Tauri IPC bridge (a hard rule). IPC serialization jitter between the Rust shell and the JS/WASM front-end would desync audio from lip movement. So the audio + viseme stream goes direct from the WebGPU front-end to the media engine over WebSocket (or WebTransport/WebRTC for a real jitter buffer), on one shared clock so lips can't drift from the audio. Tauri IPC carries the control plane only — spawn the GM process, config, low-frequency events — which is jitter-tolerant. Never pump real-time media across the serialization bridge.


7. Persistence & context-window management

Inherited from DMCP and load-bearing: the world lives in the database; the GM gets a compact briefing each session (save_pause_state / get_resume_context = "formatted briefing + full state"; get_history / get_summary for continuity). This is how a long campaign plays inside a bounded context window without the GM forgetting turn 3 — the same job the current engine's snapshot() does, now with cross-session durability.


8. Player count (1–3 players)

The design supports 1, 2, or 3 humans, and the reason is a windfall from the old build: the rules core you're porting was designed around N interchangeable seats, resolved simultaneously, each with its own hidden view (the original invariants 7 and 8). Fair multi-seat resolution and per-seat fog-of-war — the two things that usually sink hobby multiplayer — are effectively already solved.

At the rules/state layer, player count is simply which seats are human vs. GM-driven, and the GM role degrades gracefully:

Players GM plays GM's job
1 the other 2 powers + the world full rival personas + narrator
2 the 1 remaining power + the world one rival persona + narrator
3 no powers pure world / referee / narrator (crises, neutral actors, the voice of events)

Promoting a rival from GM-driven to human-driven is a config flip, not a rewrite — if the cheap-insurance choices below are preserved.

What's free vs. what's added cost. The rules, conservation math, and fog-of-war are seat-count agnostic (free). The genuinely added scope for 2–3 humans is the session/client layer — currently scoped single-client, and listed as a non-goal in §11:

  • Per-player views — the data model already carries per-seat hidden info; each human needs a client rendering only their fog. The truth is ready; the rendering isn't.
  • Human-to-human channels — "call Moscow" becomes a real, private conversation between two people.
  • Hot-seat vs. networked — the MCP-server-as-single-source-of-truth makes networked clients tractable (multiple clients attach to one server), but it's real work.

Turn-model — real-time with diegetic clocks (red-team-corrected, twice). The cinematic brink demands synchronous attention: a 3 AM nuclear crisis loses all its teeth if a player can leave the tab open for three days. But lockstep "simultaneous submit-then-resolve" also fails the cinematic bar — if US barks an order in 15 seconds and Russia interrogates their intel chief for two minutes, US sits in dead air waiting for the turn to resolve, and the tension bleeds out. So multiplayer is a shared real-time world driven by diegetic clocks, not lockstep turns: a crisis runs on a live countdown the players can see ("missile reaches airspace in 60s"), which forces concurrent action, and players act into the shared world without waiting on each other's turn to resolve. Async play-by-mail survives at most as a separate, calmer between-crises mode for slow-burn diplomacy — never how you experience a crisis. (Two corrections: an earlier draft made async primary — a cinematic brink cannot be async; a later one said lockstep simultaneous — that creates dead air in a real-time voice room. The diegetic clock is the resolution, and it is the hardest open problem in multiplayer — which is fine, MP is post-MVP.) Rec: build single-player first (it has none of this problem — one human's pace); add matchmade real-time-with-clocks multiplayer when wanted.

Cheap insurance to take now (nearly free today, painful to retrofit), even if multiplayer is only a "maybe":

  1. Model every seat as "seat X, currently human-or-GM-driven" — never bake "the player" into world state.
  2. Keep the GM's world/referee role separable from its rival-persona role, so flipping a rival to human is a flag, not a rewrite.
  3. Keep fog-of-war per-seat from day one (the design already does).

9. Decisions (open ones carry recommendations)

Status as of 2026-07-24: only #1 and #6 remain open. #2, #3, #4, #5 and #7 are decided and are recorded here as settled constraints on the build, not as options still in play.

  1. MVP scope / what "first playable" must prove. Rec: prove the FEEL in text first — the GM-over-MCP loop with the ported enforced rules and one persistent game, where taking a briefing/call in prose already feels like inhabiting the role. Graphics amplify a loop that already works; they can't rescue one that doesn't (the lesson of the current build).
  2. Is the attention/hours economy kept? — DECIDED: dropped. It was wargame texture and cuts against "inhabit the role." Not ported, not modelled, not a resource. Re-introduce only if a session ever plays out feeling consequence-free — and even then, as a new design, not a revival.
  3. Refresh cadence & blast radius. — DECIDED: a refresh seeds only NEW games. A campaign in progress is never perturbed by an ingest — not even as opt-in injected crises (this goes one step further than the original recommendation). Real-world escalation enters the world only when you start a new campaign against it. Cadence therefore collapses to on-demand at campaign start, and editorial trust was already resolved by §5's human-commit gate. Consequence for the build: history-tracked entities from day one so a refresh is a diff, but no live-campaign injection path.
  4. Real-time avatar fidelity for MVP. — DECIDED: voice-first, one leader. A single characterful accented voice is the MVP's cinematic surface. Stylized visemes/face for that one leader come next; full roster and the live globe are later. This is the §9.1 principle applied to presentation — get one voice that makes you feel like you picked up the phone before building the room around it.
  5. Name & whether the reboot is a clean repo or a branch. — DECIDED: fresh private repo, brink, built on a public DMCP fork. Working title of the game remains open; the repo name does not.
  6. Which enforced rules are truly inexorable (§4.2) — the exact list is the highest-leverage design call. Rec: the three in §4.2; resist adding a fourth.
  7. GM backend — DECIDED (§2.3/§2.4). Ship on CLI-under-Max (keyless, subscription-billed), for money-safety first and flat cost second. The metered SDK/API is a deliberate fallback only, behind the GMBackend adapter, and it carries the §2.4 credential guardrails — it is never an automatic swap, because it reintroduces the pay-per-token key this project is engineering out. Still verify driven Max use stays subscription-billed and instrument first-token latency from day one.

Cost model (for reference, not a live concern on the primary path). Metered, a ~1-hour session runs ≈ $1.30 (Sonnet 5) – $2.20 (Opus 4.8) with prompt caching — tens of dollars a month even at heavy play. But the MVP is keyless/flat via the subscription, so this is moot unless the API fallback is switched on. The genuine recurring cost is voice (TTS), which can exceed the LLM cost several-fold — mitigated by running local TTS on your own GPU (≈ $0 marginal) and reserving premium cloud voices for the signature leaders.

(Resolved since the first draft, no longer open: the presentation surface is a WebGPU cinematic client in a Tauri shell, §6.5; the ingestion pipeline is human-committed, §5; the turn model is synchronous-first, §8; the GM runtime is keyless CLI-under-Max, §2.3/§2.4. Resolved 2026-07-24: the attention/hours economy is cut (§9.2); a refresh seeds only new games, never a live campaign (§9.3/§5); the MVP presentation is voice-first, one leader (§9.4); the reboot lives in the fresh private repo brink on a public DMCP fork (§9.5).)


10. Fork strategy (three buckets + how to offer back)

  • Use DMCP out of the box: persistence spine, factions, relationships-with-history, resources, locations, secrets/visibility (fog of war), dice/check/contest, pause/resume + history/summary, the web-UI scaffold, the multi-agent ingestion hooks.
  • Fork-and-offer-back (generic, upstream-able — keep on clean isolated branches for cherry-pick):
    1. an optional declarative constraint layer — let a resource be declared conserved / bounded / monotonic, and a timed status carry a real on-expiry consequence (not just narration). Against DMCP's current grain (rules-are-the-LLM's-job), so offer it as opt-in — but it's the single most useful contribution and is our enforced-rules mechanism generalized.
    2. improvements to the resume/summary compaction.
    3. a clean ingestion-adapter interface (generalizing the lore-push seam for any external world source).
  • BoT-private fork only: the geopolitical content of the rules (prestige conservation across the powers, the DEFCON ladder + shared nuclear floor, flashpoint alignment/cohesion, deed-driven demands), the GM persona prompt, the globe / call / situation-room UI, the current-events refresh pipeline, and the avatar/voice stack.

Keeping every upstream-able change on its own branch from day one is what makes the "cherry-pick what we offer back" workflow clean.


11. Explicit non-goals (dropped from the current build)

RL / training-an-AI-to-play · self-play determinism as an invariant · adversary/injection-proofing as a hard build gate · the rigid parse-or-die command grammar · multiplayer / netcode (MVP) · photoreal deepfakes of real named people · a standing pay-per-token API key (the MVP is keyless via the subscription, §2.3/§2.4) · any credential inside the working tree a coding agent can read (§2.4).


Provenance: distilled from the 2026-07-24 playtest + design conversation, revised through two red-team passes and a money-safety discussion. Incorporated: Pillar 0 (show-don't-tell); the resolve-then-narrate anti-desync contract + react-first latency masking (§2.1a); the keyless CLI-under-Max GM runtime with credential-safety hard requirements (§2.3/§2.4, primary for money-safety after a prior metered-key-leak incident, metered API a deliberate guarded fallback); human-committed ingestion (§5); WebGPU + Tauri + WASM-where-it-earns-it presentation with a direct-WS media plane bypassing Tauri IPC (§6.5); real-time-with-diegetic-clocks multiplayer (§8); and a cost model (§9, GM ~$1–2.50/hr metered but moot while keyless; voice is the real cost). The current repo's E21 work (retiring the explicit THREATEN verb; making a demand a deed on a contested flashpoint) is the most recent rules addition and ports cleanly as the "deed-driven demand" mechanic above.