mirror of
https://github.com/ruvnet/RuView
synced 2026-06-09 10:13:17 +00:00
dc7f6cd096
Closes #391 (full-replace footgun). Phase 1 of #574 (esp32-csi-node provisioning UX). The mDNS discovery + USB-CDC pairing work in #574 remains future work; this PR handles only the provision.py-side fix. Background: provision.py flashed a fresh NVS partition at 0x9000 every invocation. The previous behaviour built that partition only from the CLI flags passed on the current run — every key you didn't pass was silently erased. We hit it ourselves earlier today: --force-partial only suppressed the safety check but still wiped the SSID. This PR replaces the full-replace semantic with a per-port state file that captures every config value previously flashed from this machine. On each invocation: 1. Read ~/.config/wifi-densepose/esp32-provision-state/<port>.json (or %APPDATA%/... on Windows). 2. Overlay the new CLI flags on top — CLI wins where set. 3. Generate + flash NVS from the merged dict. 4. Persist the merged dict back to the state file. Net effect: the exact scenario from #391 + today's incident now passes (test_partial_invocation_does_not_drop_unrelated_keys): python provision.py --port COM7 --ssid Net --password p --target-ip 10.0.0.5 # later: python provision.py --port COM7 --seed-url http://10.0.0.99:8080 # WiFi creds preserved, seed_url added. New flags: --reset Wipe per-port state before merging (recycled-board path). --state-dir Override per-user state dir (XDG / %APPDATA% by default). --state Print the merged state and exit (debug / inspection). --force-partial preserved as a deprecation-flagged escape hatch. State file caveats (in the module docstring): per-machine, atomic write via .tmp + os.replace, future follow-up to add USB-CDC NVS dump for device-authoritative merging is tracked in #574. Tests: tests/test_provision_state.py — 11 tests covering load/save round-trip, corrupt-JSON resilience, CLI-wins-over-prior, the exact #391 case, falsy-but-not-None CLI override (node_id=0 must survive), and serial-port path sanitization for /dev/ttyUSB0. 11/11 pass. Live-tested end-to-end with --dry-run + --state inspection: first run: ssid + password + target_ip persisted second run: --seed-url added — WiFi creds intact in final state.