From cb1323a2d32f495308539d4cacb269028633075b Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Wed, 5 Aug 2026 13:26:26 +1000 Subject: [PATCH] feat(mesh): name the row Buzz MeshLLM, and offer the action when the mesh is empty An empty mesh was the one state with nothing to show and nothing happening, so the row sat inert with nothing explaining why. The action is real -- you can be the first to share -- so the badge slot now carries the word "Share" where a figure would otherwise go. Static rather than throbbing. A community that never uses the mesh would animate forever, and permanent motion earns nothing but annoyance; the invite throb stays reserved for capacity that actually exists. An unfetched snapshot still offers nothing at all. A prompt derived from no data would appear for one poll and retract, which reads as a glitch rather than a suggestion -- so "not asked yet" and "asked, nothing there" are now separate branches instead of one condition. Row label is "Buzz MeshLLM" rather than "Community mesh". Signed-off-by: Michael Neale --- .../mesh-compute/meshRowModel.test.mjs | 19 +++++++++++++ .../src/features/mesh-compute/meshRowModel.ts | 27 ++++++++++++++++--- .../mesh-compute/ui/SidebarMeshComputeRow.tsx | 4 +-- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/desktop/src/features/mesh-compute/meshRowModel.test.mjs b/desktop/src/features/mesh-compute/meshRowModel.test.mjs index cc699bb77..870bdac55 100644 --- a/desktop/src/features/mesh-compute/meshRowModel.test.mjs +++ b/desktop/src/features/mesh-compute/meshRowModel.test.mjs @@ -211,3 +211,22 @@ test("an agent that uses the mesh leaves a busy sharer showing activity", () => }); assert.equal(model.pulse, "activity"); }); + +test("an empty mesh offers the action instead of sitting inert", () => { + // Nothing to show and nothing happening: without a prompt the row is inert + // and unexplained. The action is real -- you can be the first to share -- so + // the badge slot carries the word where a figure would go. + const model = derive({ snapshot: snapshot() }); + assert.equal(model.tone, "unknown"); + assert.equal(model.badge, "Share"); + assert.match(model.tooltip, /share this computer to start the mesh/); +}); + +test("an empty mesh does not throb, and an unfetched one offers nothing", () => { + // A community that never uses the mesh would otherwise animate forever; + // permanent motion earns nothing but annoyance. And a prompt derived from no + // data would appear for one poll then retract, reading as a glitch. + assert.equal(derive({ snapshot: snapshot() }).pulse, "none"); + assert.equal(derive({ snapshot: null }).badge, null); + assert.equal(derive({ snapshot: null }).pulse, "none"); +}); diff --git a/desktop/src/features/mesh-compute/meshRowModel.ts b/desktop/src/features/mesh-compute/meshRowModel.ts index c35c61f16..195b4f67c 100644 --- a/desktop/src/features/mesh-compute/meshRowModel.ts +++ b/desktop/src/features/mesh-compute/meshRowModel.ts @@ -73,6 +73,9 @@ export type MeshRowModel = { * machine is outside the mesh the figure *is* the invitation: a real number * argues for joining better than any exhortation, and unlike a nudge there is * nothing to dismiss. + * + * When the mesh is empty there is no figure, so the slot carries the word + * "Share" — the row would otherwise be inert with nothing explaining why. */ badge: string | null; /** @@ -179,16 +182,32 @@ export function deriveMeshRowModel({ // Not participating. The relay snapshot is the only view, and the only thing // that distinguishes "there is a mesh to join" from "there is nothing here". const count = snapshot?.sharingDeviceCount ?? 0; - if (!snapshot || count === 0) { + if (!snapshot) { + // Not asked yet. No figure, no prompt: a call to action based on no data + // would appear for one poll and retract, which reads as a glitch. return { tone: "unknown", - tooltip: snapshot - ? "No shared compute in this community yet" - : "Checking for shared compute…", + tooltip: "Checking for shared compute…", badge: null, pulse: "none", }; } + if (count === 0) { + // An empty mesh is the one state with nothing to show and nothing + // happening, so without a prompt the row is inert and unexplained. The + // action is real — you can be the first to share — so the badge slot + // carries the word instead of a figure. + // + // Static, not throbbing. A community that never uses the mesh would + // otherwise animate forever, and permanent motion earns nothing but + // annoyance. The invite throb stays reserved for capacity that exists. + return { + tone: "unknown", + tooltip: "No shared compute yet — share this computer to start the mesh", + badge: "Share", + pulse: "none", + }; + } const gb = snapshot.sharedCapacityGb; return { tone: "available", diff --git a/desktop/src/features/mesh-compute/ui/SidebarMeshComputeRow.tsx b/desktop/src/features/mesh-compute/ui/SidebarMeshComputeRow.tsx index a638caf32..86fef77f5 100644 --- a/desktop/src/features/mesh-compute/ui/SidebarMeshComputeRow.tsx +++ b/desktop/src/features/mesh-compute/ui/SidebarMeshComputeRow.tsx @@ -7,7 +7,7 @@ import type { MeshRowPulse, MeshRowTone } from "../meshRowModel"; import { MeshComputePopover } from "./MeshComputePopover"; /** - * The sidebar Community mesh row. + * The sidebar Buzz MeshLLM row. * * Replaces the ~120px footer card with one menu line beside Inbox and Agents, * because front-page sidebar space is premium. The row carries a single signal @@ -99,7 +99,7 @@ export function SidebarMeshComputeRow({ - Community mesh + Buzz MeshLLM