Feature work (not a bug): ClientScreen only showed the orbital, server-rooted
parent/child layout, so a swarm’s actual data-flow wiring (sources/inputs)
was invisible as a primary structure and cross-server flow couldn’t be seen at
all. Implemented via openspec change add-node-flow-view.
N/A — net-new capability. Added a second ClientScreen layout (Flow view) that hides structural containers and lays the combined swarm out by its data-flow edges, toggled from a top-right icon mirroring the avatar.
ScreenCore gained a viewMode: StateFlow<CanvasViewMode> (Server/Flow) + a
toggleViewMode() — a sticky preference deliberately not cleared by
reset(). NodeLayout.kt gained computeFlowPositions(swarm, nodeManager)
delegating to a pure, manager-free computeFlowLayout(nodes): it excludes
Server/Project/Client, builds the sources ∪ inputs edge set (resolving
peer-qualified host:nodeId ids, dropping edges to absent/hidden endpoints),
groups nodes into connected components, force-lays each component reusing the
existing sim primitives (applyNodeRepulsion/applyEdgeCrossingForces/
applyForcesWithDampening) with sources sprung harder than inputs, shelf-packs
the clusters, and returns graph positions + drawn edges + an orphan list.
ClientScreen branches the layout call and draw passes on viewMode (skips
parent-line and peer-error passes in Flow view), the avatar hosts the orphan
gutter (tap → editor), and nodes that newly gain a flow position play the
existing entrance animation so a wired-up orphan pops into its cluster.
computeFlowLayout(nodes)) is split out from the
manager-reading wrapper so it’s covered by NodeFlowLayoutTest without a
ClientNodeManager, filesystem, or wall-clock — the canonical
parameterise-the-seam shape. Connected-component grouping, container
exclusion, orphan identification, peer-id resolution, dropped-dangling-edge
behaviour, and the sources-tighter-than-inputs weighting all have assertions.CanvasViewMode was
initially named ViewMode, which silently resolved against the pre-existing
ViewMode { ROW, EDIT } enum and produced “unresolved Server/Flow” errors
rather than a redeclaration error at every use site. When adding a
package-level type, grep the package for the bare name first.design.md so they aren’t later read
as regressions. The toggle/Flow rendering is UI-only and not MCP-observable,
so it is not Ghost-verifiable (skip needs-qa-verify).