Files
maze32/PLANS.md
T

662 lines
29 KiB
Markdown

# maze32 Implementation Plan
## Plan rules
1. Milestones may be planned and added in batches.
2. Milestone numbering starts at 1 and increases without gaps. Headings use the
zero-padded form `Milestone 001`, `Milestone 002`, and so on.
3. Milestones are executed strictly in ascending numerical order. Work on a
milestone may begin only after every preceding milestone is `COMPLETE`.
4. At most one milestone may have status `IN_PROGRESS`.
5. A newly discovered milestone is appended to the end of the plan. Existing
milestone numbers and execution order are not changed without explicit
project-owner approval.
6. Every milestone contains an objective, scope, deliverables, acceptance
criteria, evidence, and status.
7. Allowed statuses are `NOT_STARTED`, `IN_PROGRESS`, `BLOCKED`, and `COMPLETE`.
8. A milestone may be marked `COMPLETE` only when every acceptance criterion is
satisfied and concrete evidence is recorded in the milestone.
9. Evidence must identify the command, test result, inspected artifact, or
hardware observation that demonstrates completion. Statements such as
"implemented" or "looks correct" are not sufficient evidence.
10. A `NOT_STARTED` milestone explicitly records that completion evidence is
not yet available. Expected evidence may be listed in advance.
11. If later work invalidates recorded evidence, reopen the affected milestone
and change its status before continuing.
12. All project documentation, milestone text, source comments, test names,
protocol identifiers, and system log messages are written in English.
Player-facing browser UI copy, game messages, and browser errors are
written in Russian.
## Milestone 001 — Requirements and technical baseline
**Status:** `COMPLETE`
### Objective
Establish a consistent, implementation-ready product specification,
architecture, board passport, build profile, and Flash layout without modifying
the read-only project sources.
### Scope
- Consolidate the agreed gameplay, browser, lobby, observer, reconnection, and
Wi-Fi provisioning requirements.
- Establish the ESP32-C6/ESP-IDF/PlatformIO baseline inherited from Battleship.
- Resolve the stale 2 MB versus confirmed 4 MB Flash configuration.
- Define the authoritative-server architecture and verification boundaries.
- Establish the sequential milestone and evidence policy.
### Deliverables
- `MVP.md`
- `ARCHITECTURE.md`
- `PLANS.md`
- `AGENTS.md`
- `docs/BOARD_PASSPORT.md`
- `platformio.ini`
- `partitions.csv`
- `sdkconfig.defaults`
### Acceptance criteria
1. All canonical project documentation is in English.
2. `MVP.md` captures all agreed roles, gameplay rules, networking behavior,
technical constraints, exclusions, and acceptance criteria.
3. `ARCHITECTURE.md` defines server authority, component boundaries, state
machines, role-specific projection, protocol direction, storage, and
verification strategy.
4. The build profile pins PlatformIO `espressif32@7.0.1`, ESP-IDF, the compatible
`esp32-c6-devkitm-1` profile, and 4 MB Flash.
5. The partition layout is contiguous and ends exactly at `0x400000`.
6. `sdkconfig.defaults` explicitly selects 4 MB Flash and 16 LwIP sockets.
7. The board passport matches the canonical configuration and does not claim an
unverified physical board model, GPIO mapping, LED, or PSRAM.
8. No file under `sources/` is modified.
9. PlatformIO can parse and resolve the canonical project configuration.
### Evidence
- `MVP.md` contains the complete English product and acceptance specification.
- `ARCHITECTURE.md` contains the English runtime, component, state-machine,
protocol, memory, failure, and verification contracts.
- On 2026-09-03, `/home/sasa/.platformio/penv/bin/pio project config` exited
successfully and resolved environment `esp32-c6-devkitm-1` with
`espressif32@7.0.1`, ESP-IDF, explicit 4 MB build/upload sizes,
`partitions.csv`, LittleFS, and `sdkconfig.defaults`. PlatformIO subsequently
emitted a telemetry-cache permission warning during process shutdown; it did
not prevent configuration parsing.
- On 2026-09-03, an `awk` continuity and end-address check over
`partitions.csv` reported the factory partition ending at `0x210000`, the
LittleFS partition ending at `0x400000`, and no gaps or overlaps from NVS
through the end of Flash.
- On 2026-09-03, `rg` confirmed
`CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y` and `CONFIG_LWIP_MAX_SOCKETS=16` in both
`sdkconfig.defaults` and the generated ESP-IDF configuration.
- `docs/BOARD_PASSPORT.md` records the confirmed ESP32-C6FH4, 4 MB Flash,
no-required-PSRAM baseline and the remaining explicit hardware unknowns.
- Canonical files were created outside `sources/`; the reference files under
`sources/` were not edited.
### Completion note
Milestone 001 establishes documentation and configuration only. It does not
claim that firmware source code exists, that a firmware image builds, or that
the target board has passed runtime tests. Those claims require evidence in
later milestones.
Milestone 001 was reopened on 2026-09-03 after its recorded evidence was found
to disagree with the checked-in canonical files. The canonical `MVP.md`
location, explicit Flash configuration, generated SDK configuration, and board
passport were repaired and reverified before returning the milestone to
`COMPLETE`. No Milestone 002 implementation work was started.
## Milestone 002 — Firmware skeleton and reproducible build
**Status:** `COMPLETE`
### Objective
Create the smallest maintainable ESP-IDF firmware and web-asset skeleton that
builds reproducibly with the locked platform and partition configuration.
### Scope
- Establish firmware, component, test, web, and script directories.
- Add startup logging, version information, and a minimal health state.
- Mount LittleFS and serve a minimal static page.
- Implement deterministic compression and filesystem-image packaging for web
assets.
- Add build-time application and filesystem size checks.
### Deliverables
- Minimal bootable firmware source tree.
- Minimal static web application.
- Web-asset compression and LittleFS packaging script.
- Host-test entry point for portable code.
- Documented build, filesystem-build, upload, and monitor commands.
### Acceptance criteria
1. A clean PlatformIO build succeeds with the locked environment.
2. The application image fits the 2 MiB factory partition.
3. The LittleFS image fits the 1,984 KiB filesystem partition.
4. Web-asset generation is deterministic and does not require manual edits.
5. The firmware boots on the target board, mounts LittleFS, and reports its
version and health state.
### Evidence
- On 2026-09-03, `/home/sasa/.platformio/penv/bin/pio project config` parsed
the updated configuration successfully with the locked platform, ESP-IDF,
4 MB Flash, root partition table, LittleFS, pinned `esp_littlefs`, bounded
LittleFS settings, and the build hook.
- On 2026-09-03, `./scripts/run_host_tests.sh` reported
`health state tests: PASS` and
`web asset reproducibility: PASS
(611eacdb06b81bdb064a9074352ff4c6f82d3af3ad3d01e65705387744b86b21)`.
- After `/home/sasa/.platformio/penv/bin/pio run --target clean`, running
`/home/sasa/.platformio/penv/bin/pio run` on 2026-09-03 completed with
`[SUCCESS]` in 43.10 seconds. PlatformIO reported 14,084 bytes of RAM and
350,232 of 2,097,152 application bytes in use. The independent build hook
reported `firmware.bin uses 350864/2097152 bytes in partition factory`.
- Running `/home/sasa/.platformio/penv/bin/pio run --target buildfs` on
2026-09-03 regenerated `data/index.html.gz`, built the LittleFS image, and
reported `[SUCCESS]`. The independent build hook reported
`littlefs.bin uses 2031616/2031616 bytes in partition littlefs`; the image is
intentionally emitted at full partition size and contains the 683-byte
compressed application asset.
- Two LittleFS builds separated by a clean produced the identical SHA-256
`ad203373be69f4541106b2d0dfd7096adb8132967ab49e2d23c391ede8f4d4f5`.
The generated gzip asset remained
`950c60077c381d4484c11b43762bc5c8378587b6cd91924c344cfbc406771bb9`.
Listing the image showed both file and image creation times normalized to
1970-01-01, demonstrating deterministic compression and packaging.
- `strings .pio/build/esp32-c6-devkitm-1/firmware.bin` found firmware version
`0.2.0` and the startup log formats for version, LittleFS capacity, and health
state. This verifies their presence in the built artifact but is not a
substitute for target-board execution.
- On 2026-09-03, `/home/sasa/.platformio/penv/bin/pio run --target uploadfs
--upload-port /dev/ttyACM0` wrote and hash-verified the 2,031,616-byte
LittleFS image at `0x210000`. A subsequent application upload identified the
target as `ESP32-C6FH4 (QFN32) (revision v0.2)` with embedded 4 MB Flash and
USB Serial/JTAG, wrote the 350,864-byte application image, and verified its
hash.
- A target-board boot capture on 2026-09-03 reported `App version: 0.2.0`,
`SPI Flash Size : 4MB`,
`LittleFS mounted: total=2031616 bytes, used=12288 bytes`,
`HTTP server ready with static and health endpoints`, and
`Health state: serving`. The capture contained no application error after
startup. This supplies the physical-board evidence for acceptance criterion
5.
## Milestone 003 — Wi-Fi provisioning and persistent configuration
**Status:** `COMPLETE`
### Objective
Implement station-first Wi-Fi operation with NVS persistence and a fallback
access-point provisioning flow.
### Scope
- Versioned NVS configuration storage.
- Station connection using saved credentials.
- Fallback access point when configuration is missing or connection fails.
- Browser flow to scan, configure, save, and retry an existing network.
- Safe handling of invalid credentials and configuration reset.
### Deliverables
- Persistent configuration component.
- Network manager and provisioning state machine.
- Provisioning HTTP interface.
- Automated configuration tests and on-device recovery procedure.
### Acceptance criteria
1. First boot exposes the fallback provisioning interface.
2. Valid credentials are stored in NVS and used after reboot.
3. Failed station connection returns to a usable fallback access point.
4. Invalid requests cannot corrupt stored configuration.
5. Network reconfiguration cannot leave an active game silently running.
### Evidence
- On 2026-09-03, `./scripts/run_host_tests.sh` reported
`health state tests: PASS`, `wifi configuration tests: PASS`,
`configuration NVS tests: PASS`, `provisioning protocol tests: PASS`, and
`web asset reproducibility: PASS
(b36a6203a78964a324e3d56986a99abb7e36a48a84688cb4ecfe4ac1934b9f92)`.
The tests exercise credential length and control-byte bounds, invalid-input
non-mutation, mandatory reconfiguration guards, real store code across an
NVS reinitialization, schema mismatch, reset, strict two-field JSON parsing,
and malformed or duplicated request fields.
- After a clean on 2026-09-03,
`/home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1` completed
with `[SUCCESS]` in 46.25 seconds. PlatformIO reported 37,452 bytes of RAM
and 985,280 of 2,097,152 application bytes in use; the independent size hook
reported `firmware.bin uses 985920/2097152 bytes in partition factory`.
- `/home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target
buildfs` completed with `[SUCCESS]` and reported
`littlefs.bin uses 2031616/2031616 bytes in partition littlefs`. The image
contains deterministic compressed application and provisioning pages; its
SHA-256 was
`f3e529542737221d46146f46ff57eb3a88a1b3c5b25c9f4298b9d3e3e22a7d3a`.
- The application and filesystem images were written to the physical
ESP32-C6FH4 and hash-verified. A production first boot with empty
configuration reported `App version: 0.3.0`,
`No usable saved station configuration; enabling fallback`,
`Fallback access point ready: SSID=maze32-F7B9,
URL=http://192.168.4.1/provision`, DHCP at `192.168.4.1`,
`Provisioning endpoints ready`, and `Health state: serving`.
- The isolated `milestone-003-device-test` environment exercised the real NVS
and network manager without accessing local Wi-Fi secrets. One continuous
target log reported `credentials saved; restarting`, reset reason `SW_CPU`,
`credentials survived restart`, station connection to the persisted test
SSID with three bounded retries, `Station connection timed out or exhausted
retries; enabling fallback`, and `failed station returned to fallback;
credentials cleared`. Normal production firmware was restored afterward and
its boot log confirmed the test credentials were absent.
- On 2026-09-03, the project owner used the device-hosted provisioning page
from a separate client to save credentials for `Mazda7`; no credential was
exposed in the test record. A subsequent physical-board reboot loaded that
persisted SSID, associated using WPA2, received `192.168.1.50`, reported
`Network state: station_connected` and `Station connected:
IP=192.168.1.50`, registered the HTTP and provisioning routes, and reached
`Health state: serving`.
- Live requests over `Mazda7` returned
`{"state":"station_connected",...,"ip":"192.168.1.50"}` from
`/api/wifi/status`, a healthy version `0.3.0` response from `/health`, and
the decompressed Russian provisioning page from `/provision`. A deliberately
invalid two-field configuration request returned HTTP 400. A final board
reboot again loaded and connected to `Mazda7`, proving the rejected request
did not alter the persisted valid configuration.
- All five acceptance criteria therefore have recorded evidence.
## Milestone 004 — HTTP, WebSocket, sessions, and lobby
**Status:** `COMPLETE`
### Objective
Provide the bounded network and session layer required for two players, four
observers, and an owner-controlled lobby.
### Scope
- HTTP application delivery and diagnostic endpoint.
- Versioned WebSocket envelope, parser, validation, and bounded queues.
- Temporary session-token creation and browser refresh restoration.
- Unique player names and humorous name suggestions.
- Two player slots, four observer slots, and Player 1 start authority.
- Lobby snapshots, readiness, and the authoritative `3-2-1` countdown.
### Deliverables
- HTTP and WebSocket gateway components.
- Session and lobby services.
- Protocol schemas and protocol tests.
- Minimal browser lobby UI and non-browser protocol test client.
### Acceptance criteria
1. Two players and four observers can connect concurrently within fixed limits.
2. Duplicate player names and excess role claims are rejected safely.
3. Page refresh restores the same session and player slot.
4. Only Player 1 can start, and only with both player slots occupied.
5. Malformed, oversized, unauthorized, and stale messages do not mutate state.
6. Both players receive one authoritative countdown and activation instant.
### Evidence
- On 2026-09-04, `./scripts/run_host_tests.sh` reported
`health state tests: PASS`, `wifi configuration tests: PASS`,
`configuration NVS tests: PASS`, `provisioning protocol tests: PASS`,
`lobby and protocol tests: PASS`, and `web asset reproducibility: PASS
(6bdc7d380994cd302019c8634570953881cda035757d577fe2b1f54742a95f33)`.
The deterministic lobby tests cover the two-player and four-observer bounds,
duplicate-name and excess-role rejection, Player 2 start rejection, Player 1
readiness enforcement, restoration to the original slot, and the shared
countdown activation instant. Protocol tests cover valid envelopes plus
malformed, oversized, duplicate-field, unsupported-version, unknown-type,
invalid-payload, and stale-sequence handling without state mutation.
- A clean production build followed by
`/home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target
upload --upload-port /dev/ttyACM0` completed with `[SUCCESS]` in 50.31
seconds. PlatformIO reported 47,508 bytes of RAM and 1,005,274 of 2,097,152
application bytes in use; the independent partition check reported
`firmware.bin uses 1005904/2097152 bytes in partition factory`. The upload
identified the physical target as an ESP32-C6FH4 with 4 MB embedded Flash,
wrote the bootloader, partition table, and application, and hash-verified all
three images.
- `/home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target
buildfs` completed with `[SUCCESS]` and reported
`littlefs.bin uses 2031616/2031616 bytes in partition littlefs`. The two
deterministic compressed browser assets total 5,970 bytes, below the 1.5 MiB
web-payload limit and within the unchanged 1,984 KiB LittleFS partition.
- The final firmware booted through the bounded station retry policy and served
its fallback network while the configured `Mazda7` access point was
unavailable. A live `GET /health` returned
`{"status":"serving","healthy":true,"version":"0.4.0","errorCode":0}`.
The host retained its independent Ethernet route while its Wi-Fi interface
joined the device access point, so device testing did not interrupt the
development connection.
- On the physical board,
`python3 scripts/ws_protocol_client.py 192.168.4.1 --verify` reported
`malformed and stale message rejection: PASS`,
`six-client capacity: PASS (2 players + 4 observers)`,
`duplicate player name: PASS`, `seventh connection rejection: PASS`,
`Player 2 start authorization: PASS`,
`session refresh restoration: PASS (Player 2 retained slot 2)`,
`authoritative countdown: PASS (activationAtMs=72223)`, and
`oversized message rejection: PASS`. The countdown payload received by both
player connections was byte-for-byte equivalent, and both subsequent active
events carried the same server activation timestamp.
- During a six-client physical run, the gateway logged all six bounded
admissions and `Six-client heap: free=305388 bytes, largest=278528 bytes`;
it rejected a seventh connection and a 513-byte frame. Session tokens were
returned only in private session messages and were absent from shared lobby
snapshots. The observer protocol exposes no mutating command, while start
authorization is resolved from the server-owned session and player slot.
- These results provide concrete host and physical-device evidence for all six
acceptance criteria. Milestone 005 remains `NOT_STARTED`.
## Milestone 005 — Symmetric maze generation and validation
**Status:** `NOT_STARTED`
### Objective
Generate connected, cyclic, reproducible, 180-degree symmetric mazes with fair
object placement and bounded memory use.
### Scope
- Compact configurable maze representation.
- Seeded generation for the default `128 x 64` map.
- Cycles, alternative paths, and multiple cross-half passages.
- Symmetric starts, keys, exits, compass cells, landmarks, and vision artifacts.
- Reachability, symmetry, collision, and fairness validation.
- Bounded regeneration when a candidate fails validation.
### Deliverables
- Portable maze generator and validator.
- Deterministic host-side test suite over a large seed set.
- Diagnostic generation metrics and failure reports.
### Acceptance criteria
1. The same configuration and seed always produce the same valid maze.
2. Every tested map is fully reachable and rotationally symmetric.
3. Every tested map contains cycles and multiple cross-half connections.
4. Player-relative starts and required objects have equal symmetric metrics.
5. Keys are outside their owners' initial views.
6. Default generation fits the agreed RAM and runtime budgets without per-cell
heap allocation.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes deterministic seed-test results, validator
statistics, memory measurements, and representative generated maps.
## Milestone 006 — Authoritative movement and visibility core
**Status:** `NOT_STARTED`
### Objective
Implement deterministic player movement, command ordering, cooldowns, and
server-enforced role-specific visibility.
### Scope
- Serial authoritative command queue and sequence numbers.
- Orthogonal one-cell movement and wall rejection.
- Independent player actions with configurable server cooldown.
- Shared-cell occupancy and meeting detection.
- Chebyshev-radius visibility with walls that do not occlude.
- Player-specific projections and complete observer projections.
### Deliverables
- Portable game-state and movement engine.
- View projector with fog-of-war security tests.
- Movement, cooldown, ordering, collision, and visibility tests.
### Acceptance criteria
1. Accepted inputs move exactly one valid orthogonal cell.
2. Invalid, premature, or rate-limited commands do not mutate state.
3. Both players may occupy the same cell and generate one meeting event.
4. Player payloads contain no hidden cells, objects, or stale opponent state.
5. Observer payloads contain the complete current state.
6. Radius-three and radius-six projections match the documented formula at
walls and map boundaries.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes host-test output, serialized payload
inspection, and deterministic command-order tests.
## Milestone 007 — Keys, artifacts, compasses, exits, and results
**Status:** `NOT_STARTED`
### Objective
Complete the authoritative gameplay mechanics and terminal match outcomes.
### Scope
- One-slot key inventory, pickup, voluntary drop, and sabotage.
- Automatic return of keys to their owners when players meet.
- Owner-only key and exit restrictions.
- One-use vision artifacts lasting ten successful moves.
- Stationary compass activation and exit-direction hints.
- Exit opening, outward victory move, 200 ms draw window, and result state.
### Deliverables
- Gameplay object and result systems.
- Deterministic edge-case and simultaneous-event tests.
- Role-specific events for inventory, hints, effects, and results.
### Acceptance criteria
1. Inventory and ground-key state never duplicate or lose a key.
2. Meeting behavior returns or swaps carried keys atomically.
3. A player cannot use the opponent's key or exit to win.
4. Vision effects last exactly ten successful moves and ignore failed moves.
5. Compass activation points toward only the activating player's own exit.
6. Victory requires the outward move, and exits within 200 ms produce a draw.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes complete mechanic tests and timestamped
result-window tests.
## Milestone 008 — Player browser experience
**Status:** `NOT_STARTED`
### Objective
Deliver the complete responsive player interface without moving game authority
into the browser.
### Scope
- Name selection, lobby, countdown, running, paused, and result screens.
- Dark, humorous retro arcade presentation following `docs/UI_STYLE.md`.
- Russian player-facing copy and locally served pixel-styled graphics.
- Maze viewport and visual landmarks.
- Keyboard movement, touchscreen swipes, and responsive on-screen arcade
controls.
- Accessible drop-key action.
- Inventory, vision duration, compass hint, connection, and error feedback.
- Default sound, supported-device vibration, and animated game feedback.
- Session restoration after page refresh.
### Deliverables
- Responsive browser application and compressed production assets.
- Implemented visual tokens, SVG icon set, and shared control styles.
- Browser interaction tests for desktop and mobile input.
- Accessibility and viewport behavior checks.
### Acceptance criteria
1. Keyboard and swipe actions produce equivalent server commands.
2. The client renders only state received in the player projection.
3. Hidden and previously seen cells are not retained on screen.
4. Inventory, effects, hints, pause, and results are unambiguous.
5. Refresh restores the active player without changing position or inventory.
6. The player flow remains usable without page scrolling at a `412 x 916`
CSS-pixel viewport and at representative tablet and desktop viewports.
7. Player-facing UI copy and browser errors are in Russian while protocol and
system-log text remain in English.
8. The application requires no runtime internet access or third-party UI
dependency.
9. The complete compressed web payload is no larger than 1.5 MiB and fits the
unchanged LittleFS partition.
10. The current stable Chrome, Safari, Firefox, and Edge releases pass the
applicable browser interaction checks, with versions and test date
recorded in the milestone evidence.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes browser-test output, desktop/mobile visual
checks, refresh recovery results, and filesystem image size.
## Milestone 009 — Observer mode and disconnect recovery
**Status:** `NOT_STARTED`
### Objective
Complete the read-only full-map observer experience and reliable player pause
and reconnect behavior.
### Scope
- Full-map observer rendering with player and object updates.
- Large-screen observer layout with initial full-map fit, zoom, and pan.
- Observer access without a password and strict read-only authorization.
- Player disconnect detection and authoritative pause.
- Session reattachment and 60-second monotonic deadline.
- Timeout draw and observer-independent match continuity.
### Deliverables
- Observer browser mode.
- Pause/reconnect state-machine integration.
- Authorization, reconnect, refresh, and timeout tests.
### Acceptance criteria
1. Four observers can view the complete live state without control authority.
2. Observer disconnects do not pause or mutate a match.
3. Either player disconnect immediately pauses gameplay and effect progression.
4. Reconnection within 60 seconds restores and resumes the same state.
5. Reconnection timeout ends the match in a draw.
6. Observer attempts to send mutation commands are rejected and audited.
7. Observer mode works at `1024 x 768` CSS pixels and larger, while smaller
viewports show the required Russian large-screen message.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes role-authorization tests, four-observer
browser evidence, and timed reconnect/timeout scenarios.
## Milestone 010 — On-device integration and resource hardening
**Status:** `NOT_STARTED`
### Objective
Demonstrate that the integrated system remains correct and responsive within
the ESP32-C6 Flash, RAM, socket, and network limits.
### Scope
- Full firmware and LittleFS production build.
- Two-player plus four-observer load testing.
- Heap, largest-block, socket, queue, latency, and disconnect measurements.
- Slow-client backpressure and malformed-message stress.
- Station and fallback-access-point integration tests.
- Long-running match and repeated-match stability.
### Deliverables
- On-device integration test procedure and results.
- Resource budget report.
- Fixed limits and defensive failure behavior.
### Acceptance criteria
1. Application and filesystem images fit their partitions with recorded margin.
2. Six simultaneous clients remain connected and responsive on target hardware.
3. Slow or malformed clients cannot exhaust memory or block player processing.
4. Heap and largest free block remain stable across repeated matches.
5. Station reconnect, provisioning fallback, and browser recovery work on the
physical device.
6. No test relies on PSRAM or an unverified GPIO.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes production build reports, physical-device
logs, six-client load results, memory graphs or samples, and repeated-match
stress results.
## Milestone 011 — Gameplay tuning and MVP acceptance
**Status:** `NOT_STARTED`
### Objective
Tune the game to its target experience and demonstrate every MVP acceptance
criterion on the release candidate.
### Scope
- Tune movement cooldown, maze balance thresholds, landmarks, artifact density,
and compass placement.
- Measure key-search and exit-search difficulty.
- Run representative human playtests targeting approximately five minutes.
- Execute the complete MVP acceptance suite and document known limitations.
- Produce the reproducible release image and matching web filesystem image.
### Deliverables
- Locked MVP gameplay configuration.
- Playtest and balance report.
- MVP acceptance report mapped to `MVP.md`.
- Release build artifacts and version record.
### Acceptance criteria
1. Key discovery is demonstrably no easier than the subsequent exit search
under the agreed metrics and playtest evidence.
2. Representative completed matches normally target approximately five minutes
without a hard match timer.
3. Every acceptance criterion in `MVP.md` has recorded passing evidence or an
explicitly approved deviation.
4. The final firmware and web images build reproducibly and fit the target.
5. No unresolved defect prevents the two-player or observer MVP flows.
### Evidence
Completion evidence is not yet available because this milestone has not
started. Required evidence includes playtest data, the mapped acceptance report,
final build hashes and sizes, and project-owner approval of any deviations.