Skip to content

feat: side-by-side compare view across multiple instances#14

Closed
BenSheridanEdwards wants to merge 1 commit into
offendingcommit:mainfrom
BenSheridanEdwards:feat/compare-view
Closed

feat: side-by-side compare view across multiple instances#14
BenSheridanEdwards wants to merge 1 commit into
offendingcommit:mainfrom
BenSheridanEdwards:feat/compare-view

Conversation

@BenSheridanEdwards
Copy link
Copy Markdown

Why

Multi-instance support landed in #8 — but the interface is still "pick one
active instance at a time." For users running a fleet of self-hosted Honchos
(e.g. one per agent), the question that motivates running them is "how do
my agents' representations of the same person differ?"
— which can't be
answered without flipping between instances and reconciling by memory.

This PR adds a /compare route that renders N columns, one per pinned
instance, so peer representations can be inspected side-by-side without
disturbing the active instance.

What

API layer

  • createScopedClient(instance) — openapi-fetch client bound to a specific
    instance rather than the active one. Sits next to the existing
    client.current pattern (no change to any existing query hook).
  • compareQueries.ts — scoped versions of useWorkspaces, usePeers,
    usePeerRepresentation, usePeerCard. Each accepts an Instance and
    scopes its TanStack Query key by instance.id so caches don't collide
    across columns.

UI

  • /compare route (top-level), search params: instances=<comma-ids> and
    peer=<target-name> for shareable/deep-linkable views.
  • CompareView — header with target-peer input and "Add instance" dropdown
    (only shows instances not already pinned), plus the columns grid.
  • CompareColumn — workspace selector, peer selector, peer representation
    list (top conclusions), and peer card via the existing PeerCardViewer.
    Auto-selects first workspace; prefers the target peer name if it exists
    in that instance, else first peer.
  • Sidebar gets a Compare nav entry between Workspaces and Settings, using
    the Columns2 icon.

Tests

  • scopedClient.test.ts — verifies requests target the instance's baseUrl
    and attach the instance's Bearer token.
  • compare.test.tsx — verifies the empty-state prompt renders when no
    instances are selected.

Out of scope (potential follow-ups)

  • Diff highlighting between columns (semantic diff of conclusion sets)
  • Synchronized scrolling between columns
  • "All peers" view (compare conclusion counts, last-dream times, etc. as a
    fleet-overview dashboard)

Manual verification

Verified against a local fleet of 5 Honcho stacks (one per agent, ports
8001–8005). Each column's queries correctly route to its own instance's
URL (confirmed via PerformanceResourceTiming). The visual layout renders
cleanly with 5 columns side-by-side.

Note: live data fetch requires the Honcho daemons to allow the dev origin
in their CORS config. The existing client.current health check hits
the same CORS path — this PR doesn't change that surface.

Conventions

  • Conventional commit (feat:)
  • TypeScript strict, no any
  • CSS variables for theme colors (no Tailwind color utilities)
  • TanStack Router as never cast at navigate callsites
  • pnpm typecheck, pnpm lint, and the new tests all pass locally

Adds a /compare route that renders N columns, one per pinned Honcho
instance, so the user can see how each instance's representation of a
peer differs without switching the active instance.

- New scoped API client (`createScopedClient`) bound to a specific
  instance rather than the active one. Backs the compare view's queries
  without disturbing the active-instance client used elsewhere.
- New scoped query hooks for workspaces, peers, peer representation,
  and peer card; query keys scoped by instance.id to keep caches
  isolated across columns.
- Compare route stores pinned instance IDs and target peer name in
  URL search params so views are shareable/deep-linkable.
- Sidebar nav gets a Compare entry between Workspaces and Settings.
- Per-column auto-selects the first workspace and prefers the target
  peer name if it exists in that instance, else first peer.

Tests:
- scopedClient: requests target the instance baseUrl + Bearer token
- compare route: empty-state prompt when no instances selected
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant