47 KiB
maze32 Implementation Plan
Plan rules
- Milestones may be planned and added in batches.
- Milestone numbering starts at 1 and increases without gaps. Headings use the
zero-padded form
Milestone 001,Milestone 002, and so on. - Milestones are executed strictly in ascending numerical order. Work on a
milestone may begin only after every preceding milestone is
COMPLETE. - At most one milestone may have status
IN_PROGRESS. - 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.
- Every milestone contains an objective, scope, deliverables, acceptance criteria, evidence, and status.
- Allowed statuses are
NOT_STARTED,IN_PROGRESS,BLOCKED, andCOMPLETE. - A milestone may be marked
COMPLETEonly when every acceptance criterion is satisfied and concrete evidence is recorded in the milestone. - 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.
- A
NOT_STARTEDmilestone explicitly records that completion evidence is not yet available. Expected evidence may be listed in advance. - If later work invalidates recorded evidence, reopen the affected milestone and change its status before continuing.
- 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.mdARCHITECTURE.mdPLANS.mdAGENTS.mddocs/BOARD_PASSPORT.mdplatformio.inipartitions.csvsdkconfig.defaults
Acceptance criteria
- All canonical project documentation is in English.
MVP.mdcaptures all agreed roles, gameplay rules, networking behavior, technical constraints, exclusions, and acceptance criteria.ARCHITECTURE.mddefines server authority, component boundaries, state machines, role-specific projection, protocol direction, storage, and verification strategy.- The build profile pins PlatformIO
espressif32@7.0.1, ESP-IDF, the compatibleesp32-c6-devkitm-1profile, and 4 MB Flash. - The partition layout is contiguous and ends exactly at
0x400000. sdkconfig.defaultsexplicitly selects 4 MB Flash and 16 LwIP sockets.- The board passport matches the canonical configuration and does not claim an unverified physical board model, GPIO mapping, LED, or PSRAM.
- No file under
sources/is modified. - PlatformIO can parse and resolve the canonical project configuration.
Evidence
MVP.mdcontains the complete English product and acceptance specification.ARCHITECTURE.mdcontains the English runtime, component, state-machine, protocol, memory, failure, and verification contracts.- On 2026-09-03,
/home/sasa/.platformio/penv/bin/pio project configexited successfully and resolved environmentesp32-c6-devkitm-1withespressif32@7.0.1, ESP-IDF, explicit 4 MB build/upload sizes,partitions.csv, LittleFS, andsdkconfig.defaults. PlatformIO subsequently emitted a telemetry-cache permission warning during process shutdown; it did not prevent configuration parsing. - On 2026-09-03, an
awkcontinuity and end-address check overpartitions.csvreported the factory partition ending at0x210000, the LittleFS partition ending at0x400000, and no gaps or overlaps from NVS through the end of Flash. - On 2026-09-03,
rgconfirmedCONFIG_ESPTOOLPY_FLASHSIZE_4MB=yandCONFIG_LWIP_MAX_SOCKETS=16in bothsdkconfig.defaultsand the generated ESP-IDF configuration. docs/BOARD_PASSPORT.mdrecords 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 undersources/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
- A clean PlatformIO build succeeds with the locked environment.
- The application image fits the 2 MiB factory partition.
- The LittleFS image fits the 1,984 KiB filesystem partition.
- Web-asset generation is deterministic and does not require manual edits.
- 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 configparsed the updated configuration successfully with the locked platform, ESP-IDF, 4 MB Flash, root partition table, LittleFS, pinnedesp_littlefs, bounded LittleFS settings, and the build hook. - On 2026-09-03,
./scripts/run_host_tests.shreportedhealth state tests: PASSandweb asset reproducibility: PASS (611eacdb06b81bdb064a9074352ff4c6f82d3af3ad3d01e65705387744b86b21). - After
/home/sasa/.platformio/penv/bin/pio run --target clean, running/home/sasa/.platformio/penv/bin/pio runon 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 reportedfirmware.bin uses 350864/2097152 bytes in partition factory. - Running
/home/sasa/.platformio/penv/bin/pio run --target buildfson 2026-09-03 regenerateddata/index.html.gz, built the LittleFS image, and reported[SUCCESS]. The independent build hook reportedlittlefs.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 remained950c60077c381d4484c11b43762bc5c8378587b6cd91924c344cfbc406771bb9. 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.binfound firmware version0.2.0and 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/ttyACM0wrote and hash-verified the 2,031,616-byte LittleFS image at0x210000. A subsequent application upload identified the target asESP32-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, andHealth 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
- First boot exposes the fallback provisioning interface.
- Valid credentials are stored in NVS and used after reboot.
- Failed station connection returns to a usable fallback access point.
- Invalid requests cannot corrupt stored configuration.
- Network reconfiguration cannot leave an active game silently running.
Evidence
- On 2026-09-03,
./scripts/run_host_tests.shreportedhealth state tests: PASS,wifi configuration tests: PASS,configuration NVS tests: PASS,provisioning protocol tests: PASS, andweb 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-1completed 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 reportedfirmware.bin uses 985920/2097152 bytes in partition factory. /home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target buildfscompleted with[SUCCESS]and reportedlittlefs.bin uses 2031616/2031616 bytes in partition littlefs. The image contains deterministic compressed application and provisioning pages; its SHA-256 wasf3e529542737221d46146f46ff57eb3a88a1b3c5b25c9f4298b9d3e3e22a7d3a.- 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 at192.168.4.1,Provisioning endpoints ready, andHealth state: serving. - The isolated
milestone-003-device-testenvironment exercised the real NVS and network manager without accessing local Wi-Fi secrets. One continuous target log reportedcredentials saved; restarting, reset reasonSW_CPU,credentials survived restart, station connection to the persisted test SSID with three bounded retries,Station connection timed out or exhausted retries; enabling fallback, andfailed 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, received192.168.1.50, reportedNetwork state: station_connectedandStation connected: IP=192.168.1.50, registered the HTTP and provisioning routes, and reachedHealth state: serving. - Live requests over
Mazda7returned{"state":"station_connected",...,"ip":"192.168.1.50"}from/api/wifi/status, a healthy version0.3.0response 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 toMazda7, 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-1countdown.
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
- Two players and four observers can connect concurrently within fixed limits.
- Duplicate player names and excess role claims are rejected safely.
- Page refresh restores the same session and player slot.
- Only Player 1 can start, and only with both player slots occupied.
- Malformed, oversized, unauthorized, and stale messages do not mutate state.
- Both players receive one authoritative countdown and activation instant.
Evidence
- On 2026-09-04,
./scripts/run_host_tests.shreportedhealth state tests: PASS,wifi configuration tests: PASS,configuration NVS tests: PASS,provisioning protocol tests: PASS,lobby and protocol tests: PASS, andweb 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/ttyACM0completed 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 reportedfirmware.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 buildfscompleted with[SUCCESS]and reportedlittlefs.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
Mazda7access point was unavailable. A liveGET /healthreturned{"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 --verifyreportedmalformed 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), andoversized 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 — Symmetric maze generation and validation
Status: COMPLETE
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 64map. - 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
- The same configuration and seed always produce the same valid maze.
- Every tested map is fully reachable and rotationally symmetric.
- Every tested map contains cycles and multiple cross-half connections.
- Player-relative starts and required objects have equal symmetric metrics.
- Keys are outside their owners' initial views.
- Default generation fits the agreed RAM and runtime budgets without per-cell heap allocation.
Evidence
- On 2026-09-04,
/home/sasa/.platformio/penv/bin/pio project configexited successfully and resolved the production, Milestone 003 device-test, and isolatedmilestone-005-device-testenvironments from the lockedespressif32@7.0.1, ESP-IDF, 4 MB Flash, root partition, and root sdkconfig baseline. - On 2026-09-04,
./scripts/run_host_tests.shreported all preceding tests asPASS,maze bounded regeneration failure: PASS (3/3 attempts), andmaze seed sweep: PASS (1024 seeds, combined hash=a264b7d133f8bad4). Generating every default128 x 64seed twice produced identical hashes and valid results. All 1,024 maps contained 8,192 reachable cells, exactly 133 cycles, six cross-half connections, 704–854 dead ends, and symmetric object and route metrics. Start-to-key distances were 416–1,442, key-to-exit distances were 346–1,244, and start-to-exit distances were 102–992; every tested candidate succeeded on its first bounded attempt and key-search route distance was never shorter than the following exit-search route distance. - The same host suite reported a maximum 5.127 ms generation time and
maze fixed memory: PASS (42332/65536 bytes, no heap API). The portable component uses one byte of passage flags per cell plus fixed bit-set, traversal, distance, and placement arrays. A separate build with-fsanitize=address,undefinedandASAN_OPTIONS=detect_leaks=0repeated the 1,024-seed suite without an address or undefined-behavior finding; leak detection was disabled because the sandbox executes underptrace. - Validator corruption tests independently rejected a broken reciprocal or rotational passage and a colliding key placement. The sweep also verified boundary starts and exits, keys outside each owner's Chebyshev-radius-three initial view, corresponding distances for keys, exits, compasses, all eight landmark pairs, and all four vision-artifact pairs. The forced impossible candidate stopped after the configured three attempts and returned a diagnostic failure instead of retrying indefinitely.
- The deterministic small-map diagnostic reported representative map hash
7396c6426181da3eand printed a complete16 x 8ASCII maze with walls, opposite starts, symmetric keys and exits, compasses, landmarks, and four vision artifacts.docs/MAZE_GENERATION.mdrecords the construction, validation, configuration, reproducibility, and resource contracts. /home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1completed with[SUCCESS]. PlatformIO reported 47,508 of 327,680 RAM bytes and 1,005,274 of 2,097,152 application bytes in use; the production upload's independent partition check reportedfirmware.bin uses 1005904/2097152 bytes in partition factory./home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target buildfsalso completed with[SUCCESS]and reportedlittlefs.bin uses 2031616/2031616 bytes in partition littlefs.- The isolated physical-board image was built and hash-verified with
/home/sasa/.platformio/penv/bin/pio run -e milestone-005-device-test --target upload --upload-port /dev/ttyACM0. The upload identified the target as an ESP32-C6FH4 with 4 MB embedded Flash. On target, requested seed1513226245generated in one attempt with hash485280a746e8900cand loggedcells=8192, reachable=8192, edges=8324, cycles=133, crossings=6, dead_ends=778, branches=1024. Paired route metrics were equal:start_key=804/804,key_exit=773/773,start_exit=191/191,compass=223/223,landmarks=3099/3099, andartifacts=1085/1085. - The same physical run logged
fixed=42332/65536 bytes, runtime=183/250 ms, heap_delta=0followed byM005 physical maze test: PASS. Production firmware was restored and hash-verified afterward; a liveGET /healthover the configured station network returned{"status":"serving","healthy":true,"version":"0.5.0","errorCode":0}. - These deterministic, validator, resource, representative-map, build, and physical-board results provide concrete evidence for all six acceptance criteria and completed Milestone 005.
Milestone 006 — Authoritative movement and visibility core
Status: COMPLETE
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
- Accepted inputs move exactly one valid orthogonal cell.
- Invalid, premature, or rate-limited commands do not mutate state.
- Both players may occupy the same cell and generate one meeting event.
- Player payloads contain no hidden cells, objects, or stale opponent state.
- Observer payloads contain the complete current state.
- Radius-three and radius-six projections match the documented formula at walls and map boundaries.
Evidence
- On 2026-09-04,
PLATFORMIO_SETTING_ENABLE_TELEMETRY=no /home/sasa/.platformio/penv/bin/pio project configexited successfully and resolved the production and isolatedmilestone-006-device-testenvironments fromespressif32@7.0.1, ESP-IDF, theesp32-c6-devkitm-1profile, 4 MB Flash, and the root partition and sdkconfig files. ./scripts/run_host_tests.shpassed every preceding suite and reportedgame movement, cooldown, and FIFO ordering: PASS (commands 1-7, states 0-3),game bounded command queue: PASS (16 entries),game shared-cell meeting event: PASS (one event), andgame visibility and payload security: PASS (r3=49/16, r6=64/49, observer=64). The same suite serialized a complete default128 x 64observer snapshot as 345 chunks and reported a maximum chunk size of 405 bytes against the 512-byte limit. A separate build with-fsanitize=address,undefinedrepeated the game-core suite without an address or undefined-behavior finding; leak detection was disabled because the sandbox executes underptrace.- The deterministic movement cases proved that queued commands are processed in assigned FIFO order, each accepted direction changes exactly one coordinate by one cell, and Player 1 and Player 2 may act at the same server timestamp. Countdown, cooldown, out-of-order timestamp, closed-wall, malformed-direction, observer, and full-queue rejections left player state, accepted-move counters, cooldown clocks, and the authoritative state sequence unchanged. Entering the other player's occupied cell left both players there and emitted one meeting event.
- Projection tests covered both player roles and reused a snapshot after an
opponent changed from visible to hidden. Radius-three squares contained 49
cells at an interior position and 16 at a corner; radius-six squares
contained 64 and 49 respectively on the
8 x 8fixture. An internal wall did not remove cells. Player structures and every serialized 512-byte-bounded JSON chunk omitted hidden cell 63, its hidden key record, and stale opponent state, while the observer contained all 64 cells, all ten fixture objects, and both player positions. The serializer also emitted the versioned envelope, authoritative sequence, phase, meeting sequence, and chunk metadata. /home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1completed with[SUCCESS]and reported 47,508 of 327,680 RAM bytes and 1,005,274 of 2,097,152 application bytes in use. The productionfirmware.binmeasured 1,005,904 bytes against the 2,097,152-byte factory partition./home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target buildfscompleted with[SUCCESS]; the independent partition check reportedlittlefs.bin uses 2031616/2031616 bytes in partition littlefs.- The isolated device image built with
[SUCCESS], using 124,468 of 327,680 RAM bytes and 1,016,242 of 2,097,152 application bytes. Its independent partition check reportedfirmware.bin uses 1016880/2097152 bytes in partition factory. Upload with/home/sasa/.platformio/penv/bin/pio run -e milestone-006-device-test --target upload --upload-port /dev/ttyACM0identified an ESP32-C6FH4 revision 0.2 with 4 MB embedded Flash and hash-verified every written image. - The physical board logged an accepted command with command sequence one,
state sequence one, and the new position. It projected 28 player cells into
two bounded chunks and the complete 8,192-cell, 30-object observer state into
345 bounded chunks; the first serialized chunk was 372 bytes. It then logged
fixed=34612/40960 bytes, runtime=5/50 ms, heap_delta=0andM006 physical game test: PASS. - The production image was restored and hash-verified after the isolated test.
A live
GET /healthreturned{"status":"serving","healthy":true,"version":"0.6.0","errorCode":0}. These host, serialization, build, resource, and physical-board results provide concrete evidence for all six acceptance criteria and complete Milestone 006.
Milestone 007 — Keys, artifacts, compasses, exits, and results
Status: COMPLETE
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
- Inventory and ground-key state never duplicate or lose a key.
- Meeting behavior returns or swaps carried keys atomically.
- A player cannot use the opponent's key or exit to win.
- Vision effects last exactly ten successful moves and ignore failed moves.
- Compass activation points toward only the activating player's own exit.
- Victory requires the outward move, and exits within 200 ms produce a draw.
Evidence
bash scripts/run_host_tests.shcompleted successfully. Its new deterministic mechanics suite reportedgame key inventory, drop, and sabotage: PASS,game atomic meeting key return: PASS (opponent keys swapped to owners),game owner-only exit opening and outward move: PASS,game one-use vision duration: PASS (10 successful moves, failed move ignored),game compass bearing and role-specific projections: PASS, andgame outward result window: PASS (200 ms draw boundary, 201 ms winner). All Milestone 001-006 host regressions and the reproducible web-asset check passed in the same run.- The key tests exercised pickup of both owner and opponent keys, one-slot rejection, opponent-key sabotage, deterministic pickup when both keys occupy one cell, voluntary drop, and rejected empty drop. They asserted after every transition that each key existed exactly once on the ground or in one inventory. A crossed-key meeting cleared both inventories and reassigned the keys to their owners in one state transition.
- Exit tests proved that the wrong key cannot open a player's own exit and that neither carrying the opponent's key nor standing at the opponent's exit permits opening or an outward move. Carrying the matching key opened only the owner's exit; a later outward boundary command was required to enter the finish window. Timestamped cases proved that the second outward move at exactly 200 ms produces a draw, while advancing time at 201 ms finalizes the first player as winner; the symmetric Player 2 winner case also passed.
- Artifact tests consumed an artifact once, selected the authoritative radius six, retained all ten moves after entry, ignored a failed move, and returned to radius three after exactly ten later successful moves. Compass tests produced the direct eight-way bearing to only the activating player's own exit, preserved it across a rejected command, and cleared it on the next successful move.
- Projection inspection covered both player roles and the observer. Player
snapshots contained only their own inventory, effect, compass hint, and exit
state; an opponent's carried key appeared only while that opponent was
visible and disappeared when hidden. Observer snapshots contained both
inventories, effects, hints, exit states and timestamps, all remaining
ground objects, and the result. The complete default
128 x 64observer snapshot serialized into 688 versioned chunks with a worst-case maximum of 471 bytes, below the 512-byte message bound. Independent AddressSanitizer and UndefinedBehaviorSanitizer runs of both game suites passed without findings; leak detection was disabled because the sandbox executes underptrace. PLATFORMIO_SETTING_ENABLE_TELEMETRY=no /home/sasa/.platformio/penv/bin/pio project configparsed the lockedespressif32@7.0.1, ESP-IDF,esp32-c6-devkitm-1,partitions.csv, andsdkconfig.defaultsconfiguration, including the isolatedmilestone-007-device-testenvironment./home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1completed with[SUCCESS], reporting 47,508 of 327,680 RAM bytes and 1,005,274 of 2,097,152 application bytes; the independent partition check reportedfirmware.bin uses 1005904/2097152 bytes in partition factory. The isolated device image also built with[SUCCESS], using 124,628 RAM bytes and 1,020,168 application bytes, withfirmware.bin uses 1020800/2097152 bytes in partition factory./home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1 --target buildfscompleted with[SUCCESS]; the partition check reportedlittlefs.bin uses 2031616/2031616 bytes in partition littlefs. The test image upload identified an ESP32-C6FH4 revision 0.2 with 4 MB embedded Flash and hash-verified each write. The board loggedM007 events: artifact=0, key=0, hint=8, opened=1, outward=1, result=1, sequence=6, player and complete observer projections,fixed=34776/40960 bytes, runtime=6/50 ms, heap_delta=0, andM007 physical mechanics test: PASS.- The normal firmware was restored and hash-verified after the isolated test.
A live
GET /healthreturned{"status":"serving","healthy":true,"version":"0.7.0","errorCode":0}. These deterministic, security-boundary, size, sanitizer, and physical-board results provide concrete evidence for all six acceptance criteria. Milestone 008 remainsNOT_STARTED.
Milestone 008 — Player browser experience
Status: COMPLETE
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
- Keyboard and swipe actions produce equivalent server commands.
- The client renders only state received in the player projection.
- Hidden and previously seen cells are not retained on screen.
- Inventory, effects, hints, pause, and results are unambiguous.
- Refresh restores the active player without changing position or inventory.
- The player flow remains usable without page scrolling at a
412 x 916CSS-pixel viewport and at representative tablet and desktop viewports. - Player-facing UI copy and browser errors are in Russian while protocol and system-log text remain in English.
- The application requires no runtime internet access or third-party UI dependency.
- The complete compressed web payload is no larger than 1.5 MiB and fits the unchanged LittleFS partition.
- 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
Implementation and required verification are complete.
bash scripts/run_host_tests.shcompleted successfully. The five focused browser tests reported keyboard/swipe direction equivalence, intention-only command envelopes, full replacement of chunked projections without explored-map memory, token-only refresh restoration, and local Russian, accessible, responsive assets. All Milestone 001-007 host regressions passed in the same run. The complete default observer projection remained bounded at 688 chunks with a worst-case maximum of 495 bytes against the 512-byte message limit. A separate AddressSanitizer and UndefinedBehaviorSanitizer run of the changed projection suite passed without findings; leak detection was disabled because the sandbox executes underptrace.python3 scripts/verify_web_assets.pyreportedweb asset reproducibility: PASSwith digestf321d5bb1b4ad8cfcdf306c5a5e696f3b2b00b54792c727fd639671e585b573dand a complete compressed payload of 17,100 of 1,572,864 allowed bytes. Source inspection and tests found no remote runtime URL, import, font, framework, analytics, or icon dependency.node --check web/player.jsandxmllint --noout web/icons.svgalso completed successfully.pio run -e esp32-c6-devkitm-1completed with[SUCCESS], reporting 47,508 of 327,680 RAM bytes and 1,005,660 of 2,097,152 application bytes. The independent partition check reportedfirmware.bin uses 1006288/2097152 bytes in partition factory.pio run -e esp32-c6-devkitm-1 --target buildfscompleted with[SUCCESS]; the independent partition check reportedlittlefs.bin uses 2031616/2031616 bytes in partition littlefs, with all five gzip assets present in the image.- Physical delivery passed after the board re-enumerated as
/dev/ttyACM0.pio run -e esp32-c6-devkitm-1 --target upload --upload-port /dev/ttyACM0and the correspondinguploadfscommand both completed with[SUCCESS]and hash-verified every write. The ESP32-C6FH4 revision 0.2 boot log reported application version0.8.0, the unchanged 4 MB partition table,LittleFS mounted: total=2031616 bytes, used=36864 bytes, and successful HTTP, WebSocket, and provisioning service startup. The saved station SSID remainedk49, so the device correctly entered itsmaze32-F7B9fallback AP while the host remained onMazda7; the host network was not changed. - A USB readback of the complete LittleFS partition used
/home/sasa/.platformio/penv/bin/python /home/sasa/.platformio/packages/tool-esptoolpy/esptool.py --chip esp32c6 --port /dev/ttyACM0 read_flash 0x210000 0x1f0000 /tmp/maze32-m008-littlefs-readback.bin. Both the built image and physical readback had SHA-256606b98e11cbc479bf11bffa9a38d62ddfebce0689f0e3ebf148521190a032fd5;cmpreturned zero, proving byte-for-byte delivery without interrupting the host's internet connection. - Automated live browser validation was unavailable because the browser-control
runtime returned
No browser is availableand its browser inventory was empty. The project owner subsequently supplied the required manual browser evidence recorded below. - On 2026-09-04, a fresh browser-control inventory check again returned an
empty list. Milestone 008 was therefore changed from
IN_PROGRESStoBLOCKED; no Milestone 009 implementation work was started. - On 2026-09-04, the project owner completed the required manual player-UI
checks in Chrome 152, Firefox 155, Safari 26.6, and Edge 152.0.4191.53. The
checks covered the
412 x 916phone layout without page scrolling, representative tablet and desktop layouts, keyboard and swipe movement, the accessible drop-key control, and refresh/session restoration. Together with the automated browser-contract, projection-security, localization, offline-asset, payload-size, build, and physical-device evidence above, this satisfies every Milestone 008 acceptance criterion. Milestone 008 isCOMPLETE; Milestone 009 remainsNOT_STARTED.
Milestone 009 — Observer mode and disconnect recovery
Status: IN_PROGRESS
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
- Four observers can view the complete live state without control authority.
- Observer disconnects do not pause or mutate a match.
- Either player disconnect immediately pauses gameplay and effect progression.
- Reconnection within 60 seconds restores and resumes the same state.
- Reconnection timeout ends the match in a draw.
- Observer attempts to send mutation commands are rejected and audited.
- Observer mode works at
1024 x 768CSS pixels and larger, while smaller viewports show the required Russian large-screen message.
Evidence
Implementation is complete, but the milestone remains IN_PROGRESS until the
required physical-device and observer-browser checks can be recorded.
- On 2026-09-05,
bash scripts/run_host_tests.shcompleted successfully. The new deterministic recovery suite proved immediate authoritative pause, rejection of commands without state or effect progression while paused, restoration before the monotonic 60,000 ms deadline, timeout draw at the deadline, late-reconnect rejection, and preservation of the remaining 200 ms finish window across a pause. Observer-role command enqueue returnedread_only, and observer connection changes left lobby phase unchanged. - The same host run reported
game default observer serialization: PASS (688 chunks, maximum 494 bytes). The projection contains all 8,192 cells, both player records and connection states, and remains below the 512-byte message bound. Seven browser-contract tests passed, covering authoritative chunk assembly, observer role rendering, absence of observer mutation controls, bounded fit/zoom/pan behavior, and the Russian sub-1024 x 768notice. Web asset reproducibility passed with SHA-256e8d097c7aa1a56cf84748078176b50cc8e2718082edfda35625b6d4436a1fd67and 19,133 of 1,572,864 allowed compressed bytes. - Separate AddressSanitizer and UndefinedBehaviorSanitizer runs of the changed
game-core and disconnect-recovery suites passed without findings; leak
detection was disabled because the sandbox executes under
ptrace.node --check web/player.js, compilation ofscripts/ws_protocol_client.py, andgit diff --checkalso passed. /home/sasa/.platformio/penv/bin/pio run -e esp32-c6-devkitm-1completed with[SUCCESS], reporting 124,148 of 327,680 RAM bytes and 1,023,742 of 2,097,152 application bytes. The independent partition check reportedfirmware.bin uses 1024368/2097152 bytes in partition factory. The correspondingbuildfscommand completed with[SUCCESS]and reportedlittlefs.bin uses 2031616/2031616 bytes in partition littlefs, with all five compressed assets present.- Physical verification remains outstanding. The prepared dependency-free
command
python3 scripts/ws_protocol_client.py 192.168.1.50 --verify-m009covers simultaneous full-state delivery to four observers, observer mutation rejection, observer-disconnect continuity, same-state player restoration, and the real 60-second timeout draw. At the end of this pass,/dev/ttyACM0was absent and192.168.1.50was unreachable, so the final0.9.0images could not be uploaded and this scenario could not be run. - Automated live observer validation also remains outstanding. The
browser-control runtime returned
No browser is available, and its browser inventory was empty. A live check at1024 x 768or larger plus a smaller viewport must still confirm full-map fit, updates, zoom, pan, read-only UI, player connection state, and the required Russian large-screen notice.
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
- Application and filesystem images fit their partitions with recorded margin.
- Six simultaneous clients remain connected and responsive on target hardware.
- Slow or malformed clients cannot exhaust memory or block player processing.
- Heap and largest free block remain stable across repeated matches.
- Station reconnect, provisioning fallback, and browser recovery work on the physical device.
- 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
- Key discovery is demonstrably no easier than the subsequent exit search under the agreed metrics and playtest evidence.
- Representative completed matches normally target approximately five minutes without a hard match timer.
- Every acceptance criterion in
MVP.mdhas recorded passing evidence or an explicitly approved deviation. - The final firmware and web images build reproducibly and fit the target.
- 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.