Skip to content

feat(ui): node tapper, built from whatever fleet the server reports - #1825

Open
clonea1 wants to merge 3 commits into
ruvnet:mainfrom
clonea1:contrib/ui-ground-truth-capture
Open

feat(ui): node tapper, built from whatever fleet the server reports#1825
clonea1 wants to merge 3 commits into
ruvnet:mainfrom
clonea1:contrib/ui-ground-truth-capture

Conversation

@clonea1

@clonea1 clonea1 commented Sep 4, 2026

Copy link
Copy Markdown

Adds the per-location tapper: stand near a node, tap its button, and the label
is stamped into the recording as it happens rather than recalled afterwards.

Built entirely from /api/v1/nodes at load. One button per node the server
actually knows about, sorted by id and labelled "Node 1", "Node 2" and so on,
so the page suits a fleet of three or thirty with no editing. Node identity is
the only spatial reference: no floor plan, no coordinates, nothing tied to one
building.

Two generic places sit alongside the nodes. A fleet never covers every space,
and the uncovered ones need ground truth arguably more than the rest, precisely
because nothing there is measuring.

An unreachable server or an empty roster is reported as such and leaves the
generic places usable. It never guesses at node ids -- invented ones would
attach marks to nodes that do not exist, which is worse than no mark.

Occupancy is recorded by ROLE, never by person: adult1, adult2, child1,
children-together, everyone. Ground truth outlives the run it was captured in,
so it should not carry anyone's name.

Marks are written twice, to the server sink and to localStorage, because losing
ground truth means re-walking everything.


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
Phase is the channel every published CSI technique leans on -- Doppler,
direction of arrival, breathing extraction -- and there is no way to see what
the phase channel on a given deployment actually contains. When a phase-based
method fails, nothing distinguishes "the algorithm is wrong" from "the phase on
this hardware is unusable".

Adds phase_diag.rs (600 lines, 8 tests): an opt-in sink recording raw and
sanitised per-frame phase to CSV for offline analysis, behind
--phase-diagnostics <dir>. Off unless the flag is given.

Single-antenna ESP32 CSI carries a packet-detection timing offset appearing as
a phase slope across subcarrier index, and it is large -- on this hardware
roughly 758 radians per ADC sample of jitter. That is not noise to be averaged
away; it swamps the physical phase entirely, and the sanitised channel is what
remains after detrending it. Comparing the two on real captures is the only way
to judge whether a phase-based method has signal to work with on a given board.

Co-Authored-By: claude-flow <ruv@ruv.net>
Ground truth recalled after the fact is soft. The only high-provenance label of
an overnight run is the one reported AS IT HAPPENS -- everything recalled
afterwards drifted by roughly half an hour, and matching a detection to a
remembered time is post-hoc fitting: during an active stretch the detector
bumps every ~1.5 min, so any estimate "matches" something.

Adds three pages that can be driven one-handed from a phone while walking:

  mark.html    stamp a labelled instant into the recording
  survey.html  record a position observation at a known point
  walk.html    capture a timed walk path

and GET /api/v1/diag/mark/:label, which stamps the label into the phase
diagnostics stream and returns the recording-relative timestamp so the client
can show what it captured.

Marks are written twice, to the server sink and to localStorage, because losing
ground truth means re-walking everything.

The endpoint reports plainly when diagnostics are not enabled rather than
accepting a mark that silently goes nowhere.

Co-Authored-By: claude-flow <ruv@ruv.net>
Adds the per-location tapper: stand near a node, tap its button, and the label
is stamped into the recording as it happens rather than recalled afterwards.

Built entirely from /api/v1/nodes at load. One button per node the server
actually knows about, sorted by id and labelled "Node 1", "Node 2" and so on,
so the page suits a fleet of three or thirty with no editing. Node identity is
the only spatial reference: no floor plan, no coordinates, nothing tied to one
building.

Two generic places sit alongside the nodes. A fleet never covers every space,
and the uncovered ones need ground truth arguably more than the rest, precisely
because nothing there is measuring.

An unreachable server or an empty roster is reported as such and leaves the
generic places usable. It never guesses at node ids -- invented ones would
attach marks to nodes that do not exist, which is worse than no mark.

Occupancy is recorded by ROLE, never by person: adult1, adult2, child1,
children-together, everyone. Ground truth outlives the run it was captured in,
so it should not carry anyone's name.

Marks are written twice, to the server sink and to localStorage, because losing
ground truth means re-walking everything.

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