D175 — The dashboard is binding-aware, and says when it does not know¶
Decision. The dashboard stays one list screen and gains four things: a kbs
line per provider carrying its binding and the binding's origin, a kinds line
carrying the per-kind breakdown cartographer status already printed, a server
panel broken into a labelled block whose KB inventory counts bindings per KB,
and a footer, a sync-all progress report and a disconnect confirmation that
name what they act on. Every provider detail line goes through one grid helper.
Rationale.
- The screen could not answer the question it exists to ask. With four KBs
mounted every provider rendered identically — three lines, all
in-sync— and the KB list appeared once, as a property of the server. Which provider receives which KB was unanswerable, and D170 made the answer differ per provider. The binding belongs on the provider, next to what it explains. - The three binding states get three sentences.
BoundKBsdistinguishes absent, empty and populated; rendering the first two as an empty list would make "receives every known KB" and "receives none" look the same, which is the exact confusion D169 introduced the resolver to prevent. So: the names with(explicit),all known (default),none (explicit). - The TUI showed strictly less than the CLI, and the comment claimed
otherwise.
formatKindStatus's doc comment named the dashboard as a caller; it never was one. The breakdown was already on the snapshot both renderers read, so this is a rendering omission, not a new computation — and the fix is reading the field, which is also why the two cannot now drift. - "Not measured" is not "fine". A breakdown is only shown for a provider
whose manifest was actually read:
remoteStatusMsg.kindsomits a provider whose state came backunknown, and the row rendersunknownrather than keeping the previous poll's counts. A dashboard reportingin-synccomputed against a manifest it could not fetch is worse than one that admits it does not know. The mirror case is kept apart: a manifest read and found empty isno artifacts. - The count in the server panel is a count of bindings. Not sessions, not
proof a sync completed — the label says
boundfor exactly that reason. A KB the server mounts and nobody consumes (kb-tre (0)) is the most useful fact the panel can carry, and it can only carry it if the number means one thing. - No new colours, no second pane. The dashboard is a quick-inspection tool;
depth belongs to
statusanddoctor. Another badge in another colour makes the screen less readable, not more, so the existing styles are reused and the work went into the grid instead. - Progress reporting must never be able to stall a sync.
Swas already sequential under one lock (D172); it now announces each provider on a channel buffered for the whole run, so a send cannot block while the lock is held. A progress message arriving after the outcome is dropped rather than allowed to overwrite the result the user needs to read. - The confirmation names the KBs. "Removes managed artifacts" does not say what leaves the machine, which is the only thing a destructive confirmation is for.
Deviation from the plan. The plan folded the breakdown under artifacts as
a second, unlabelled line. It became a labelled kinds row instead: an
unlabelled unknown floating under a status is ambiguous about what is
unknown, and the two-column grid the plan calls the reason the screen is
scannable is what makes the label cheap.
Invariant preserved. The first frame is still built from local data only —
the binding is resolved in buildRows through Config.BoundKBs, alongside
agent detection and mcp-config presence. Nothing added here waits on the
network.
Consequences. Presentation only; no behaviour outside the dashboard
changes. The server panel's single line became four, and ready=ready became
· ready — cosmetic, but visible to anyone reading a screenshot. The S
behaviour change is the one inherited from D172 and should be described as such
in the release notes.