# Thousand Token Wood v2: Story Mode -- Engineering Spec Source: roadmap in `tasks/story-mode-roadmap.md`. Locked decisions: Patron player role; multi-model sponsor-max council (design to strict sum <=32B); agent-driven beats. ## 1. Product summary and core player fantasy v2 turns a watch-the-chart sandbox into a player-driven finance drama. You stop being a weather god who pokes the world and become the Patron of Thousand Token Wood: a shadow financier who lends pebbles at interest, whispers tips that may be true or planted, shorts goods, bribes creatures, and brokers alliances, while five small-model creatures scheme back, remember how you treated them, and Magistrate Heron investigates suspicious wins. The chart stays the scoreboard; the story is the people. Core fantasy: "I move money and information from the shadows, the wood reacts to me personally, and I stay one whisper ahead of the regulator." ## 2. Assumption audit (HIGH = gates dependent phases) - A1 (HIGH): gpt-oss-20b serves on a single L4 under vLLM at acceptable cold-start/latency. gpt-oss needs a RECENT vLLM (not the v1 pin 0.6.6) and MXFP4 handling. If wrong: bigger GPU (A10/A100) for that one engine, or a smaller OpenAI-eligible fallback. OpenAI track + Narrator both depend on it. Validate via Phase 0 serve smoke test. - A2 (HIGH): MiniCPM-2B and Nemotron-Mini-4B-Instruct load on a pinned compatible vLLM. If wrong: per-engine vLLM pin, or same-lab substitute. OpenBMB + NVIDIA eligibility at stake. - A3 (HIGH): Modal budget tolerates up to 4 concurrent warm engines (one ~20B). If wrong: load-on-demand/stagger, short keep-warm windows, tiny-only dev mode, reserve full council for recorded-demo + judging only. - A4 (HIGH): small models scheme/lie/retaliate convincingly enough to read as drama. If wrong: Narrator (gpt-oss-20b) carries prose; engine state (heat, relationships, debt) carries plot; scheming becomes engine-mechanical, not purely emergent. - A5 (MED): tolerant parse-and-repair extends to new action types across 4 heterogeneous models. If wrong: per-model prompt nudges + canonical re-serialization, or enumerated-vocab actions. - A6 (LOW): 32B sum holds: gpt-oss-20b(~21) + Nemotron-4B(4) + MiniCPM-2B(~2.7) + qwen-0.5b(0.5) = ~28B; narrator reuses gpt-oss (no add). Recheck on any swap. - A7 (MED): players grok the power-move console without a tutorial. If wrong: inline microcopy + one-screen how-to (Phase 6). ## 3. Phased scope (roadmap Phase 0-6); each phase reviewer-gated; parse-and-repair reused ### Phase 0 -- Foundations (multi-model serving + Patron state + player-move turn loop) - [ ] Per-model serve smoke test passes for each distinct model (gpt-oss-20b, Nemotron-Mini-4B, MiniCPM-2B, ttw-trader-0.5b): deploy, load, one chat_batch; record cold-start + latency. - [ ] Multi-engine serving layer routes each creature to its assigned model; one completion per creature per logical turn (N GPU calls grouped by model). - [ ] Documented param-budget assertion: sum of council params <= 32B. - [ ] Patron state (purse:int, reputation:int, heat:int) added and initialized. - [ ] Turn loop accepts an optional queued player move (placeholder ok) and steps without error. - [ ] TTW_DUMMY=1 tiny-only / no-GPU mode runs end to end. - [ ] Documented Modal cost estimate ($/judging-hour full warm council) + burn note. - [ ] v1 test suite still passes. ### Phase 1 -- Player-as-operator loop (replace god-mode shocks with costed power moves) - [ ] Six power moves (Lend/Whisper-tip/Short/Bribe/Broker-alliance/Fund-corner) with defined cost (purse/reputation/heat) and world effect; each logged as a structured event. - [ ] Each creature-targeted move yields an observable creature response next turn. - [ ] v1 god-mode shock buttons removed (or relabeled as Patron moves); no direct god-powers. - [ ] Insufficient purse/reputation blocks a move with a clear message; no negative purse. - [ ] New model-involving action types round-trip the parse-and-repair layer; malformed dropped. - [ ] Parse-reliability harness >= 90% valid-JSON per council model for new types. - [ ] Reviewer-approved; suite green. ### Phase 2 -- Information war (true/false tips, heat, Magistrate Heron investigation) - [ ] Tip carries a hidden truth flag; a true tip forecasts the next Wood Legend and acting on it before it fires yields a measurable pebble edge in a seeded run. - [ ] Heat meter rises by defined rules on suspicious wins; surfaced in UI. - [ ] Crossing heat threshold opens an investigation with >=3 stages (testimony/evidence/verdict) as structured events. - [ ] Each verdict (fine/frozen pebbles/exile) has a defined, tested effect. - [ ] Investigation events produce rich exportable traces. - [ ] Seeded run demonstrates full arc: plant true tip -> profit -> heat -> investigation -> verdict. - [ ] Reviewer-approved; suite green. ### Phase 3 -- Agent memory + relationships (grudges, alliances, cartels) - [ ] Each Creature carries a structured relationship store keyed by counterparty (incl. Patron): sentiment + notable events. - [ ] Documented triggers update relationships (loan repaid/defaulted, bribed, shorted, tipped truly/falsely, allied, betrayed). - [ ] Negative-sentiment creature gives measurably worse terms / hostile gossip to the Patron vs neutral baseline, in a seeded run. - [ ] >=1 emergent multi-creature alliance/cartel behavior observable in a seeded run. - [ ] Relationship state is in each model's prompt context and survives across turns. - [ ] Memory growth bounded (documented cap); no unbounded prompt inflation. - [ ] Reviewer-approved; suite green. ### Phase 4 -- Narrator + chapter arcs (Billions voice) - [ ] Narrator uses the gpt-oss-20b engine with a separate prompt (no extra model/param budget). - [ ] Narrator calls few per turn (documented) and degrade gracefully: on failure/timeout show plain narrate.py ticker (no crash, no blank panel). - [ ] Light authored chapter skeleton (named chapters/acts); current chapter surfaced in UI. - [ ] Ticker renders as a headline feed + >=1 character-dialogue beat per eventful turn. - [ ] Narrator output length/format guarded so it cannot overflow the panel. - [ ] Seeded demo run yields a coherent dramatized arc for the Best Demo video. - [ ] Reviewer-approved; suite green. ### Phase 5 -- Leverage + ruin (loans, margin, margin calls, bankruptcy/exile, short P&L) - [ ] Loans carry principal/interest/term; repayment and default modeled and logged. - [ ] Margin call triggers when collateral < maintenance level; defined tested resolution. - [ ] Short-selling P&L tracked separately from spot inventory value. - [ ] Bankruptcy/exile reachable, removes the creature without corrupting market clearing. - [ ] Pebble/inventory conservation invariants hold across loan/interest/short/margin flows. - [ ] Seeded run demonstrates leveraged short, margin call, and >=1 ruin/exile. - [ ] Reviewer-approved; suite green. ### Phase 6 -- Retro operator console UI (Off-Brand) - [ ] Custom (non-stock-Gradio) frontend renders console, relationship map, heat meter, dialogue/cutscene panel, headline feed. - [ ] Every Phase 1 power move issuable from the console with cost shown before commit. - [ ] Relationship map reflects current sentiment/debt edges, updates each turn. - [ ] Heat meter tracks engine heat; signals when investigation threshold near. - [ ] COLOR-CONTRAST GATE (non-negotiable, Section 7): every custom light/cream panel forces dark text via id-scoped !important; legibility verified in the dark Space theme before ship. - [ ] Stays a Gradio app under build-small-hackathon, served via Modal/vLLM; runs without crashing. - [ ] Reviewer-approved; suite green. ## 4. Data-model sketch (extends ttw/world.py, ttw/game.py) - Patron dataclass on WorldState (world.patron): purse:int, reputation:int, heat:int, loans:list[Loan], shorts:list[ShortPosition], pending_moves:list[dict]. - Tip record (hidden truth flag, not shown to creatures): target, good|legend_key, truth:bool, turn_planted. - Investigation dataclass on WorldState when open: stage(testimony/evidence/verdict), evidence:list[dict], verdict:str|None. - Loan(borrower, principal, interest, term, turn_issued, outstanding); ShortPosition(good, qty, entry_price, open:bool; P&L derived from last_price). - Creature gains relationships:dict[str,Relationship] keyed by counterparty incl "Patron"; Relationship(sentiment:int, notes:list[str] bounded). Keep free-text memory list, bound length. - Chapter/Act skeleton on Game (name, order) + current_chapter. - Game accessors mirror existing *_frame/*_markdown: patron_view(), relationship_frame(), heat, narrator buffer, chapter accessor. New action types parse via extended parse_actions/_extract_json. ## 5. Non-goals Not a real/accurate economy (drama over fidelity); player is not a trader nor the Magistrate; no real money/tickers/living people (economic history only); no multiplayer, no cross-session persistence; no models beyond the locked <=32B-sum council; Tiny Titan not retained; chapter skeleton stays light (not a full dialogue tree); no mobile-specific work. ## 6. Bonus/prize acceptance criteria (Tiny Titan dropped) - [ ] OpenAI track: >=1 creature runs gpt-oss-20b live on Modal/vLLM, driving decisions. - [ ] OpenBMB: >=1 creature runs MiniCPM-2B live. - [ ] NVIDIA Nemotron Quest: >=1 creature runs Nemotron-Mini-4B-Instruct live. - [ ] Modal: all inference on Modal vLLM; documented in README + Field Notes. - [ ] Best Agent: agents respond to the player (P1) + persistent memory/relationships (P3); seeded run. - [ ] Best Demo: gpt-oss-20b Narrator dramatizes a coherent arc (P4); demo video of a power-move-and-consequence story. - [ ] Well-Tuned: ttw-trader-0.5b published + serves >=1 creature live (pipeline exists). - [ ] Sharing-is-Caring: traces (incl investigation + relationship beats) published. - [ ] Field Notes: post on the multi-model council + Billions pivot published. - [ ] Off-Brand: custom operator-console frontend ships (P6). ## 7. UI/UX requirements (incl. non-negotiable contrast rule) - HF Space renders DARK by default; Gradio forces light body-text with !important; design for dark. - COLOR-CONTRAST / READABILITY (non-negotiable, repeated prior correction): any custom light/cream panel MUST force dark text via an id-scoped !important rule (pattern in app.py: `#town-panel, #town-panel * {color:#2e2519 !important;}`). Every new light panel in any phase (Patron console, relationship map, heat meter, dialogue, headline feed) carries its own such rule, and legibility is visually verified in the dark theme before that phase ships. - Preserve v1 cold-start UX: interim "thinking/waking" status during a possibly-cold call; never frozen/blank. Extends to the Narrator call (graceful fallback to plain ticker). - Emoji allowed in user-facing Gradio strings; NO emoji in code/docs prose; NO em dashes anywhere. - Patron console shows each move's cost before commit; purse/reputation/heat always visible. - A fresh viewer can execute a tip-then-short loop without a tutorial (validate P1 + P6 QA). ## 8. Resolved defaults (chosen 2026-06-06; were open questions) - Q1 fifth creature: Qwen-0.5b (our fine-tune) powers TWO creatures (Mossback + Pip); the other three (Bramble, Fenn, Oona) run MiniCPM-2B, Nemotron-Mini-4B, gpt-oss-20b respectively. - Q2 starting Patron values (Phase 0 defaults, tune later): purse 500, reputation 50 (0-100), heat 0; investigation opens at heat >= 70. - Q3 Modal budget: original credit is the cap; dev defaults to tiny-only; full warm council only for recorded demo + judging; staggered load-on-demand acceptable. - Q4 exile: REVERSIBLE (a creature can re-enter after a chapter) so the cast stays intact for the demo video; "frozen pebbles" is the harsher-but-recoverable mid-demo verdict. ## 9. Build order + minimal Billions slice Order: P0 (foundations + serving de-risk) -> P1 -> thin P2 (true/false tip + heat + single-stage investigation) -> thin P4 (narrate one fallout) -> complete P2 -> P3 -> P5 -> P6. Each through architect -> implementer -> reviewer -> qa, reviewer after each fix round; commit/push as phases land. Minimal Billions slice (internal milestone): P1 + thin P2 + thin P4 = player plants a true/false tip and a leveraged short; Magistrate may catch them; one creature retaliates; Narrator dramatizes.