feat(mesh): make the cold state name its action

With nothing shared anywhere, the row and popover were both status surfaces
with no status: a hollow dot beside "Buzz MeshLLM", and a "Mesh capacity"
heading over "0 sharing in this community". Nothing said what the switch does,
which is the one thing a first-time reader needs and the one thing a zero
cannot tell them.

The row now drops the "Buzz" qualifier -- "Buzz MeshLLM" plus an invitation
does not fit 256px, and the name is the part that can afford a word -- carries a
Share2 glyph where the status dot would go, and offers "Share your compute" in
the trailing slot. The dot returns the moment there is a real state to report,
which is the more honest signal there.

The popover's cold subtitle explains rather than reports: "Share your spare
compute with the Buzz community to run models." Its heading names the thing
instead of heading an absent number.

Only the cold state invites. A permanent nudge beside a real figure becomes
furniture, and a prompt derived from an unfetched snapshot would appear for one
poll and retract, reading as a glitch.

Also renames the popover's footer link from "Compute settings" to "Advanced
settings": it named the destination, where the useful thing to name is what is
there. The picker, custom model refs, and the memory cap are all advanced
concerns; the popover already covers the everyday ones.

Signed-off-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Michael Neale
2026-08-05 14:15:30 +10:00
parent cb1323a2d3
commit 390f0aa6ce
6 changed files with 141 additions and 26 deletions
@@ -327,3 +327,22 @@ test("the card hint distinguishes giving, taking, and neither", () => {
"3 of 4 requests ran on shared compute",
);
});
test("the cold popover explains the switch instead of restating a zero", () => {
// "0 sharing in this community" is a status line with no status. Someone
// opening this for the first time needs to know what the switch beside it
// does, which is the one thing a zero cannot tell them.
const model = deriveMeshDetailModel({
view: null,
snapshot: snapshot({
sharingDeviceCount: 0,
sharedCapacityGb: null,
devices: [],
}),
usage: null,
isSharing: false,
inboundWork: false,
});
assert.match(model.participationLabel, /Share your spare compute/);
assert.doesNotMatch(model.participationLabel, /^0 /);
});
@@ -31,6 +31,13 @@ import { describeRequestOrigin } from "./meshActivity";
* while our own dispatch count stays flat, means the work is not ours. See
* `inferInboundWork` in `meshActivity.ts`. It is sampled, so it can undercount
* — but it never over-claims, which is the direction that matters.
*
* ## The cold state explains, it does not report
*
* With nothing shared anywhere there is no status worth stating, so the subtitle
* says what the switch does rather than restating a zero. Every other state has
* a real number, and an explanation sitting permanently beside those would be
* furniture.
*/
export type MeshDetailModel = {
@@ -133,9 +140,12 @@ export function deriveMeshDetailModel({
? peers.length === 0
? "No other devices yet"
: `${peers.length} ${peers.length === 1 ? "peer" : "peers"} connected`
: // Not participating: the relay snapshot is all we have, and it is the
// reason to consider joining.
`${snapshot?.sharingDeviceCount ?? 0} sharing in this community`,
: (snapshot?.sharingDeviceCount ?? 0) > 0
? // Someone else is sharing: the count is the reason to join.
`${snapshot?.sharingDeviceCount ?? 0} sharing in this community`
: // Cold. There is no status worth reporting, so the line explains what
// the switch beside it actually does instead of restating a zero.
"Share your spare compute with the Buzz community to run models",
busyNow: (usage?.inflight ?? 0) > 0,
activityLabel: describeActivity({ usage, isSharing, inboundWork }),
originLabel: describeRequestOrigin(usage),
@@ -215,13 +215,38 @@ test("an agent that uses the mesh leaves a busy sharer showing 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.
// the trailing slot carries an invitation where a figure would go.
const model = derive({ snapshot: snapshot() });
assert.equal(model.tone, "unknown");
assert.equal(model.badge, "Share");
assert.equal(model.callToAction, "Share your compute");
assert.equal(model.badge, null);
assert.match(model.tooltip, /share this computer to start the mesh/);
});
test("the cold state drops the Buzz qualifier to make room", () => {
// "Buzz MeshLLM" plus "Share your compute" does not fit 256px. The name is
// the part that can afford to lose a word.
assert.equal(derive({ snapshot: snapshot() }).label, "MeshLLM");
assert.equal(
derive({
snapshot: snapshot({ sharingDeviceCount: 1, sharedCapacityGb: 36 }),
}).label,
"Buzz MeshLLM",
);
});
test("only the cold state invites; every other state reports", () => {
// A permanent nudge beside a real figure becomes furniture.
for (const input of [
{ snapshot: null },
{ snapshot: snapshot({ sharingDeviceCount: 2, sharedCapacityGb: 64 }) },
{ toggle: SHARING, view: view() },
{ toggle: CONSUMING },
]) {
assert.equal(derive(input).callToAction, null);
}
});
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
@@ -64,6 +64,11 @@ export type MeshRowPulse = "none" | "activity" | "invite";
export type MeshRowModel = {
tone: MeshRowTone;
/**
* Row label. Drops the "Buzz" qualifier in the cold state, where a call to
* action shares the same 256px and every character costs.
*/
label: string;
/** Accessible state sentence, used as the row tooltip. */
tooltip: string;
/**
@@ -78,6 +83,15 @@ export type MeshRowModel = {
* "Share" — the row would otherwise be inert with nothing explaining why.
*/
badge: string | null;
/**
* Invitation text, or null.
*
* Only set in the cold state — no capacity anywhere, nothing running. There
* is no number to show and no status to report, so without words the row is
* inert and unexplained. Every other state has a figure or a tone that speaks
* for itself, and a permanent nudge beside them would become furniture.
*/
callToAction: string | null;
/**
* Why the dot moves, if it does. Never decorative: a still dot is a real
* statement that there is nothing to act on and nothing happening.
@@ -85,6 +99,9 @@ export type MeshRowModel = {
pulse: MeshRowPulse;
};
/** Full name. Used everywhere except the cold state, which needs the room. */
const LABEL = "Buzz MeshLLM";
/** Live pool capacity: this machine plus every peer that reports a figure. */
function liveCapacityGb(view: MeshLiveView | null): number {
if (!view?.connected) return 0;
@@ -126,9 +143,11 @@ export function deriveMeshRowModel({
) {
return {
tone: "starting",
label: LABEL,
tooltip:
pendingAction === "stop" ? "Stopping sharing…" : "Starting to share…",
badge: null,
callToAction: null,
pulse: "none",
};
}
@@ -138,8 +157,10 @@ export function deriveMeshRowModel({
if (health && health.status !== "ok") {
return {
tone: "failed",
label: LABEL,
tooltip: "Sharing failed — open for details",
badge: null,
callToAction: null,
pulse: "none",
};
}
@@ -153,18 +174,22 @@ export function deriveMeshRowModel({
if (hasMeshAgent === false) {
return {
tone: "sharing",
label: LABEL,
tooltip: "Sharing compute · no agent is using it yet",
badge,
callToAction: null,
pulse: "invite",
};
}
return {
tone: "sharing",
label: LABEL,
tooltip:
peerCount > 0
? `Sharing compute · ${peerCount} ${plural(peerCount, "peer")}`
: "Sharing compute · waiting for another device",
badge,
callToAction: null,
pulse: busyNow ? "activity" : "none",
};
}
@@ -173,8 +198,10 @@ export function deriveMeshRowModel({
const gb = liveCapacityGb(view);
return {
tone: "consuming",
label: LABEL,
tooltip: "Using shared compute from the mesh",
badge: gb > 0 ? formatCapacityGb(gb) : null,
callToAction: null,
pulse: busyNow ? "activity" : "none",
};
}
@@ -187,8 +214,12 @@ export function deriveMeshRowModel({
// would appear for one poll and retract, which reads as a glitch.
return {
tone: "unknown",
label: LABEL,
tooltip: "Checking for shared compute…",
badge: null,
// Nothing offered from no data: a prompt that appears for one poll and
// retracts reads as a glitch, not a suggestion.
callToAction: null,
pulse: "none",
};
}
@@ -203,14 +234,18 @@ export function deriveMeshRowModel({
// annoyance. The invite throb stays reserved for capacity that exists.
return {
tone: "unknown",
// "Buzz" is dropped here so the invitation fits beside it.
label: "MeshLLM",
tooltip: "No shared compute yet — share this computer to start the mesh",
badge: "Share",
badge: null,
callToAction: "Share your compute",
pulse: "none",
};
}
const gb = snapshot.sharedCapacityGb;
return {
tone: "available",
label: LABEL,
tooltip:
gb === null
? `Shared compute available · ${count} ${plural(count, "device")}`
@@ -221,6 +256,7 @@ export function deriveMeshRowModel({
gb === null
? `${count} ${plural(count, "device")}`
: formatCapacityGb(gb),
callToAction: null,
pulse: "invite",
};
}
@@ -83,7 +83,7 @@ export function MeshComputePopover({
<div className="flex items-start justify-between gap-2">
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-semibold leading-tight">
{model.capacityLabel ?? "Mesh capacity"}
{model.capacityLabel ?? "Buzz MeshLLM"}
</p>
<p
className="mt-0.5 text-2xs text-muted-foreground"
@@ -226,7 +226,7 @@ export function MeshComputePopover({
onClick={onOpenComputeSettings}
type="button"
>
Compute settings
Advanced settings
</button>
) : null}
</div>
@@ -1,3 +1,5 @@
import { Share2 } from "lucide-react";
import { SidebarMenuButton, SidebarMenuItem } from "@/shared/ui/sidebar";
import { SidebarMenuLabel } from "@/shared/ui/sidebar-menu-label";
import { cn } from "@/shared/lib/cn";
@@ -81,31 +83,47 @@ export function SidebarMeshComputeRow({
aria-hidden
className="flex h-4 w-4 shrink-0 items-center justify-center"
>
<span className="relative flex h-2 w-2 items-center justify-center">
{row.pulse === "none" ? null : (
<span
className={cn(
"absolute h-2 w-2 rounded-full opacity-75 motion-reduce:animate-none",
PULSE_CLASS[row.pulse],
TONE_PING[row.tone],
)}
data-mesh-pulse={row.pulse}
/>
)}
<span
className={cn("h-2 w-2 rounded-full", TONE_DOT[row.tone])}
data-testid="mesh-row-dot"
{/*
In the cold state a status dot has nothing to say — there is no
capacity to report and nothing running — so the slot carries a
Share2 glyph, which names the action instead. Every other state has
a real status, and the dot is the more honest signal there.
*/}
{row.callToAction ? (
<Share2
className="h-3.5 w-3.5 text-muted-foreground"
data-testid="mesh-row-share-icon"
/>
</span>
) : (
<span className="relative flex h-2 w-2 items-center justify-center">
{row.pulse === "none" ? null : (
<span
className={cn(
"absolute h-2 w-2 rounded-full opacity-75 motion-reduce:animate-none",
PULSE_CLASS[row.pulse],
TONE_PING[row.tone],
)}
data-mesh-pulse={row.pulse}
/>
)}
<span
className={cn("h-2 w-2 rounded-full", TONE_DOT[row.tone])}
data-testid="mesh-row-dot"
/>
</span>
)}
</span>
<SidebarMenuLabel className="opacity-80">
Buzz MeshLLM
{row.label}
</SidebarMenuLabel>
</SidebarMenuButton>
</MeshComputePopover>
{/*
Capacity, in every state that has a number — not just while sharing.
The trailing slot: an invitation when cold, capacity otherwise.
Capacity shows in every state that has a number — not just while
sharing.
This slot used to hold a 70%-scaled unlabelled Switch, which was hard to
see and ambiguous about what it would do. The control moved wholesale to
@@ -114,7 +132,14 @@ export function SidebarMeshComputeRow({
joining better than any exhortation, and unlike a nudge there is nothing
to dismiss. Pointer-events off so the whole row stays one click target.
*/}
{row.badge ? (
{row.callToAction ? (
<span
className="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-2xs font-medium text-muted-foreground group-data-[collapsible=icon]:hidden"
data-testid="mesh-row-cta"
>
{row.callToAction}
</span>
) : row.badge ? (
<span
className="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-2xs tabular-nums text-muted-foreground group-data-[collapsible=icon]:hidden"
data-testid="mesh-row-badge"