From 473c5d11dbf9baa74940047e247f348d98796502 Mon Sep 17 00:00:00 2001 From: ruv Date: Sat, 23 May 2026 14:38:57 -0400 Subject: [PATCH] docs(adr-110): user-guide REST docs for /api/v1/mesh and /api/v1/nodes/:id/sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Iter 31 — parallels the iter 25 WebSocket sync docs with the matching HTTP surface. Adds 2 rows to the REST API table + a worked "Get fleet mesh state" example showing the sample JSON for two C6 boards (leader + follower) so operators see the leader's near-zero offset alongside the follower's §A0.10-measured 1.16 s delta in the same response. Also covers the 404 paths the iter 29 handlers actually emit: - {"error": "unknown_node", "node_id": N} - {"error": "no_sync", "node_id": N, "hint": "..."} The "hint" field is verbatim so operators searching docs for the string they see in curl output land here. Links back to the existing "Per-node mesh sync (ADR-110)" section for field meanings instead of duplicating them — one source of truth. Co-Authored-By: claude-flow --- docs/user-guide.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/docs/user-guide.md b/docs/user-guide.md index 74642bc3..08750a87 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -473,6 +473,71 @@ Base URL: `http://localhost:3000` (Docker) or `http://localhost:8080` (binary de | `POST` | `/api/v1/adaptive/train` | Train adaptive classifier from recordings | `{"success":true,"accuracy":0.85}` | | `GET` | `/api/v1/adaptive/status` | Adaptive model status and accuracy | `{"loaded":true,"accuracy":0.85}` | | `POST` | `/api/v1/adaptive/unload` | Unload adaptive model | `{"success":true}` | +| `GET` | `/api/v1/mesh` | ADR-110 fleet-wide mesh sync map ([iter 29](adr/ADR-110-esp32-c6-firmware-extension.md)) | `{"nodes":{"9":{...},"12":{...}},"total":2}` | +| `GET` | `/api/v1/nodes/:id/sync` | Single-node mesh sync snapshot (or 404) | `{"offset_us":1163565,"is_leader":false,...}` | + +### Example: Get fleet mesh state (ADR-110) + +```bash +curl -s http://localhost:3000/api/v1/mesh | python -m json.tool +``` + +```json +{ + "nodes": { + "9": { + "offset_us": 1163565, + "is_leader": false, + "is_valid": true, + "smoothed": true, + "sequence": 20, + "csi_fps_ema": 10.0, + "csi_fps_samples": 47 + }, + "12": { + "offset_us": -7, + "is_leader": true, + "is_valid": true, + "smoothed": false, + "sequence": 20, + "csi_fps_ema": 10.0, + "csi_fps_samples": 51 + } + }, + "total": 2 +} +``` + +Empty `{"nodes": {}, "total": 0}` means no mesh peers reachable. +Nodes that haven't emitted a sync packet yet are omitted from the map. + +### Example: Get one node's sync state + +```bash +curl -s http://localhost:3000/api/v1/nodes/9/sync | python -m json.tool +``` + +200 → same `NodeSyncSnapshot` shape as inside `/api/v1/mesh` or the +WebSocket `sync` field. Field meanings are documented under +[Per-node mesh sync (ADR-110)](#per-node-mesh-sync-adr-110). + +404 (unknown node): +```json +{"error": "unknown_node", "node_id": 99} +``` + +404 (node exists but hasn't synced yet): +```json +{ + "error": "no_sync", + "node_id": 9, + "hint": "node hasn't emitted a sync packet yet (no mesh peer or not v0.6.9+)" +} +``` + +Useful for Home Assistant REST sensors, Prometheus exporters, +automation rule probes, and curl debugging — anywhere you want +one-shot mesh state without holding a WebSocket connection. ### Example: Get Vital Signs