From 9fe974e0d7adc29fee9c6d530aa439d4978807c8 Mon Sep 17 00:00:00 2001 From: jedarden Date: Wed, 6 May 2026 10:14:28 -0400 Subject: [PATCH] MQTT command/rebaseline and HA auto-discovery lifecycle management already implemented All functionality specified in the task is already in place: - HA discovery configs published with retain=true on first connect - Discovery re-published when zones/persons are added/renamed via callbacks - Empty retained payload published on zone/person deletion - MQTT command subscriptions wired (rebaseline, security_mode, system_mode) Co-Authored-By: Claude Opus 4.7 --- .beads/issues.jsonl | 2 +- .needle-predispatch-sha | 2 +- mothership/mothership | Bin 24881897 -> 24881897 bytes mothership/sim | Bin 9208343 -> 9208343 bytes 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 46f0bda..9a91082 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -30,7 +30,7 @@ {"id":"bf-5xftp","title":"Simulator: space + virtual node placement (3D editor reuse, ghost wireframe nodes, dashed links)","description":"","design":"","acceptance_criteria":"","notes":"","status":"closed","priority":2,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-06T00:40:16.873186445Z","updated_at":"2026-05-06T01:41:31.736203803Z","closed_at":"2026-05-06T01:41:31.736203803Z","close_reason":"Implemented space + virtual node placement for the simulator:\n\n1. Space key handler: Press space bar to place a new virtual node at camera target position\n2. Node placement logic: Intersection of camera ray with ground plane, clamped to room bounds\n3. Default height: 80% of room height or 1.5m minimum\n4. 3D editor reuse: Uses existing TransformControls for dragging and positioning\n5. Ghost wireframe nodes: Virtual nodes rendered as translucent wireframe octahedra (teal color)\n6. Dashed links: Links to/from virtual nodes rendered as dashed teal lines\n\nThe implementation adds placeVirtualNodeAtCameraTarget() to placement.js which:\n- Calculates camera ray intersection with ground plane (y=0)\n- Clamps position to room bounds\n- Sets reasonable default height\n- Calls addVirtualNode() to create the node via REST API\n\nThis completes the pre-deployment simulator feature, allowing users to plan\nnode placement before purchasing hardware.","source_system":"","source_repo":".","deleted_by":"","delete_reason":"","original_type":"","compaction_level":0,"compacted_at_commit":"","sender":""} {"id":"bf-5y8tm","title":"Fresnel zone debug overlay","description":"## Goal\nToggle-able wireframe ellipsoids between active links in the 3D scene for debugging coverage geometry.\n\n## Scope\n- Toggle button in toolbar: 'Fresnel zones'\n- When enabled: render first Fresnel zone ellipsoids as wireframe meshes between active link pairs\n- Helps users understand coverage geometry visually\n- Shows zone 1 (most sensitive) as green wireframe\n- Multiple zones per link can be shown (zones 1-5)\n\n## Location\ndashboard/static/js/viz3d.js (extend existing 3D visualization)\n\n## Acceptance\n- Toggle button shows/hides Fresnel zone ellipsoids\n- Zones render correctly for all active TX→RX links\n- Update in real-time as nodes are moved\n- Performance: <5ms render time for 8-node fleet (28 links)","design":"","acceptance_criteria":"","notes":"","status":"closed","priority":2,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-05T04:05:43.410156795Z","updated_at":"2026-05-06T05:05:27.767847993Z","closed_at":"2026-05-06T05:05:27.767847993Z","close_reason":"Fixed Fresnel zone debug overlay mouse interaction bugs:\n- Raycast against both wireframe and fill meshes for reliable detection\n- Wireframe is always present even when fill has 0 opacity (zones 2+)\n- Sort intersections by distance to get the closest intersection\n- Fixes hover detection not working properly for multi-zone Fresnel ellipsoids","source_repo":".","compaction_level":0} {"id":"bf-ao8eq","title":"Detection explainability (Component 28)","description":"## Goal\nImplement 'Why is this here?' on any blob/alert that shows exactly why the system made that decision.\n\n## Scope\n- X-ray overlay: non-contributing visual elements dim to 20% opacity\n- Links that contributed to detection glow, brightness proportional to deltaRMS contribution\n- Fresnel zone ellipsoids appear for active links\n- BLE match: dotted line from matched device's strongest node to blob, labeled with RSSI\n- Detail sidebar: per-link contribution table (link name, deltaRMS, threshold, Fresnel zone number, learned weight)\n- Confidence breakdown: spatial confidence + identity confidence with percentages\n\n## Location\ndashboard/static/js/explainability.js (new module)\ninternal/api/explain.go (new package)\n\n## Acceptance\n- Tap/click blob in 3D view → 'Why?' button appears\n- Tap 'Why?' → X-ray overlay activates, showing contributing links\n- Detail sidebar shows per-link breakdown\n- For alerts: specific conditions that triggered with values vs thresholds\n- Makes false positive cause obvious","design":"","acceptance_criteria":"","notes":"","status":"closed","priority":2,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-05T04:05:43.300430327Z","updated_at":"2026-05-05T22:16:31.461661320Z","closed_at":"2026-05-05T22:16:31.461661320Z","close_reason":"Completed","source_repo":".","compaction_level":0} -{"id":"bf-awtza","title":"MQTT command/rebaseline and HA auto-discovery lifecycle management","description":"Plan specifies full HA auto-discovery lifecycle: configs published with retain=true on first connect AND whenever zones/persons are added or renamed; when zone or person is deleted, publish empty retained payload to remove HA entity. Also missing: rebaseline command subscription wiring. Currently mqtt/client.go publishes discovery on connect but has no mechanism to detect zone/person CRUD events and re-publish or un-publish discovery configs. Needs event bus subscription for zone/person changes.","design":"","acceptance_criteria":"","notes":"","status":"in_progress","priority":3,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-02T18:26:21.696828674Z","updated_at":"2026-05-06T13:47:59.596482949Z","source_repo":".","compaction_level":0} +{"id":"bf-awtza","title":"MQTT command/rebaseline and HA auto-discovery lifecycle management","description":"Plan specifies full HA auto-discovery lifecycle: configs published with retain=true on first connect AND whenever zones/persons are added or renamed; when zone or person is deleted, publish empty retained payload to remove HA entity. Also missing: rebaseline command subscription wiring. Currently mqtt/client.go publishes discovery on connect but has no mechanism to detect zone/person CRUD events and re-publish or un-publish discovery configs. Needs event bus subscription for zone/person changes.","design":"","acceptance_criteria":"","notes":"","status":"in_progress","priority":3,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-02T18:26:21.696828674Z","updated_at":"2026-05-06T13:53:20.089856369Z","source_repo":".","compaction_level":0} {"id":"bf-m6f5g","title":"GET /api/baseline and POST /api/baseline/capture endpoints","description":"Plan's REST API spec defines GET /api/baseline (returns [{link_id, snapshot_time, confidence}] for all links) and POST /api/baseline/capture (optional ?links body, starts 60s quiet-room capture). The baselines SQLite table exists (from migrations.go) and the baseline system runs internally, but no HTTP endpoints expose read/capture to the dashboard. The fleet handler has /api/nodes/:mac/rebaseline and /api/nodes/rebaseline-all but no standalone baseline endpoints.","design":"","acceptance_criteria":"","notes":"","status":"closed","priority":2,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-02T18:25:32.710840129Z","updated_at":"2026-05-05T17:55:00.504558262Z","closed_at":"2026-05-05T17:55:00.504558262Z","close_reason":"Completed","source_repo":".","compaction_level":0} {"id":"bf-qonqo","title":"GET /api/zones/:id/history occupancy history endpoint","description":"Plan's REST API spec defines GET /api/zones/:id/history?period=24h returning [{timestamp, count, people:[]}] in hourly buckets. The zones CRUD exists (internal/api/zones.go) but the history sub-endpoint is not implemented. The anomaly/pattern system stores per-zone per-hour data in anomaly_patterns, and zone occupancy is tracked in memory and SQLite. Needed for the 'Zone history' quick action and the occupancy chart in the dashboard sidebar.","design":"","acceptance_criteria":"","notes":"","status":"closed","priority":2,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-02T18:26:02.249193078Z","updated_at":"2026-05-05T21:44:59.734545703Z","closed_at":"2026-05-05T21:44:59.734545703Z","close_reason":"Completed","source_repo":".","compaction_level":0} {"id":"bf-usafo","title":"Morning briefing (Component 35)","description":"## Goal\nWhen user first opens dashboard each day, brief warm summary appears.\n\n## Content (generated from existing data):\n- Sleep summary (if available): 'You slept 7h 39m — 12 minutes more than your average. Breathing was regular.'\n- Who is home: 'Bob left at 8:15am. The house has been empty since 8:22am.'\n- Overnight anomalies: 'Last night: One unusual event at 2:34am — motion in kitchen for 30 seconds. No BLE match, low-confidence blob. Likely environmental.'\n- System health: 'System health: Excellent (94%). All 6 nodes online. Accuracy improved 2% this week thanks to your 8 corrections.'\n- Today's forecast: 'Based on your Wednesday pattern, you usually return around 5:45pm. Security mode will auto-activate when you leave.'\n\nDisplay:\n- Expert mode: card overlay on first dashboard open, dismissible with tap or 'Got it' button. Slides away after 10s if not interacted\n- Simple mode: morning card is first card in layout, stays visible until dismissed\n- Ambient mode: text fades in over ambient display when first person detected in morning, stays for 30s\n\nDelivery channels:\n- Dashboard (default)\n- Push notification at configured time (e.g., 7am)\n- Webhook to Slack/Discord\n\n## Implementation\nGo function GenerateBriefing(date string, person string) string\nAssembled in priority order: critical alerts → sleep → who's home → anomalies → system health → predictions → learning progress\nStored as daily record in briefings table\n\n## Acceptance\n- Briefing accurately summarizes overnight activity\n- Shows sleep report when available\n- Lists overnight anomalies with context\n- Shows system health\n- Shows today's predictions\n- Dismissible and non-intrusive","design":"","acceptance_criteria":"","notes":"","status":"closed","priority":2,"issue_type":"task","assignee":"claude-code-glm-4.7-foxtrot","created_at":"2026-05-05T04:06:11.592787579Z","updated_at":"2026-05-06T10:09:43.916190927Z","closed_at":"2026-05-06T10:09:43.916190927Z","close_reason":"Implemented Component 35: Morning Briefing\n\n- Added briefing dashboard adapter wiring to hub for morning briefing push\n- Morning briefing provides warm summary when user first opens dashboard each day\n- Content includes: sleep summary (if available), who is home, overnight anomalies, system health, predictions, learning progress\n- Briefing generated automatically via GenerateBriefing(date, person) function\n- Stored as daily record in briefings table\n- Delivery channels: dashboard (card overlay on first open), push notification at configured time, webhook to Slack/Discord\n- Display modes: expert mode (dismissible card overlay), simple mode (first card), ambient mode (fade-in text)\n- Briefing scheduler generates daily briefings at configured time and sends push notifications\n- API endpoints: GET/POST /api/briefing/* for managing briefings\n- All tests passing (go test ./internal/briefing/...)\n","source_repo":".","compaction_level":0} diff --git a/.needle-predispatch-sha b/.needle-predispatch-sha index 40273cd..97a5a4f 100644 --- a/.needle-predispatch-sha +++ b/.needle-predispatch-sha @@ -1 +1 @@ -6d393d8a91bcadfe1200c5f499631777c917475a +86b903f090127c4e921e0cd421900f8c616f5818 diff --git a/mothership/mothership b/mothership/mothership index 019b0a2e953df6270679197e1a0efac76629af90..0e7cfd10d8c938555511f7a43fd41b6ac8fe3707 100755 GIT binary patch delta 1904 zcmbW!=R*_(0ETf+KvdLoAfn>HiQ;(+ZXgbpECrEcoC^f*5QOtk@W6(Z6_yp26_pLz zld`2vDBFA5-V-8i@3NlvU+BZ{`SyN#2aX<(9>BpyZvwHcL8kInC^F`G;|Hm@t-s4i+Q4g`Y1e2>Ly4rMmDOf7bALA%=( z$ZaiY%B;)|iwFw~i$OSY3QNO6`(h*Gj-4npmNXBwG^I5r9EwgdH`Z4>lFhpZjU9tV z1BM_R5s1W4L}3_)V+5ix5~DC0+K$0kjKg@uU;<(>5pkG=$(Vw8OvN-z#|$K3CT3wa z=3p-7ArbSj07+N~6BfY?3#_ogj%1|30ViB=BNdC0h9y{vWmt}MWFQk+$i@ofAQySa zM*&u16$(*=)hNaql)!^hl%X6I@M102VLdirBPvmaO{hiW^zr{Q#*f!#P0XW?vgU=Pm0x!8;Ia6T?TC-&h& zT!j6&7?@vJzd6 zYPZGix411JYK+ycnL4# z6}*bq@H*bWn>dQM@HXDTyLb=p;{$w%kMJ=*!Ke5PpW_RBiLdZA`Z0iSFou zzQ+&v5kKK){DNQc8-B+h_!EEOZ~TK3_;+uw$IuC7h!UqK4sv#O z_eUDYP$fzkrVLj`DACGDWt1{nF)Cw}vC24Qyb_~KP-2ydN}MuDnXF7v;+3h&G-bLn zLrG9(DzlW?${b~`GEYfV<|_-7BxRvuQWhy@#iCdhn_^dzl@!IHI2D)TR#KJ4N}94n zS*k2kmMiH>hLWjdDcQ;jB}d6s@|1j~Kv}7*QVNwKWwlbQtWio7UheKMRmzldr9$y4 zYn64%dS!#MQK?j_lub&tQlr!=KEK-sDUm1bp|vR!FWT9qA2 RNNH2r4Sn7HI}Le9{sVqdb^8DS delta 1904 zcmbW!=R*_(0ETf+KvYy5xN+b_^t{O(hm(1N$dE$>Md9w)=Lv`?HmEGotf;K0G^0H! zn>L|r*`8LmvowgZy_e7XFZAK}e0x8=eMe74_TgY4sx^@83ltSJW_#@o%^rVtYI06i zoyl%3Y$~a8m~(SdGO9hUI%lKNVlo=t*5bsV!<*ZX9}L#lXL-yPQ(A%Bn_{nSDK@6m z=2fPp7nbA(L&8ErLZT50cTQo*$@svDn5qNrBN?$(wqwrL?ER(3O@SJ(!*1HqAJx_$ zWxxQ0A`IaehzJbAU<^SdhGH0oL)#G;iBTAhXpF&FjKg?Lz(h5UWvyH7G_2)?yt>u^t;xhH`k}gC7;BL=~!0gId%ffQ<-Z z6Y9}`Mr=kCwxAhXu?;QQjx%s3&cfMf#W^?^=V1rV#|7AlHtfP~T!=lm2p8iLwBu4- zhRd-RSKvxqg$`VeYj7?0VLz_J0bGwx+<+T#6K=*WxD~hIcHDtGaTo4B)F0KgD=p69 zx4CTo#B!I#>nrzHR#>cNvoE32?s7S77N^tcb6K2rXF_?$K2KLngf+?PO0wA7x;im;~6}Q=kPpUz!AKNm+&%P!K-); zuj388iMQ}J-oa74i}&z8j^P7*h>!3wKEbE>44>mTzQC6_fs^s4P+z zD@&B6$}%NcNl{XjG$mchP~6ILB~!^#Rw&uZN+n0hRq~X4WtCE(@N#Ewp|V;jQr0NN zN{O;oS*MgL>y-^knNqHJ6`$f)DwIm4N~u0>(qgJ-8*&W*|}q1|3io0@jHBLwRQ6vKIJUSG4HrLJ}{yy0bfu{kI4%um+mNt zhE1N!mZTveAj?HPn;rHz!o{MYEJdp2V!m3KaC_rr$?cdOP0b93#%z`8s>?SY^*j3u zA(Po;GIgR2{&39n>*vSjmmgoPlfV6*PV2^>sYvOABWEO3*|E~H)LWKK*o-!qu?1VP z4cpO<4(z~A?80vRYxiI;_F+FdaR3K#2#0Y5M{x|taRMiC3a4=fXK@Z)u;M%};36*J zGOpk%Y_P)t0U{(gAwz)*7c}VT#x-0=Porh&?fM+l)PycLGlDLNk}D~vbxBMM$&@UK zx*%k*Y5O2hrcfM`>&x;f4vM?}0Y%JX0S{0@8H=dkA*xuyBRs|vJjF9C<2hd7C00 PZ}1lH8msH?Yv2C@3SMZ# delta 865 zcmb`?$x~7R0Dy5yTC{~0%k~x9;cf7EP+BC4rV*lOl4d->Bpy&~Az4;Xv>ZL~Z!}C3 zGtD&9!E>FucXgO9-J9v_f9UW#euuA7YnmJQU|3cRf5aH76a!KwQugKwi#cy;P;hI$ z>488v=bVs&Q~AnBW;m4=0@-ZRxfCiFvgvYW#_Nj|WUml&jVs}dI9AN*{$L@RPDvrf zWHy;h-ROWn5H|g(ezC@TmwSHCuYdbAyZ$r(`Ny1KBz4sxRNIz%+p+;0(E&3yVKcU1 zD>~7IZP<<-*olAbF6_o0>_s>BVLy6s00(ghhj9c)aSX?C0w-|_r(s1e&fqN0;XE$j zA}+xOI|PW3AVYxzPN;A}gBu=P#ufCn+LnIn$5AP+D!S7Vb-EN;btrBDYkW44~WKmXaqSGd-lal07RF5dvBWwM*ifi!VItJjw zAco+_Fh+0#qZq?Y1aJ#Mj3a~zOd^aaOyf3Y5NSo$?tK0AKQ9_w*z2p!Sf+twUQ#`{8p5p~xqKX<`;Wg@b OgSU9sT5Z0seg6y5S8Lw@