UI Framework & Lexicon (Surface companion)
Reused companion (2026-06 origin). The shell/slot/composition design here is carried forward by Surface Platform. Terminology drift: the “Sanjaya” agent plane is now simply the agent surface (agents are Actors at the seam), and the slot list is superseded by Surface Platform §slots. Where the two disagree, Surface Platform wins.
Adaptive UI Framework & Lexicon
Status: Design decisions from a working grill session. The skeleton is settled; two
forks remain open (route grammar specifics, the canonical role set) and are flagged at the end.
Companion to: Lepton_AI_Native_Operations_Vision.md, Lepton_Infrastructure_Cloud_PRD.md
Reuses: the @vinxi/app-ui shell and the @vinxi/design system.
0. The one-paragraph thesis
The product is a digital twin you operate with agents. The screen is a composition of three planes — a persistent twin Stage in back, the working Surface of lists and details in the middle, and Sanjaya (the agent plane) woven through. It is viewer-, context-, and situation-adaptive: the same route-state renders natively on phone, tablet, desktop, watch, TV, and VR. Every piece of state lives in the URL, so every view is a shareable link. Agents and humans reach the same universal capabilities — there is no agent backdoor.
1. The Lexicon
─ STRUCTURE ────────────────────────────────────────────────────────── Shell Per-surface container that arranges Slots and renders the three planes. One per form factor: PhoneShell, TabletShell, DeskShell, WatchShell, TvShell, VrShell. Slot A canonical named region content flows into (via Portkey): stage · primary · focus · aside · drawer · hud · command · nav · status Portkey The teleport engine (@vinxi/tunnel) that fills Slots. (the motor) Module A top-level route-prefixed section (Fiber · Electric · Plan · Operate). A PRD "Vertical Accelerator" ships as a Module bundle.
─ THE THREE PLANES (back → front) ──────────────────────────────────── Stage The persistent backdrop plane. Usually renders the digital twin (2D/3D). CONDITIONAL: present when you're looking at the world, empty/absent on account/settings screens. Surface Where Workspaces & Compositions dock (the middle Slots). Sanjaya The agent plane — "the one granted sight to see the whole field and narrate it to the one who can't." Proactive, ambient, situation-aware.
─ CONTENT ARCHETYPES (what a screen IS — only two) ─────────────────── Workspace A set of entities + optional focus. (list→detail, inbox, map, board…) Composition A rearrangeable card canvas (dashboards, reports, briefings).
─ RENDERING ────────────────────────────────────────────────────────── Projection How a Workspace's collection draws: map · table · list · cards · board · timeline · chart. SEVERAL live at once, sharing one focus. View The pluggable, registered unit of content placed in a Slot. A Projection, a focus pane, a Sanjaya item, a Composition tile are all Views.
─ DIALS (cross-cutting state, ALL URL-encoded → every state is a link) ─ focus the selected entity (a route segment, never in-memory) altitude detail density: glance → standard → deep time the temporal cursor — point or range; powers playback & compare layers which data overlays render on the Stage (the GIS sense)
─ STAGE ARRANGEMENT ────────────────────────────────────────────────── single · compare · overview+detail · playbackA builder making a new screen answers five small questions and the Shell composes it: Stage or not? which Module? Workspace or Composition? which Projections? which dials? No new layout code. That is the “adding a screen just works” property.
2. The Three Planes
┌─────────────────────────────────────────────┐│ SANJAYA (ambient agent plane) │ proactive items + Copilot;│ ┌─────────────────────────────────────────┐ │ never the whole screen│ │ SURFACE (Workspaces / Compositions) │ │ lists, details, cards —│ │ list = drawer · focus = sheet/panel/card │ │ docked in Slots│ │ │ ││ │ STAGE (persistent digital twin) │ │ 2D/3D world model;│ │ pan/zoom/pitch survive navigation │ │ conditional│ └───────────────────────────────────────────┘ │└─────────────────────────────────────────────────┘The unifying invariant: all three planes are actors on the same route-state. The human
focusing an asset, the Stage flying to it, and Sanjaya deciding to surface it are the same
operation — a change to focus/altitude/time/layers in the URL. That is how “the agent
manipulates the UI” stays inspectable and undoable instead of magic.
Stage presence rule: Stage is present when content is about the world (assets, outages, work, designs); absent when content is about you or the tool (profile, billing, team, API keys). Same Shell, same archetypes — the Stage plane simply isn’t mounted.
- Destinations (you navigated to settings) → Stage unmounts; plain pane.
- Interruptions (a quick popover, an agent panel) → Stage stays mounted, frozen/dimmed behind.
3. The Shell + Slot contract (multi-surface)
A View never knows what surface it’s on. Each Shell renders the canonical Slots in its native idiom. Add a surface = write one Shell; Modules/Views/Workspaces/Sanjaya don’t change.
| Slot | Desk (web) | Phone | Tablet | Watch | TV | VR |
|---|---|---|---|---|---|---|
stage | full-bleed behind panels | full-bleed | full-bleed | — | dominant | spatial plane |
primary/focus | floating/resizable panels | bottom drawer + push pages | drawer or split | one card | side rail | floating planes |
hud (Sanjaya) | corner cards | top toast + sheet | corner/sheet | glance card | lower-third | gaze-anchored |
command | ⌘K palette | search + voice | ⌘K / voice | voice | voice | voice |
nav | sidebar / tabs | bottom bar | sidebar | crown/scroll | remote rail | wrist menu |
status | status bar | thin top | thin top | — | — | — |
The phone is the hardest composition and the heart of the vision (Google-Maps-style): full-bleed Stage + a snap-point bottom drawer (peek→half→full) holding a list Projection + Sanjaya items surfacing as cards over the Stage + bottom-bar Module nav.
4. Archetypes, Projections, Dials
- Workspace = collection + optional focus. Focus is a route segment (e.g.
…/assets/SC-4521), never component state — so it survives share, refresh, and the back button. Web wide → list + focus side-by-side (split); narrow → focus is a sheet or push page; back-to-list is the browser back button, landing at the exact scroll/filter (also in the URL). - Composition = a rearrangeable grid of cards; each card is a portal into a Workspace query
at
glancealtitude. Dashboards/reports/exec briefings are Compositions. - Projection = how the collection draws.
maprenders on the Stage;table/list/cards/ board/timeline/chartrender in a Slot. Multiple Projections can be live simultaneously over one shared focus (select a table row → it highlights on the map → the focus pane opens). - Dials (all in the URL):
focus,altitude(glance→standard→deep — controls density, map detail, and how much Sanjaya says),time(point/range; powers playback + compare-over- time; intrinsic because the data substrate is event-sourced),layers(which overlays on the Stage — GIS sense). - Stage arrangement:
single(default) ·compare(two linked Stages — plan A vs B, as-built vs as-designed) ·overview+detail(locator inset + zoomed main) ·playback(one Stage + the time cursor).
5. Sanjaya — the agent plane
Sanjaya raises three kinds of item, named by what they ask of you:
| Sanjaya raises a… | Autonomy | What it asks of you |
|---|---|---|
| Insight | L0 inform / L1 recommend | nothing — glance if you want; L1 carries a one-tap suggested action |
| Approval | L2 act-with-approval | a decision — parked until you act |
| Action | L3 act-and-inform / L4 autonomous | nothing — already done, logged and undoable |
You converse with Sanjaya through the Copilot (the conversational entry inside the plane).
5.1 The attention model (one rule, every agent obeys it)
attention = (autonomy × blast-radius) damped by situation, with a safety-critical floor| Autonomy | Type | Default attention | Blast-radius escalation |
|---|---|---|---|
| L0 inform | Insight | quiet in Sanjaya’s rail, badge count | — |
| L1 recommend | Insight + action | quiet in rail, one-tap to act | — |
| L2 act-w/approval | Approval | parked, persists till resolved; SLA deadline if any | huge radius → foreground interrupt |
| L3 act-and-inform | Action | brief toast → lands in the log; undoable | huge radius → toast becomes a confirm-window before commit |
| L4 autonomous | Action | log only, no toast | huge radius → forces a toast |
- Situation (
monitoring at desk·heads-down in a task·driving·off-shift) can only damp (defer/batch into a digest, hold non-urgent Approvals, silence toasts) — never amplify. Exception: a safety-critical Insight (gas leak near the tech, energized line) always breaks through. - Per-viewer floor: the operator sets a personal “what always reaches me” subscription. That is how an exec gets the big outage to interrupt — escalation is opt-in per viewer, not something situation does globally.
- A new agent cannot invent a louder way to nag you — it declares only its autonomy level and blast radius; the rule decides the volume.
6. The capability spine (the trust model)
- Capabilities are universal. One registry of what-can-be-done. Humans and Sanjaya reach it through the same door. Add a capability once → both get it. No agent-only code path exists.
- Two front-ends, one registry: the Command bar is the human’s invoker; Sanjaya is the agentic invoker. Same actions underneath.
- RBAC and autonomy are one policy layer over that registry: a human’s role caps what they may invoke; an agent’s autonomy level caps what it may invoke.
- Strict human-equivalence: Sanjaya can only do what an operator could do through the same UI/API. Bulk/fast ops are not agent superpowers — they are first-class batch actions a human can also fire, which Sanjaya merely calls.
- Two action channels, both shared with humans:
- View channel — Sanjaya sets the same
focus/altitude/time/layers/arrangementroute-state a human sets. Its moves are shareable links; back undoes them. - World channel — Sanjaya mutates through the same actor-tagged event log (
actor: sanjaya). Every move is attributable, auditable, replayable, and undoable to the extent the action is reversible (irreversible high-blast actions are already parked behind L2).
- View channel — Sanjaya sets the same
This composes with the event-sourced data substrate (the History/Graph-as-projection model): agent actions are just authored-by-Sanjaya events in the same append-only log humans write to.
7. How this maps to @vinxi/app-ui today
app-ui is a composable shell (Portkey slots, extension Views, the Items collection framework,
Dashboard, command bar, Modules, Rio reactive state). ~65% reusable as-is.
| Our concept | In app-ui today | Action |
|---|---|---|
| Stage | main-canvas fixed slot + commented // MapPortalOut | Build — wire the twin into the reserved slot |
| Surface overlays | floating panels (desk) / drawer+bottom-bar (mobile) via Portkey | Keep; unify under the slot contract |
| Sanjaya | — nothing — | Build — new hud slot + agent View kind |
| Workspace (archetype) | Items framework + panel-page | Keep Items; move focus from modalState → URL |
| Composition | Dashboard (dashboard-page) | Keep |
| Projection | Items viewMode (list/grid) | Generalize to the full set incl. map→Stage |
| Module | Module (route-prefixed sidebar section) | Keep |
| slot engine | Portkey | Keep — it’s the motor |
| Shell | WorkspaceLayout / MobileLayout (two parallel files) | Rename WorkspaceLayout→Shell; collapse to one slot contract, N thin Shells |
Reworks worth noting: the two parallel layout files + divergent slot names won’t scale to
watch/TV/VR (canonicalize the slot contract); focus must leave modalState for the URL;
panel-system.tsx is half-stubbed (shape it, don’t fight it).
8. Design system (@vinxi/design)
“Bloomberg terminal for infrastructure” — rendered in the light theme (the default). Use it precisely.
- Type: Hanken Grotesk (display/body) + Geist Mono (numbers, labels, status).
- Color (LIGHT, default): snow ground
#FBFDFF/ alt#F2F5F9; midnight ink#1A2040(--midnight-deep #14193A); blue#0066E3(--blue-dark #0055C0,--blue-tint #E8F0FE); secondary text in slate#3D4566/ graphite#4F5670/ steel#6B7280/ ash#8E94A6; hairlines--silver #DFE3EA; semantic green#62CA94/ amber#B57E00/ red used sparingly. (A.theme-darkexists — snow→#0B1020, ink→#E8EBF2, blue→#4D8DFF— but light is the default for these mockups.) - Geometry: sharp 1px lines, no rounded corners; corner brackets (SVG L-shapes at
card corners); mono UPPERCASE labels with letter-spacing; eyebrow/numbered section labels;
KPI cells; data tables; status pulses; subtle dot-grid texture
(
radial-gradient(circle, var(--silver) 1px, transparent 1px), ~22px); tight negative letter-spacing on display type; the square Lepton mark (midnight square w/ inset blue square). - Files:
/Users/nikhilsaraf/vinxi/vinxi/design/src/{brand,tokens,base,atoms,components, scale-dashboard,terminal}.css. - Self-contained LIGHT exemplar (study it & lift its
:root):docs/presentation/index.html. The decksexternal.html/internal.htmlare light too.lepton-architecture.htmlis the dark variant — do not use it for these mockups.
9. Open forks (resolve against the first mockups)
- Route grammar — the canonical URL shape encoding
module · workspace · focus · tab · altitude · time · layers · stage-arrangement, including how spatial state (map viewport) is (or isn’t) URL-encoded. Tenant resolved out-of-band (subdomain/session/token), path is tenant-agnostic and identical across apps. - The canonical viewer/role set — candidates: field technician · NOC/control-room operator · planner/designer · executive · customer (self-service) · contractor/vendor. Each viewer × altitude × surface × situation selects the composition.
Viewer × composition matrix (working)
| Viewer / surface | Stage | Surface | Sanjaya |
|---|---|---|---|
| NOC operator, desk | single | drawer(table) + panel(focus) | Insight → Approval |
| Field tech, phone | single | sheet(focus) + drawer(list) | Copilot + Cue cards |
| Planner, desk | compare | composition(BOM/cost cards) | design suggestions |
| Exec, tablet | none (map = one card → expands) | composition(dashboard) | briefing |
| Outage post-mortem | playback | timeline + drawer(list) | root-cause narrative |
| Settings / profile | none | pane | — |