Complete local prototype — implementation specification
The owner approved the nine local prototype improvements on 2026-09-08. Remote play is excluded. The owner chose interviews before implementation of the proposed rule changes. This specification defines scope, shared contracts, acceptance criteria, and agent handoffs. It does not claim that these features are implemented.
Track status and dependencies in EPIC-003, its nine features, and TASK-033 through TASK-066. The local source is liste. The portable copy is site/data/liste.json, which contains the full work contracts and dependency links. This document describes the design; it is not a second status tracker.
All 100 questions are answered. Read the processed owner decisions before any older contract. Work on feature/local-playtest-prototype until owner review; no deployment or merge.
Current-rule addendum, 2026-09-09: TASK-092 supersedes this specification's older Jump-climbing Heat and fall requirements. New games use paid vertical movement: ordinary legs pay destination terrain entry plus the absolute elevation change, working Jump legs ignore the elevation surcharge in both directions, and vertical movement adds no Heat or fall consequence. Existing saves preserve their embedded legacy behavior. The original task labels below remain as historical scope records.
Historical starting baseline (before this branch)
Read docs/reviews/2026-09-08-session-handoff.md and the assembly and melee brief first. The implementation notes distinguish current mechanics from provisional values. Check current source before using an older inventory as a bug list.
- The visual box and sprue builder, separate arms and held equipment, and hard build limits work.
- Interactive melee rolls both pools up front. Successful dice fund both attacks and parries. Failed dice fund neither. This is confirmed owner intent.
- Higher Piloting acts first in melee; ties favor the initiator. A fresh melee costs a Full action. The defender retains its normal activation. Keep these decisions.
- The packet and bench share navigation and styling. Preserve that design across the new screens.
- Workshop drafts and one-to-three-mech teams persist locally. Complete human games do not yet have a durable save/replay format.
TurnControllersupports human activations and melee decisions. Other reactions resolve synchronously. Deployment is automatic. Initiative currently starts the rolled winner automatically.runMatchsupports bot matches and policy-driven substitutions. It is not a human match or hidden sideboard controller.- Battle already has event logs, activation snapshots, and bot replay. Play already has range, movement and target hints. Extend these rather than build parallel rules.
The last recorded baseline was 313 passing tests, a passing typecheck, and a passing packet build. Re-run relevant checks when implementation starts. Do not describe the catalog or melee as balanced.
Approved scope
| Feature | Result the player should get |
|---|---|
| FEAT-014 · Full local match | Build a four-mech roster, field three, deploy manually, play best of three, and use the reserve between games. |
| FEAT-015 · Board and inspector | Keep the board central; pan, zoom, focus, and inspect a mech without losing the current choice. |
| FEAT-016 · Dice presentation | See successful source-labeled opportunity pips and their consumption; detailed rolls remain in the log; follow ranged and melee outcomes at a readable pace. |
| FEAT-017 · Action previews | See legal choices, costs, paths, cover, objectives, possible reactions, and why an action is unavailable. |
| FEAT-018 · Saves and replay | Resume a paused human game, export it, and replay the actual human decisions with the original content. |
| FEAT-019 · Interactive rules | Carry activation alternation across rounds and resolve reactions, bonus rounds, and Jump-leg climbing Heat; remove Overcharge using interviewed rules. |
| FEAT-020 · Workshop library | Name, save, copy, edit, compare, and transfer builds and rosters; understand pilot synergies and melee pools. |
| FEAT-021 · Sandbox | Set positions and damage, repeat trials, swap sides, and use clearly marked controlled dice and rewind. |
| FEAT-022 · Playtest and learning | Bookmark confusing moments, export reports, learn through short scenarios, and use keyboard/touch/text/motion controls. |
No rooms, network synchronization, accounts, spectators, matchmaking, or remote reconnect work is part of this epic. Existing hosted static play and file export remain supported. New factions, campaign progression, new objective types, and balance retuning are separate scope. A competitive countdown is not implied by local prototype completeness; its timing during defender choices needs a separate owner decision.
Interview record and gates
The owner now prefers a bulk Markdown interview, with follow-ups after reviewing their answers. Use the answer sheet linked above. Record answers separately from proposals, preserve blank answers as unresolved, and batch documentation/tracker updates and builds. Do not resume a question-by-question interview unless requested. A rulebook label such as Locked does not override the owner's latest instruction to interview these mechanics.
Activation continuity confirmed: the owner wants the next alternating activation to carry across round boundaries. There is no per-round initiative roll or winner choice. Alternation also continues directly from deployment: the first placer takes the first activation. Reaction refresh is also confirmed: after all surviving mechs have activated, score objectives and refresh each mech’s once-per-round Reaction before the next activation. Other status durations retain their written expiry (Q016). Refreshing the Reaction budget does not itself grant Prepared or Overwatch.
Reaction preparation confirmed: Prepare remains a Quick action required for reactions other than Overwatch. Overwatch arms itself through its Full action. Melee parries remain independent: they require no Prepare and do not spend the once-per-round Reaction. The owner also confirmed that declining spends no Reaction and preserves Prepared or Overwatch until its normal expiry. A declined Overwatch opportunity does not prevent reacting to a later eligible move. When several friendly mechs can react to the same event, the owner confirmed that their player chooses the order and decides one at a time after seeing each result. Check remaining eligibility after each reaction; each reacting mech spends its own Reaction. Prepare does not reserve a reaction type or weapon: choose from eligible reactions and legal weapons when the trigger occurs. Overwatch remains tied to the weapon named when it was set. This weapon-selection policy is confirmed.
Overwatch area and timing: Q034 changes the area to a cone; the follow-up will settle origin and angle. Select one elevation and name a ranged weapon. Show its fixed outline and distinguish currently blocked tiles. Let the reacting player choose an eligible point on the untraveled path or pass. Resolve at that position, revalidate remaining options, and never return to an already passed point. Overwatch expires at the owner’s next activation. Other area wording in older contracts is superseded.
Reaction continuation confirmed: Disengage resolves just before leaving adjacency. Overwatch resolves at the chosen watched hex. After reactions, a surviving mech continues its declared path if still able. Destruction or a disabling effect cancels only movement or follow-up actions that it makes illegal. Reaction attacks cannot trigger further reactions. Revalidate each remaining option after a result. The branch pauses at plain reaction windows and reconstructs the interrupted action from accepted responses. Per-step movement events preserve the exact firing position.
Deployment confirmed: players alternate placing one mech at a time. Use a simple d6 roll-off; reroll ties. The winner chooses the board end. The loser places first. The owner answered “Alternate” and “simple roll off” to these proposals. H8 must reflect this die choice. Selecting a hex previews the placement; explicit confirmation commits it. Initial team selection and sideboard reveal follow Q024–Q033 in the processed answers.
| Decision task | Questions that must be settled before its implementation |
|---|---|
| TASK-035 · Deployment | Placement order and board-end roll, confirmed above. |
| TASK-036 · Activation order | Confirmed: no new initiative roll or choice each round; continue the alternating activation sequence after scoring. Confirmed: continue directly from deployment; the first placer takes the first activation. |
| TASK-037 · Overcharge | Resolved: remove Overcharge (Q001–008). |
| TASK-038 · Endgame | Extra-round scoring; wipe timing; Hull calculation; second tie; treatment of draws in a match. |
| TASK-039 · Climbing heat | Which climbs trigger heat, how often, when heat resolves, and what damage can interrupt along the path. |
| TASK-040 · Reactions | Interview complete: preparation, refresh, decline retention, sequential player-chosen order, trigger-time weapon choice, fixed single-elevation Overwatch area, firing-point choice, movement continuation, and no reaction chains. Implementation remains TASK-054. |
| TASK-041 · Match setup | Initial fielded selection/reveal, roster and pilot lock, one swap or stand pat plus legal ammunition changes, seeded random maps, and private local handoffs. |
Confirmed decisions release only their dependent work. Unanswered questions do not block board layout, the browser harness, session contracts, or library work. Do not reopen the shared successful melee pool, arms versus held weapons, hard capacity limits, or defender activation rules without a new owner request.
Shared architecture contracts
Accepted follow-up experiment: Enraged (E9, 2026-09-09)
The owner authorized a local Enraged experiment after the original interview implementation. Enemy-caused allied destruction queues every survivor's next own activation, including when a survivor is already active. Enemy Heat and lethal pushes count; own Heat and environmental deaths do not. At activation start, add +2 ordinary movement allowance without changing Speed or Boost. Provide one failed offensive die reroll shared across that whole activation. Automatically reroll the first eligible failed ranged hit, or the first failed non-defense-only die in an initiated melee pool; retain existing modifier dice and keep the replacement result. Exclude reactions, the defender's pool, and shield/parry-only dice. Additional deaths cannot stack or refresh the current bonus; a death during an active Enraged turn may queue the next one. End the active benefit and unused reroll at activation end.
Engine state, snapshots, and event-time replay must distinguish pending, active, and available/spent reroll state. Attack/pool records retain both original and replacement values; presentation must not generate another roll. Show the bonus in the live inspector, unit status, and roll explanations without adding a decision prompt. New games default to the enabled rule, including scenarios that override unrelated rule values. Controlled experiments must explicitly set the flag false. Bump the session engine version and reject older sessions without modifying their files; no migration or replay under new rules is promised. Keep rejected-command/RNG parity, interruption reconstruction, and save/restore exact. This is an accepted experiment with a provisional automatic first-failure policy, not evidence of balance improvement.
Authoritative state and identity
Keep combat and legality in engine/. The UI issues commands and renders read models. Give each roster mech a stable instance ID distinct from its catalog/build ID. A saved library build, its roster copy, and its deployed instance must not share mutable data.
Separate a four-slot roster from its three selected deployed instances. A single build must meet its hard limits. B5 applies pilot uniqueness without part-copy limits to the four-mech roster. B3 applies Team Cap to the deployed three. A legacy team of one to three mechs remains usable in a trial; migration must not silently invent a fourth build or discard the old team. The completed interview permits ammunition edits between games; parts and pilots remain locked.
Use explicit phases and decision ownership. Proposed phase vocabulary: roster setup, end selection, deployment, activation choice, activation, melee response, reaction response, game result, sideboard, and match result. TASK-033 owns the exact typed API. Every waiting choice needs a stable ID, eligible actor, legal options, and continuation. UI-only hover, pinned inspection, and selected parry dice are separate view state.
Commands and exact reconstruction
Record the initial configuration and each accepted command in order. A command contains a schema version, sequence/decision ID, actor, kind, and validated payload. Rejected or duplicate commands must not alter state or advance RNG. Automatic bot choices must be reproducible under a pinned engine/policy version; record enough audit information to detect divergence.
Start with deterministic reconstruction from initial configuration and commands. Current makeRng hides its state; TurnController has private queues, budgets, and continuation fields; a melee constructor rolls dice. Serializing these class instances is not a valid save strategy. If reconstruction becomes too slow, add a separately tested checkpoint/hydration contract that includes RNG and all pending continuations. Never reroll a restored pool.
The envelope must identify its format and compatible engine/rules version. Include the seed, resolved map, roster and deployed instance IDs, controller/bot modes and policy, all effective rules and numeric tuning, command history, phase, and recoverable view state. Catalog alone is insufficient: melee and other tuning JSON may be imported outside the Catalog type. TASK-033 must inventory these inputs; TASK-042 must remove mutable ambient dependencies from an active session.
Use an immutable content snapshot for an active session. Workshop and Tuner edits apply to future sessions. Unsupported rules versions produce a clear error rather than a plausible replay with changed behavior. Import validation must complete before replacing the last good save. Local storage failures must preserve the active game and offer file export.
Resumable rules
Expose plain reaction windows and serialize accepted responses with their exact trigger identity. Reconstruct the interrupted synchronous action with those responses supplied in advance. Catch only the dedicated suspension; validation and exhausted dice scripts remain errors. On each acceptance, revalidate weapons, targets, positions, life state, budgets, and the continuation. A reaction can destroy the mover or disable an arm. Do not finish the original action blindly. A declined prompt follows the interviewed retention policy.
Keep the once-per-round Reaction budget distinct from responsive melee parries. Keep bot and human decision paths on the same rule implementation. Adding a phase requires a save/resume fixture in that phase, including when a bot initiated the interrupted action.
Queries, events, and presentation
Read-only preview queries expose legal targets and structured rejection reasons. They must not consume randomness or execute actions speculatively. Show deterministic costs separately from roll ranges and conditional enemy reactions. Submit the command through normal validation even after a valid preview.
Dice trays, diagrams, playback, and reports consume actual engine events. They never roll or independently calculate damage. fire summaries and per-shot events overlap; define canonical counting sources before analytics. Replay must reconstruct the positions at the event, not draw a shot from a later activation snapshot.
Keep resolveFire dice order and worked example J intact. Document any approved event or RNG contract change with a version boundary and test. Numerical tuning stays in JSON. No balance change belongs in a presentation task.
Local privacy and sandbox separation
Private sideboard choices use a pass-device curtain, then a joint reveal at the agreed phase. On reload, return to the curtain rather than expose the previous player's selection. Do not show hidden choices in public panels or logs. This is shared-device etiquette; local storage and exported files are not a security boundary.
Normal match commands cannot edit damage, force dice, or rewind. Sandbox and tutorials declare their mode in their configuration and exports. Rewind creates or restores a sandbox branch; it never rewrites a completed ordinary match report. Controlled dice must be validated against the requested die and visibly identified.
Delivery sequence and ownership
This sequence describes integration order. Liste holds live status and exact dependencies.
- Establish contracts and verification. TASK-033 defines shared interfaces; TASK-034 checks in browser coverage. Continue the decision tasks alongside this work.
- Make Play usable and recoverable. Commands, saves, roster schema, board, inspector, and library establish the base. These streams can use separate owners after contracts are agreed.
- Complete the local game loop. Add each interviewed rule, deployment, match controller, and hidden sideboard. Every new decision extends persistence tests.
- Explain and exercise the game. Integrate dice playback, action previews, comparisons, replay, sandbox trials, reports, and learning scenarios. Build accessibility into each component and perform the complete audit here.
- Verify the complete experience. TASK-066 runs the cross-feature acceptance matrix and refreshes the packet and handoff with actual results.
Assign one integration owner to engine/battle.ts, engine/turn.ts, and session contracts. Assign one to the Play shell. Other agents should implement separate modules against those contracts and coordinate shared-file edits. Do not have multiple agents independently redesign controller state, roster storage, or Play navigation. Worktrees do not remove semantic conflicts in these APIs.
The full interview is answered and processed. Implementation is active on feature/local-playtest-prototype. Use liste for current task status, and the session handoff for verification evidence. Only the two named follow-ups remain provisional; do not represent defaults as owner-confirmed decisions.
Work package index
Each task's full body in liste and site/data/liste.json contains its objective, source entry points, exclusions, acceptance checks, dependencies, and handoff requirements.
| Task | Work package | Depends on |
|---|---|---|
| TASK-033 | Define shared session, command, decision, and roster contracts | None |
| TASK-034 | Check in a repeatable browser interaction test harness | None |
| TASK-035 | Deployment interview: placement, roll-off, and reveal order | None |
| TASK-036 | Activation-order interview: continuous alternation and game start | None |
| TASK-037 | Overcharge decision: remove the feature | None |
| TASK-038 | Endgame interview: sudden death and match draws | None |
| TASK-039 | Climbing heat interview: trigger and action boundaries | None |
| TASK-040 | Reaction interview: optional responses and trigger ordering | None |
| TASK-041 | Match setup interview: roster lock and local hidden sideboarding | None |
| TASK-042 | Route human play through deterministic serializable commands | TASK-033 |
| TASK-043 | Persist and restore complete local sessions | TASK-042 |
| TASK-044 | Separate four-mech rosters from legal deployed teams | TASK-033 |
| TASK-045 | Build a named local library with edit, duplicate, and transfer | TASK-044 |
| TASK-046 | Show build comparisons, melee pools, and pilot synergies | TASK-045 |
| TASK-047 | Build a board-centered Play layout and camera controls | TASK-033 |
| TASK-048 | Add mech silhouettes and a persistent tactical inspector | TASK-047 |
| TASK-049 | Present combat dice and outcomes as readable sequences | TASK-042, TASK-048 |
| TASK-050 | Expose engine-backed action and movement previews | TASK-042, TASK-047 |
| TASK-051 | Connect previews to action controls and rule explanations | TASK-050, TASK-048 |
| TASK-052 | Implement manual deployment as a resumable phase | TASK-042, TASK-044, TASK-035 |
| TASK-053 | Carry alternating activations across round boundaries | TASK-042, TASK-036 |
| TASK-054 | Pause for optional human reactions and resume safely | TASK-042, TASK-040 |
| TASK-055 | Remove Overcharge from active rules and prototype state | TASK-042, TASK-037 |
| TASK-056 | Implement approved sudden-death and terminal result rules | TASK-042, TASK-038 |
| TASK-057 | Implement approved climbing heat and movement interruption | TASK-042, TASK-039 |
| TASK-058 | Add a human best-of-three match controller | TASK-052, TASK-053, TASK-056, TASK-044, TASK-041 |
| TASK-059 | Add local hidden sideboard selection and reveal | TASK-058 |
| TASK-060 | Replay human sessions with exact decision and event positions | TASK-043, TASK-049 |
| TASK-061 | Build an isolated scenario editor and resettable trials | TASK-042, TASK-045, TASK-050 |
| TASK-062 | Add repeatable tactical trial fixtures and side swapping | TASK-061, TASK-054, TASK-055, TASK-057 |
| TASK-063 | Export playtest reports and annotated decision bookmarks | TASK-060, TASK-059 |
| TASK-064 | Add guided assembly and first-game learning scenarios | TASK-049, TASK-050, TASK-059, TASK-054 |
| TASK-065 | Verify keyboard, touch, text, and motion controls across Play | TASK-047, TASK-049, TASK-059, TASK-034 |
| TASK-066 | Integrate the complete local prototype and update packet evidence | TASK-046, TASK-051, TASK-062, TASK-063, TASK-064, TASK-065, TASK-055, TASK-057 |
Integrated acceptance matrix
| Journey | Required evidence |
|---|---|
| Assembly to legal match | Build four named mechs including independent arms, a two-handed weapon, and a shield; choose three; report hard build/roster/team failures correctly; deploy legally from either end. |
| Interactive melee | Inspect sources and rolls; select/deselect a two-die parry and shield die; handle an empty pool and arm loss; start another fresh exchange; retain the defender's normal activation. |
| Durable decisions | Save and reload at end selection, partial deployment, round scoring, activation choice, pending parry, reaction, result, and private sideboard. Next actor, budgets, accepted commands, and next dice match uninterrupted play. |
| Complete match | Finish a 2-0 and 2-1 local match, plus the approved draw and sudden-death cases; validate swaps, roster locks, map order, fresh game state, and terminal results. |
| Explain an action | Place a cone watch area (Q034; final geometry pending) at a chosen elevation; verify movement through it can trigger a shot while other elevations and tiles outside it cannot. Select a path and target; compare cover, elevation, costs, objective effects, and possible reactions; cancel without mutation; execute the same legal action. |
| Transfer and replay | Export/import a human game and bookmark; reconstruct events and transient positions; reject corrupt/incompatible files without losing the prior save; change Tuner without affecting the running game. |
| Repeat a trial | Reset and swap sides in a melee/heat/reaction scenario; preserve setup and seed; label controlled dice; prevent scenario edits and rewind in ordinary matches. |
| Accessible packet | Complete key flows by keyboard and touch; inspect without hover; use reduced motion and enlarged text; test tablet landscape and desktop widths; follow a rule link and recover the game. |
For engine changes, add behavior tests before implementation. Preserve seeded runGame/runBatch behavior and existing rule coverage; intentional versioned behavior changes need explicit fixtures. UI work needs meaningful browser coverage, not assertions that duplicate component internals. Run pnpm test, pnpm typecheck, the checked-in browser command, pnpm site:data, and pnpm site:build for the integrated release. Record exact commands, outcomes, and revision.
A functional trial is not a balance experiment. Any later balance verdict requires recorded catalog/rules, seed range, both sides, and the aggression-grid equilibrium under the existing tuning workflow.
Picking up work in another session
- Read this specification and the session handoff. Inspect the current branch and uncommitted changes.
- Find the target item and its dependencies in liste, or read
site/data/liste.jsonif the local tracker is absent or stale. The task body is the work contract. - Claim a ready task in the authoritative tracker and state file ownership before edits. Confirm that any required interview decision is recorded as agreed.
- Implement the bounded task and its acceptance cases. Do not expand a presentation task into a rules redesign.
- Hand off changed files, public API changes, checks/results, unresolved questions, and the next ready dependency. Mark done only when the contract is met.
The owner excludes .liste/ changes from Git pushes. Preserve that preference. Commit the exported site/data/liste.json and design documents so another agent has the contracts. A checkout with older .liste/ files must not run site:data over the newer snapshot. Use the snapshot read-only for pickup until the authoritative local tracker is available or deliberately reconciled; do not invent replacement IDs or overwrite newer task state.
Deployment is a separate release action. A passing build is not a deployment, and a plan is not an implemented feature. Record which source revision is live when deployment is requested and completed.