Roadmap
Milestones M0–M11 from toolchain to closed alpha, with small tasks, tests, evidence, gates, art dependencies and token estimates.
Rules: each task fits one agent session and is logged; each milestone ends at a gate with evidence and owner
review. M0–M2 are pre-production: prove the risky things (tools, 1,000-player network, one perfect skill)
before making content. The data source is roadmap.json.
M0Kickoff & toolchainpre-productionNOT STARTED
Every tool works on this machine, the monorepo builds, logging works, and the first ADRs are written.
| Task | Size | Title | Test | Evidence |
|---|---|---|---|---|
| M0-01 | S | git init, branch policy, CI script stubs (pnpm test, cargo test) | pnpm -r test passes | git log, logs/tasks.json |
| M0-02 | S | Blender headless smoke: build a cube, export GLB, render PNG | blender -b -P tools/blender/smoke.py exits 0; GLB validates | logs/test-output + render PNG |
| M0-03 | S | Install Rust; hello-world crate + golden-vector export (JSON) for the C# prediction subset | cargo test; vectors JSON schema test | build log + vectors.json |
| M0-04 | M | apps/client-unity: URP project (owner installed Unity Hub + pinned 6.x LTS), quality profiles Low/Mid/High/Ultra, FPS overlay; batchmode builds for macOS + Web + Android APK (ADR-032) | Unity -batchmode -runTests EditMode passes; Web build opened by Playwright reports the graphics API and 0 console errors | build logs + screenshot |
| M0-04C | S | Client tier defaults, Ultra gate and frame targets from feel-quality.json (tierSelection, proposed): low-memory phones and low-end browsers start on Low, a native startup benchmark picks the default (the player’s saved choice wins), phone Ultra only through a test launch option until the M1 thermal/frame gate passes, per-tier frame-rate caps | Unity EditMode tests for every rule pass; Web, macOS and Android smokes show the data’s default tier and frame cap with 0 errors | logs/evidence/M0-04C/ (smoke JSON, a screenshot per platform, default tier and frame target table) |
| M0-04D | S | Phone smokes for the M0-04C tier rules: Android APK smoke (default Mid by benchmark at 30 fps, High 60, Ultra only by the test launch option, overlay cycle Low/Mid/High) and the phone-Chrome Web smoke with the frame-cap and low-end checks | node tools/unity/android-smoke.mjs and web-smoke.mjs --cdp pass with 0 errors (platformNoise unchanged) | logs/evidence/M0-04C/ android-smoke.json, web-smoke-phone-chrome.json, android screenshots, tier-defaults.txt |
| M0-05 | M | Capability probe on the owner's Android phone, Chrome and the M3 (ADR-032); physical Low baseline (Galaxy A07 4G 4 GB, iPhone SE 2020, Intel N150 8 GB) stays pending until units exist ADR-032: owner results are labelled with their probe and do not validate the Low references. | probe JSON schema test | logs/evidence/<task>/device-probes + reference-devices.json validation records |
| M0-06 | S | ADR-003…005 + ADR-024 committed (server + protocol, monorepo, skill system, Unity client) | docs lint: every ADR has status/context/decision/consequences | docs/vision/DECISIONS.md (ADR-003, ADR-004, ADR-005, ADR-024); owner approval pending in logs/reviews.jsonl |
| M0-07 | S | Unity toolkit gate: Unity Test Framework + Performance Testing pinned and proven (no MCP: the unity-mcp smoke test was skipped by owner direction, 2026-10-08) | PlayMode performance tests pass in batchmode (sky step 0 GC allocations, Boot frame times recorded); unity-run.mjs prints median/p95 | logs/evidence/M0-07 (perf results JSON + runner summary) |
| M0-08 | M | Tripo → Blender → Unity bake-off: 3 assets (monster, prop, weapon) from approved concept art, API credit cap set, Blender polish script, turntable renders for the owner Replaced by MODEL-01 (ADR-033, 2026-10-08): no Tripo API and no credits; the owner makes models by hand in the Tripo website from the model request log, agents validate and polish them in Blender. Kept for the record. | validator passes tris/bones/UV/texture budgets; credits used ≤ cap in logs/tripo-gen.jsonl | turntable clips + validator JSON |
| MODEL-01 | M | Model request log (ADR-033): gen-model-requests.mjs → model-requests.json (monsters, elites, bosses, mounts, armour pieces, costumes, set pieces; budgets, Tripo settings, roadmap order, Dune Beetle first), reference views cut by tools/model-views.py, undersuit and armour-piece 2D requests | pnpm data:test (model-requests.test.mjs); python3 tools/model-views.py cuts the Dune Beetle views | logs/evidence/MODEL-01/ (Dune Beetle views contact sheet, monster views overview) |
| MODEL-01B | M | Model inbox checker tools/model-inbox.mjs (pure-Node GLB parse: id, bounds, tris vs budget, TEXCOORD_0, embedded textures, no skin/animation → model-delivered.json; rules in model-requests.manual.json inbox) with synthetic GLB fixtures; view-cut fixes in tools/model-views.py (scale bar painted out, gap-first split: Ashroot Pangolin) | node --test packages/game-data/tests/model-inbox.test.mjs (valid, skinned, animated, no-UV, no-texture, over-budget, far over, wrong id, .v2 beats .v1, broken file, units); also in pnpm data:test | logs/evidence/MODEL-01B/ (inbox-check.txt, views-fixed.png, views-all-monsters.jpg) |
| MODEL-01C | S | View-cut part ownership in tools/model-views.py (a connected part with ≥ 0.9 of its pixels in one view goes to that view whole; other views painted out: Ashroot Pangolin front sliver gone, clipped whiskers/tails back); art/3d/inbox/README.md, inbox GLBs git-ignored (sha256 provenance in model-delivered.json), model-inbox.mjs ignores the README | python3 tools/model-views.py cuts all 40 (contact sheet); pnpm data:test (model-inbox.test.mjs README fixture) | logs/evidence/MODEL-01C/ (views-fixed.png) |
| MODEL-01D | S | Wiki page Model requests (follows Art/Audio generation): counts by status, owner steps rendered from TRIPO_PIPELINE Current mode, the agent step (model-inbox.mjs), kind/status filters and search, one card per request (id, kind, use, neededBy, budget, prompt + avoid with copy buttons, view previews or views missing → ART-… request via /art-requests/?q=, Tripo settings, saveAs, status and delivery note), nav entry in lib/routes.ts | wiki typecheck + build; e2e tests/model-requests.spec.ts: renders, card count = request count, kind and status filters, the views-missing link opens the art queue filtered to its ART id, no console errors | logs/evidence/MODEL-01D/ (page 1440×900 and 390×844 screenshots, first card desktop and mobile) |
| MODEL-01E | S | Fix the Bellwhisker Jerboa side/front view split in tools/model-views.py (the cut falls on the thin tail: side.png is only the tuft); re-cut MDL-MON-bellwhisker_jerboa and its elite and refresh the wiki previews | python3 tools/model-views.py --only MDL-MON-bellwhisker_jerboa (side.png holds the whole body in profile); pnpm data:test | logs/evidence/MODEL-01E/ (jerboa views before/after) |
| GM-00 proposed | S | GM arena roadmap (gm-room.json): GM-01 in M2 right after the Combat Lab, GM-02 in M4, GM-04 (the owner's local role CLI) in M6, GM-03 at the end of M9; the M2/M4/M6/M9 gates name their GM arena part and the wiki Roadmap shows a milestone's tasks next to its groups Proposed: owner decision 2026-10-08 (GM arena run). GM-04 is its own M6 task because role access starts with the M6 accounts, three milestones before GM-03; GM-03 closes M9 instead of opening a new milestone (no new id, order or gate to keep in step). | pnpm data:test (gm-arena-roadmap.test.mjs: placement, proposed notes, GM rules, every gm-room.json area and command placed); node tools/ctx.mjs task GM-01 prints the card; the built wiki roadmap page lists GM-02 and GM-03 | logs/evidence/GM-00/ (GM-01…GM-04 cards as .txt) |
| M0-09 | S | Engine-free C# gameplay core scaffold (ADR-029): a netstandard2.1 library with no UnityEngine references plus an xunit project, run by pnpm core:test; Unity will consume the same folder through an asmdef | dotnet test passes; a test fails if any file in the core references UnityEngine | test log |
| M0-10 | S | Unity runner (ADR-029): tools/unity-run.mjs wraps batchmode tests and builds, saves the full log and prints the result, the counts and the first five errors | runner unit tests on recorded logs (pass, compile error, failing test, licence error); one live EditMode run through it | runner output sample |
| M0-11 | M | One-simulation spike (ADR-029): build a small zoen-sim step function as a client plugin for macOS, Windows, Android and iOS and as a static library for the Web build with the pinned editor's Emscripten version; call it from Unity on Web, macOS and Android; Windows and iOS recorded not tested (ADR-032) | the golden vectors pass through the plugin on Web, macOS and Android; the Web build loads with 0 console errors; step cost and binary size recorded | spike report with pass/fail per target; ADR-029 updated with the result |
| M0-12 | S | Time-of-day and weather controller in the first scene (ADR-030): phases and weather states from time-weather.json, a server-clock interface, GM toggles /gm time, /gm cycle and /gm weather | EditMode: the state machine follows the data file; PlayMode: each toggle changes the state and logs it; the telegraph contrast check passes across the review matrix on Low | four-phase capture strip + state log |
M1Feasibility spikes (render + network at scale)pre-productionNOT STARTEDafter M0
Prove the two hardest numbers before content: 150 animated characters on screen on mid mobile, and 1,000 bot players in one Rust zone at 20 Hz.
| Task | Size | Title | Test | Evidence |
|---|---|---|---|---|
| M1-01 | M | Crowd render test in Unity: 150 baked-animation crowd characters (GPU instancing) + 50 full skinned; GPU Resident Drawer on native | Performance Testing PlayMode run: p95 frame ≤ 16.7 ms on Windows/desktop, ≤ 33 ms on mid Android; Web build Mid p95 ≤ 33 ms in Chrome | perf.json per target |
| M1-02 | M | VFX stress: 300 pooled GPU particle emitters + 200 projectiles | p95 frame budget per tier; zero GC spikes > 4 ms | perf.json + video |
| M1-03 | L | zoen-zone: fixed 20 Hz loop, spatial hash, AOI interest sets, delta snapshots | cargo test (AOI correctness, delta round-trip); criterion: tick ≤ 15 ms p99 with 1,000 bots + 4,000 mobs on 4 cores | bench report |
| M1-03B | M | zoen-zone part B: delta snapshots per client (baselines and acks, bit-packed position/yaw/anim/HP deltas, priority accumulators and the near/mid/far rates from NETCODE_1000.md), the first protocol schema entries in packages/protocol/zoen.schema.json (Rust generator), and a WebSocket endpoint the M1-04 bots connect to | cargo test (delta round-trip against full state, ack/baseline loss, snapshot within the 32 KB/s per-client cap); the M1-03 tick bench stays ≤ 15 ms p99 with snapshots | bench report with snapshot bytes per client |
| M1-03C | M | zoen-zone part C: WebSocket endpoint (zone binary, cargo run -p zoen-zone --bin zone -- --port <p>): minimal RFC 6455 on std::net (HTTP upgrade with SHA-1 + base64 accept key tested on the RFC vectors, binary frames, masking, ping/pong, close; no new crates until the owner approves one), network threads with bounded queues off the pure tick, hello/join, inputs into the tick, 20 Hz snapshots from the M1-03B replicas, acks, pong, graceful shutdown | cargo test: SHA-1/base64/accept-key RFC vectors, frame codec round-trip; integration test with 2-10 local Rust test clients that connect, move and receive consistent snapshots, then a graceful shutdown; re-run pnpm zone:snapbench on an idle machine for the M1-03B tick + snapshots p99 <= 15 ms criterion (unmeasurable at load average 180) | integration test log excerpt |
| M1-03D | S | zoen-zone part D: socket load check for the zone binary (pnpm zone:loadcheck: about 200 Rust WebSocket clients on localhost for 10 s, random walk, ack every snapshot, ping each second) recording loop p50/p99/max, skipped frames and bytes per client per second, plus the M1-03B tick + snapshots p99 re-run on an idle machine | zone:loadcheck exits 0 with every client joined and cleanly closed, no stale/dropped inputs, frames skipped under 1 percent; pnpm zone:snapbench re-run | load-check JSON, server log excerpt |
| M1-04 | M | Bot client (Rust) simulating 1,000 players (walk, fight, chat) over WebSocket | 1,000 bots connected 10 min, no disconnects, server tick p99 within budget, avg downstream ≤ 12 KB/s/client | metrics.json + Grafana-like PNG |
| M1-04B | M | M1-04 part B: split snapshot building and hand-off across 4 cores (M1-04 profile: build 11.7 ms + hand-off 2.6 ms of a 17.4 ms mean loop at 1,000 clients; tick-thread CPU 15.1 ms/tick, so code-bound), then the 10-minute 1,000-bot soak (stepped ramp 100/250/500/1,000) and the Grafana-like PNG chart | pnpm zone:bots: 1,000 bots 10 min hold, no disconnects, loop p99 within tick.targetP99Ms, avg downstream within loadTest.avgDownstreamKBps, memory flat within loadTest.memoryDriftPercent; no per-tick allocations (snapshot_no_alloc test still passes) | metrics.json + Grafana-like PNG, server log excerpt |
| M1-04C | M | M1-04 part C: the 10-minute 1,000-bot soak (stepped ramp 100/250/500/1,000 via --steps, memory-drift check, per-second RSS and RTT series) and the Grafana-like PNG chart (M1-04B: snapshot pool on 4 threads, 1,000 bots 80 s loop p99 12.1 ms) | pnpm zone:bots: 1,000 bots 10 min hold, no disconnects, loop p99 within tick.targetP99Ms, avg downstream within loadTest.avgDownstreamKBps, memory flat within loadTest.memoryDriftPercent; snapshot_no_alloc and snapshot_pool tests still pass | metrics.json + Grafana-like PNG, server log excerpt |
| M1-04D | S | M1-04 part D: re-run the 10-minute 1,000-bot soak on a quiet Mac (M1-04C passed bots, bandwidth and memory but missed loop p99 at load average 200-380 on 8 cores: tick-thread CPU 4.5 ms + workers 7.9 ms per loop) | pnpm zone:bots -- --steps 100,250,500,1000 --step-s 30 --hold-s 600 at a load average near the core count: every check passes (loop p99 within tick.targetP99Ms, no dropped ticks, no disconnects, memory within loadTest.memoryDriftPercent) | metrics.json, soak-chart.png (tools/zone-soak-report.py), summary.txt with the load average, server log excerpt |
| WIN-01 proposed | M | Windows test build (ADR-032): `unity-run build windows` (Mono x86_64 from this Mac), import rules for the Windows sim DLL, a zip + owner smoke kit (a .bat/.ps1 that runs the player per tier with -logFile and a node/PowerShell checker for the ZOEN lines; results pasted back as a file into logs/evidence), the Windows probe (M0-05 format) via the kit, and the PC build steps for the sim DLL Proposed: owner decision 2026-10-11 (ADR-032: test on Web, Android and Windows; macOS and iOS paused). The owner runs the kit on his Windows PC (agents can't reach it) and builds the sim DLL there with Rust and Visual Studio Build Tools; agents never download Microsoft's Windows SDK or CRT. Until the DLL exists the player runs without the native sim (the boot check reports it absent; not an error). The PC's probe fills reference-devices.json → ownerTestDevices owner_windows. | node tools/unity-run.mjs build windows passes (ZOEN_BUILD target and size in the build summary); EditMode tests pass with the Windows DLL import rules (x86_64 Windows player only); the kit checker passes on a saved sample log (pnpm data:test); the owner's returned results show every tier booting with 0 errors and a ZOEN_PROBE line that holds the probe contract | logs/evidence/WIN-01/ (build summary JSON, kit file list, checker output on the sample log, the owner's returned results file, the Windows probe JSON) |
| M1-05 | M | Unity client (native + Web) connects, predicts movement with the C# prediction subset, reconciles | PlayMode test with 200 ms injected latency: prediction error < 0.15 m p95; C# subset matches all Rust golden vectors | test log + clip |
| M1-06 | S | Security event log from day one: zone + gateway report rejected/suspicious actions (append-only, never public) | forged message from the bot client writes a proto_forged event; schema test of security.json | event sample JSON |
M2Combat Lab: one perfect skillpre-productionNOT STARTEDafter M1
Warblade · Horizon Cleave is AAA-complete end to end: input → server phases → animation → VFX → SFX → hit reaction on a dummy and a monster → damage numbers → camera.
| Task | Size | Title | Test | Evidence |
|---|---|---|---|---|
| M2-09 | M | Preparation gate: versioned Zoen mannequin, rest pose/axes/bind matrices/socket contract and Humanoid Avatar validation before skill clips | Rig validator and deformation poses pass; exports preserve contract; supported body/grip/armour review matrix recorded | rig contract hash + deformation sheet + review checklist |
| M2-01 | M | Combat Lab scene: dummy, 10/25/50/100 dummy fields, spawnable monster, debug HUD; input/phase/cancel/hit/reconciliation timeline debugger; simulated 80 ms round trip by default with a 0 ms switch (NET-01, ADR-031) | scene loads; spawn commands work via console API | screenshot + replay timeline sample |
| GM-01 proposed | L | GM arena core in the Combat Lab scene (gm-room.json): static_targets (/gm dummy with DPS meter and hit log), spawn_ring for the monsters that exist by then (/gm spawn), reset_station for what exists (/gm level, /gm reset cooldowns, /gm clear monsters), debug toggles (/gm god, /gm mana, /gm nocd, /gm hitboxes, /gm telegraphs, /gm ai freeze|resume), network lab (/gm lag) and Time/Weather buttons on the M0-12 controller (/gm time, /gm cycle, /gm weather) Proposed: owner decision 2026-10-08 (GM arena run). GM rules: every GM action is audited (who, what, where); GM-made items carry the gm flag and can never be traded, sold, listed or mailed; until M6 test builds use a dev-only local GM flag (never in release builds); from M6 access is by the gm or qa role, agents never grant roles, and the owner gives his own account the gm role with the local CLI (GM-04). GM tools never add a global time-scale and never hide telegraphs. | one automated test per GM-01 command (server state after it, audit record written, refused without the dev GM flag); no toggle changes the global time scale or hides a telegraph; Time/Weather commands leave the server outcome identical (ADR-030) | arena panel screenshot + 10 s clip (spawn, dummy DPS meter, /gm lag with jitter and loss, dusk + sandstorm) + audit log excerpt (.txt) |
| M2-02 | M | Server cast-phase state machine (windup/active/recovery, cancel windows, cast id, per-target hit ids); ADR-027 cancel in every own attack phase; cast-owned vs independent damage lifetime | golden timelines include cancel/contact ties, commit costs/refund, released entity persistence; no double hits/costs under duplication/loss/reordering | test log |
| M2-10 | M | Movement-first input arbitration and cancellation self-tests C1–C18 across keyboard/mouse, gamepad and touch ADR-032 (2026-10-11): keyboard/mouse on the Windows PC and in Chrome on the Mac, touch on the owner's phone; gamepad unverified until one is connected. | Boundary-swept cancels in all phases; explicit actions beat held chain; WASD policies, costs, entity lifetimes, collision and network-fault replays pass; positive mana and exact reuse/travel boundaries, hard-control/root exceptions, combo memory expiry/refund and R3-only view toggle verified | control-results.json + input/cast/hit timeline + both-camera clips |
| M2-03 | M | Horizon Cleave greybox on the validated mannequin; locomotion/steering contract and cancel/chain blends | contact ±1 frame; marked planted-foot slide <2 cm; grip drift <1 cm; continuous eight-view/both-camera review, cancel transitions and representative bodies pass | eight-view contact sheets + side strip + continuous motion and interruption clips + self-review checklist |
| M2-04 | M | Horizon Cleave VFX: semantic roles, material impact, cancel cleanup, pooled Low/High profiles | tier/frame caps, overdraw/cost metrics and pool return pass; footprint and boss telegraph readable in both cameras, terrain and accessibility modes | Low/High side-by-side clip + budget JSON + readability/cancel checklist |
| M2-05 | S | SFX: 4-layer hit (swish, impact, material, sweetener) + voice limit | audio bus peak < −1 dBFS; voice cap respected | audio capture |
| M2-06 | M | Hit reactions: flinch_light/heavy, stagger, knockback on Dune Beetle placeholder (insectoid set) | reaction chosen = rule(impact, weight, poise) for 12 cases | video |
| M2-07 | S | Game-feel layer: local hitstop, trauma camera shake, hit flash, damage numbers, magnetism; strict and predicted-contact impact modes behind a switch, contact-to-confirm delay measured (ADR-031, NET-02) | toggles respected; server outcome identical with feel on/off and in both impact modes | A/B video |
| M2-08 | S | Human review: owner watches the 10 s clips at 80 ms in both impact modes, picks one (ADR-031) and signs off (or lists fixes) in Chrome (Low–Mid) and on the Windows PC (High) (ADR-032, 2026-10-11) | review entry in logs/reviews.jsonl | clip + notes |
| M2-11 | L | Skill factory (ADR-029): data-driven runtimes for the shape families, one gate runner that iterates skills.json and one command that produces the evidence (contact sheet, Low/High clips, budget JSON) | Horizon Cleave passes the gate through the factory with no skill-specific code; a second skill from another family is added as data only | gate report for both skills + evidence pack |
M3Character pipelineproductionNOT STARTEDafter M2
Canonical human male + female from turnaround → mesh → rig → modular armour → locomotion + greatsword set, retargetable to all lineages.
- Tripo pipeline automation: tools/tripo/generate.py (SDK, credit guard, logs) + tools/blender/polish_tripo.py (headless clean/retopo/UV/rig/LOD) — docs/production/TRIPO_PIPELINE.md
- Turnarounds (ART-CHR-050/051) → image-to-3D or sculpt → retopo (≤ 22k tris) → UV/texture 2K
- Rigify humanoid → Mixamo-compatible bone map → weight paint (≤ 4 influences) → corrective shapes
- Modular slots: helmet/body/gloves/boots + costume override; hide covered submeshes
- Locomotion set (idle/walk/run/sprint/turns/jump/land/hit/death) + greatsword grip layer
- LOD0–3 + VAT crowd version; glTF export validator
- Lineage proportion variants (orc/elf/vanara/auralin) with cosmetic corrections only
M4Vertical slice (3 builds)productionNOT STARTEDafter M3
Warblade, Windarcher and Spellslinger fully playable with 6 skills each, 6 movement gems, Atlas + Codex, Dewgrass/Orchard monsters with reaction sets, HUD v1 desktop + mobile.
- 18 skills through the skill gate, built with the skill factory (M2-11)
- Atlas UI + Codex UI + Smart Chain + keybinds remap
- 6 mana-consuming movement gems with traversal validation; proposed Cairn Vault 1 s / Reed Rush 0.3 s reuse targets profiled; other gems individually tuned
- 4 monsters (hare, fox, boar, beetle) modelled, rigged, reaction sets
- HUD v1 using ART-HUD-001…013
- Desktop + mobile input; gamepad basic
- Close/tactical camera toggle (V/R3/touch), optional close-view boss lock-on and off-screen threat cues
- Server-owned enemy engagement tokens by role/difficulty, active crowd positioning and boss punish windows
- Training/accessibility/telemetry foundation and optional cosmetic encounter KO/combo counter; perfect-dodge rewards, hit-confirm cancels, hazards and destruction deferred
| Task | Size | Title | Test | Evidence |
|---|---|---|---|---|
| GM-02 proposed | L | GM arena for the vertical slice: preset_builds for the vertical-slice builds in builds.json (warblade, windarcher, pyromancer; /gm preset per presetRule: level 40, gear, gems, planBuild Atlas, Codex, hotbar), item_forge for slice items (/gm item, /gm affix, /gm socket, /gm refine), one-click Dewgrass/Orchard monster packs in spawn_ring, teleport inside the slice (/gm tp) and the Atlas, Codex and facet resets (/gm reset atlas|codex|facets) Proposed: owner decision 2026-10-08 (GM arena run). GM rules: every GM action is audited (who, what, where); GM-made items carry the gm flag and can never be traded, sold, listed or mailed; until M6 test builds use a dev-only local GM flag (never in release builds); from M6 access is by the gm or qa role, agents never grant roles, and the owner gives his own account the gm role with the local CLI (GM-04). GM tools never add a global time-scale and never hide telegraphs. | each slice preset's Atlas allocation equals planBuild from the wiki Atlas planner (golden test); forged and preset items match the forge preview (affix tier and value in range) and carry the gm flag, and every trade, sell, list or mail path that exists by then refuses them; every slice pack and teleport target resolves; one automated test per GM-02 command | per-build preset screenshot (gear, Atlas, hotbar) + forge preview vs in-game popup pair + audit log excerpt (.txt) |
M5World greybox → art (Amber Basin 4×4 km)productionNOT STARTEDafter M1
Streamed terrain, roads, 12 zones, Amber Gate town, waypoints, mount, navigation grid shared with the server.
- Heightmap + splat generator (deterministic) from world.json
- 256 m chunk streaming + LOD + impostors
- Walkability grid (1 m) + HPA* used by server and client
- Amber Gate greybox → kit art (ART-ENV-054)
- Vegetation instancing + wind; sky/fog/lighting per zone mood
- Mount + waypoint travel + click-to-travel (map/minimap click → navmesh path, auto-mount over 40 m, waypoint offer; controls.json clickToTravel)
- Time-of-day keyframes and weather states per area (time-weather.json, ADR-030), night variants of the area beds, contrast and perf checks across the review matrix
M6Online core at 1,000 per channelproductionNOT STARTEDafter M1, M4
Accounts, characters, persistence, channels (1,000 cap), parties, chat, reconnect; real clients + bots together.
- Gateway (axum) + Postgres schema + migrations
- Admission + channel assignment + transfer
- Parties (4), chat, friends, inspect (opt-in)
- Inventory/stash/bank transactions
- Reconnect + crash recovery
- Load: 1,000 bots + 10 real clients for 60 min
- Accounts: one-tap Google sign-in (web One Tap, Android Credential Manager, iOS Google + Sign in with Apple, Windows system-browser PKCE); gateway token verification + Zoen sessions (docs/tech/ACCOUNTS_AUTH.md)
- Security system: rule engine over security.json (certain → auto permanent ban + rollback; strong → restriction; watch → log), ban screen with ban id + Contact us, appeal review tool, rule-quality limits; red-team and false-positive gates (docs/tech/SECURITY_ANTICHEAT.md)
- Version gate: /v1/status minimum version; Update required (native) and reload banner (Web)
| Task | Size | Title | Test | Evidence |
|---|---|---|---|---|
| GM-04 proposed | M | GM role access: a local CLI the owner runs to give his own account the gm role (and qa to testers he picks), audited; /gm commands switch from the dev-only local GM flag to the gm/qa role check; agents build and test it on a throwaway local database and never grant a role Proposed: owner decision 2026-10-08 (GM arena run). Role access starts with the M6 accounts, so the CLI lands here, before GM-03 (M9). The owner runs it on his own account; agents never grant roles. | on a throwaway local database: grant and revoke write audit rows; /gm commands are refused without gm or qa and allowed with it; release builds contain no dev GM flag (build check) | CLI test log + audit rows excerpt (.txt) |
M7Quests + Auto-Quest + Auto-HuntproductionNOT STARTEDafter M5, M6
Quest engine runs quests.json; Auto-Quest 1→10 hands-free; Auto-Hunt online; offline Auto-Hunt as a visible actor for 4 h.
- Quest state machine + dialogue UI
- Auto-Quest planner (travel/talk/hunt/collect/interact/escort)
- Auto-Hunt presets (targets, radius, potions, buffs, loot filter, return rules)
- Offline actor lease + receipts
- Bot test: fresh character reaches L10 with Auto-Quest only
M8Content alphaproductionNOT STARTEDafter M7
All 9 pure builds, all 20 monsters + elites, chapters 1–3, Kiln Depths dungeon, items/crafting/refinement.
- 6 more pure builds (36 skills)
- 16 more monsters + elites
- Chapters 1–3 (31 quests)
- Kiln Depths dungeon + ranking
- Crafting/orbs/refinement +15 per items doc
- Stash/stalls
M9Content betaproductionNOT STARTEDafter M8
6 hybrid builds, chapters 4–5, Bellbound Regent, Kharuun, Lantern Convoy event.
- 6 hybrid builds (36 skills)
- Chapters 4–5 (16 quests)
- 2 bosses with telegraphs + break pressure
- Lantern Convoy (16 players)
- Boss reward caps + receipts
- Named boss music start/end/reset/leash/leave/death/reconnect and warning ducking; ordinary outdoor travel remains environment-only
| Task | Size | Title | Test | Evidence |
|---|---|---|---|---|
| GM-03 proposed | L | GM arena complete: boss_pit (/gm boss for the Bellbound Regent and Kharuun with start phase, enrage-timer toggle, fight reset and telegraph timing overlay), all 18 preset_builds (presetRule; Atlas by planBuild, the Atlas page's planner), item_forge over every base, affix, tier, socket, refinement +0…+15 and the fractured flag, /gm give stacks up to 999, /gm tp to every waypoint, area, boss spawn and quest step, and every gm-room.json command with its own automated test Proposed: owner decision 2026-10-08 (GM arena run). Area features with no gm-room.json command yet (boss enrage timer and fight reset, dummy armour/resistance presets, show server positions, refill life and mana, remove buffs) get a proposed command there first, so each has its test. GM rules: every GM action is audited (who, what, where); GM-made items carry the gm flag and can never be traded, sold, listed or mailed; until M6 test builds use a dev-only local GM flag (never in release builds); from M6 access is by the gm or qa role, agents never grant roles, and the owner gives his own account the gm role with the local CLI (GM-04). GM tools never add a global time-scale and never hide telegraphs. | a coverage check fails when any gm-room.json command has no automated test; 18/18 preset Atlas allocations equal planBuild; the forge round-trips every base and every affix tier's value bounds; every teleport target resolves; each boss start phase and the enrage toggle reach the expected server state with telegraphs visible on Low; trade, sell, listing and mail refuse gm items | command coverage report JSON + boss pit clip per start phase on Low + 18-build preset contact sheet + audit log excerpt (.txt) |
M10Art + audio + polishpolishNOT STARTEDafter M9
Final HUD art, VFX polish, music + SFX pass, accessibility, performance tuning on reference devices.
- Replace every placeholder (art-requests empty for P0/P1)
- VFX polish per build palette
- Town + GM-room + named boss encounter themes (ADR-026), outdoor environment beds/emitters/accents + full SFX pass
- Accessibility (flash reduction, colour-blind, remap)
- Perf: Low/Mid/High/Ultra on 3 devices
M11Platform + closed alphareleaseNOT STARTEDafter M10
PWA + Capacitor builds, hosting, monitoring, closed alpha.
- Web build (Low–Mid) on the CDN: version check + reload prompt
- Store builds: Windows installer + launcher/patcher, Android AAB, iOS (store accounts are owner decisions)
- Hosting + monitoring + backups
- Closed alpha (50–200 players) + telemetry review
- Premium public site (docs/design/PUBLIC_SITE.md): visual directions → Home, Showcase, public Roadmap, Event times, Skill + Inventory playgrounds, Account, Redeem key; Lighthouse ≥ 90 mobile
- Auto-patching: Windows launcher/patcher (signed manifest, deltas, verify, rollback), Addressables remote content on all platforms, Android in-app updates, iOS update screen (docs/tech/PATCHING.md)
- Site + admin started early in the WEB lane (ADR-025, tasks WEB-*); this milestone adds store builds and the live account pages.
◆Critical path
Before content expansion, follow the preparation gates: M2 establishes the rig/mannequin, verifies movement-first controls with C1–C18 and reviews the first skill from all required views. M4 proves the full battle slice; M5 applies area briefs, movement/camera checks and environmental readability. These are planned tasks; this wiki update does not start engine development.
M0 toolchain → M1 render + network at scale → M2 one perfect skill → M3 character pipeline → M4 vertical slice
runs in parallel with M5 world (after M1). Then M6 online core → M7 quests + automation → M8 content alpha → M9 content beta → M10 polish → M11 alpha.
The GM arena (GM room) grows with the game: GM-01 in M2 right after the Combat Lab, GM-02 in M4
for the slice, GM-03 at the end of M9 with every /gm command tested; GM-04 in M6 is the owner's local role CLI.
◆Token planning
Per-task token ranges come from this wiki's own build (see the Ledger). They are rough and get recalibrated after M0 with real game tasks. The Ledger page always shows the actual running total.
Source: zoen/docs/roadmap/ROADMAP.md · 258 words · edit the Markdown, not this page.
