Skip to content

test(sensing-server): cover room-builder config validation + persistence - #1822

Open
clonea1 wants to merge 3 commits into
ruvnet:mainfrom
clonea1:contrib/ui-room-builder
Open

test(sensing-server): cover room-builder config validation + persistence#1822
clonea1 wants to merge 3 commits into
ruvnet:mainfrom
clonea1:contrib/ui-room-builder

Conversation

@clonea1

@clonea1 clonea1 commented Sep 4, 2026

Copy link
Copy Markdown

Extracted POST /api/v1/config/room's validation into a pure
validate_room_config(&RoomConfig) -> Result<(), String> function so it's
unit-testable without a full SharedState/axum harness; behavior
unchanged, the handler just delegates to it now.

9 new tests: load-missing/malformed-file defaults, save+load round trip,
and validation for non-positive/non-finite dimensions, non-finite node
coordinates, duplicate node ids, and an empty node list.

Also adds a "Reload from Saved" button to the Room Builder UI (discards
unsaved local edits, re-fetches the live server config).


Rebased onto current main before opening: staged before today's seven merges, so it needed replaying to avoid reading as a revert of them. Clean rebase, no files deleted.

Joe and others added 3 commits September 4, 2026 15:02
New tab (index.html nav + section, wired in app.js following the same
container-lookup + component pattern as the other tabs) backed by
GET/POST /api/v1/config/room. A 2D top-down canvas: set room width/
depth, add/remove sensor nodes, drag them into place or type exact
X/Y/Z, save. Save applies immediately (live, no restart) and persists
to room_config.json, which future launches load automatically -
replacing the --node-positions CLI-only workflow.

Metric/imperial unit toggle (display-only - this.config and everything
sent to the API always stay in meters, remembered per-browser via
localStorage). Compass badge + explanatory text establishing (0,0,0)
as the room's Northwest corner, +X = East, +Y = South, so placements
can be oriented to the real room.

Rows are matched to their node by array index rather than by id -
id is itself one of the editable fields, and using it as the lookup
key meant renaming a node into an id already in use broke the row<->
node link (two rows silently reading/writing the same node object,
which looked like one node jumping onto or stacking with another).
Duplicate ids are now also caught client-side (warned while editing,
hard-blocked on save) ahead of the server's own validation, and a
server-side validation rejection (200 OK with an {"error": ...} body,
not a failure status) is now checked for explicitly rather than
silently treated as a successful save.

Co-Authored-By: claude-flow <ruv@ruv.net>
(cherry picked from commit 4cc202a)
Extracted POST /api/v1/config/room's validation into a pure
validate_room_config(&RoomConfig) -> Result<(), String> function so it's
unit-testable without a full SharedState/axum harness; behavior
unchanged, the handler just delegates to it now.

9 new tests: load-missing/malformed-file defaults, save+load round trip,
and validation for non-positive/non-finite dimensions, non-finite node
coordinates, duplicate node ids, and an empty node list.

Also adds a "Reload from Saved" button to the Room Builder UI (discards
unsaved local edits, re-fetches the live server config).

Co-Authored-By: claude-flow <ruv@ruv.net>
(cherry picked from commit a3b9907)
…al Vec

ruvnet#1791 landed with `node_positions_config` as a positional `Vec<[f32; 3]>`
keyed by active-node rank, not the `HashMap<u8, [f32; 3]>` this branch was
written against. The Room Builder handlers therefore no longer compiled:
`.map(|(&id, p)| ...)` over a Vec, and `.insert(id, ..)` on one.

Read path now enumerates and derives the id from the index, matching the
convention the fusion path actually uses. That consistency is the point: the
Room Builder exists to show where the server thinks the nodes are, so if it
described a different binding than fusion applies, it would be worse than
showing nothing.

Write path builds the vector indexed BY node id before assigning, so a sparse
or non-contiguous set of ids still lands each node in the right slot and gaps
stay at the origin. Pushing in iteration order instead would silently shift
every node after a gap.

270 server tests pass.

Co-Authored-By: claude-flow <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant