Home Blog

Role tabs and a live Data Analysis monitor

12 June 2026

At a glance — REMIT grew a tabbed, role-based shell over one shared data store, and the first new role — a Data Analysis drill-down — can pop out into its own window and glow as the data changes while you drive the mission next door.

Drilling a Plan into its Baseline by clicking a content-id reference, breadcrumb trail above

The problem

REMIT has been a single screen: one user, one seven-stage lap. But the target system is a command post — many roles (CO, duty officers, SMEs) each looking at the same underlying data through a different lens, updating it in their own scoped ways. We wanted to start making that real without rebuilding the app: introduce role-specific UIs over one central store.

And there was a concrete frustration that crystallised the design: you can’t watch the data update and drive the changes at the same time when both live in one screen.

Options

The strategy

Four moves, all read-only this phase:

  1. Extract the shared context — the one ObjectStore, seam, world, playhead — out of the monolith so every surface imports the same objects.
  2. Declare roles as config: {id, label, status, poppable, mount}. Overview is the original UI (lazy-booted, untouched); five roles are labelled “coming soon”; Data Analysis is the first real alternative projection.
  3. Inject the context into each surface (mount(container, ctx)), so the same surface renders the same live store whether it runs inline or in a popped-out window (where the pop-out passes window.opener.__remit).
  4. Make change visible: because REMIT objects are immutable and content-addressed, “data changed” means new ids appeared. The monitor diffs the store and glows new rows and their type-group header — the same hook future mock feeds will fire on injection.

The results

It stays honest to the architecture: surfaces read via projections (NF1), and the first DEC-61 write is now wired — denying cells in Plan is the application of intel, so it’s shared to the store as an attributed SteeringDelta and shows up live in the monitor (risk appetites stay local — that’s a ranking lens, not shared intel). The roles list stays UI-only config (ADR-0012 §2), but the shared SteeringDelta is modeled in LinkML (Delta + SteeringDelta, generated to TypeScript / JSON Schema / the HTML reference) — data types belong in the source of truth (ADR-0011), not hand-shaped.

Screenshots

Seven role tabs; Overview is the original UI unchanged

The Data Analysis index grouped by object type, with search

Popped out: the monitor runs in its own window while the main window returns to the mission