Skip to content

Page Structure & Information Architecture

Overview

This document defines the information architecture for the web dashboard: the pages, how they are reached, and which backend domain each one is a view of. It is held against the backend API surface (controllers and WebSocket channels) and the Warm Ops identity described in Brand & UX.

Guiding principle: every page maps to a real backend domain with live data. No user-facing placeholder pages and no "under construction" stubs.


Page List

Primary Navigation

High-frequency destinations, always visible in the sidebar.

Dashboard (/)

Org overview: metric tiles (tasks, active agents, spend, failed runs), the Org Pulse panel, recent activity widget, pending approvals, and a budget snapshot with sparkline. The central "what is the company doing, and what is stopping it?" view.

Org Pulse answers the question the dashboard's own numbers raise, in two halves. Running now names the work in flight from the cockpit's live snapshot, which resolves each row's agent name and task title at the read boundary. Beside it sit the queue depth and the idle headcount, both from the overview. Queue depth is work waiting on capacity: filed, or assigned and not yet started. It deliberately excludes a review session (dispatched work, not backlog), a blocked task (the other half of the panel counts it, and counting it twice reads as more work waiting than there is), and anything waiting on a person (awaiting_input, auth_required, interrupted, suspended), because hiring or unblocking does not move those. Blocking progress merges, worst first: runs that produced nothing (from the outcome counts), tasks parked at BLOCKED grouped by blocked_reason and phrased as the answer each park waits on, and every subsystem not in the active phase, rendering the detail and waiting_on that GET /subsystems exists to report. An empty second half is a real all-clear, never a zero.

The dashboard deliberately carries no per-department health rollup. Department health is a terminal task-outcome success rate, so a department that has run nothing has none to report, and an org that is stuck is exactly the org with nothing to average: the rollup goes blank at the moment an operator most needs to know why nothing is happening. The per-department numbers live where they are readable instead: the Org Chart's cards carry each department's agents, active count and 7-day cost, served by GET /departments/{name}/health.

The Live Activity feed and the outcome tile (succeeded / empty / failed) are fed by real task-lifecycle metrics, so a failed or empty run surfaces distinctly instead of hiding behind a generic in-review count. No feed row prints an identifier: an ActivityEvent's description carries none, its references travel in related_ids, and actor_name / subject_title are resolved per page via api/_read_names (the same helpers GET /cockpit/* uses). A reference nothing resolves leaves the field null and the dashboard supplies its own words.

API endpoints: GET /analytics/overview, GET /analytics/forecast, GET /budget/config, GET /activities, GET /cockpit/snapshot, GET /subsystems, GET /tasks?status=blocked WS channels: tasks, agents, budget, system, approvals (aggregated into the metric tiles, the Org Pulse panel and the activity feed)

Chat (/chat)

One unified conversation with the organisation, Claude-Code-style: a single composer and transcript, no mode picker. The operator types anything and the org detects intent and responds inline, escalating visibly: a plain answer, a drafted plan handed off to Plan Review, a convened group, or a direct action. Specialists speak inline with their own attribution (transparent multi-voice, opt-out), and the Chief of Staff is the default front door. Direct acting stays fail-closed and buffered. A History drawer resumes a prior conversation; an optional charter side panel drives a charter interview. Intent is classified server-side, so the frontend never pre-classifies the operator's intent. The conversation is also where the org asks: a question a running agent parked on arrives live as an inline card and is answered in place (see The Org Asks), including when no conversation is open. The surface has two transports over one classification: an explain turn streams its answer token-by-token over POST /meta/chat/turn/stream (SSE), while every side-effecting intent (propose / group_convene / act / charter) is deferred on the stream and re-issued against the buffered, idempotent POST /meta/chat/turn so an acting turn only ever runs once.

API endpoints: POST /meta/chat/turn (buffered), POST /meta/chat/turn/stream (SSE for explain; defers other intents), GET /meta/chat/conversations, GET /meta/chat/conversations/{id}, GET /meta/chat/questions, POST /meta/chat/questions/{approval_id}/answer, POST /meta/chat/questions/{approval_id}/decline, GET /agents/active WS channels: approvals (a parked agent question arrives live; SSE still carries the streamed explain answer)

Org Chart (/org)

Living org visualisation with real-time agent status. Two view modes toggled via toolbar:

  • Hierarchy view (default): Dagre-based hierarchical layout with CEO, departments, teams, and agents carrying status dots and health overlays. Supports drag-drop agent reassignment between departments (optimistic update with rollback on API failure, ARIA live announcements, drop zone highlight with accent border). Left-to-right sibling order is the operator's own: the chart reads departments, each department's agents, and each department's teams in the order the reorder endpoints persist, so the Hierarchy view and Edit Organisation always agree. The chart flows top to bottom, and every set of three or more siblings wraps into a block rather than a line: min(n, ceil(sqrt(n))) columns, so three read as two and one, four as two and two, nine as three by three, and the departments hanging off the root fill a block centred on it instead of one endless row. The rule is unconditional rather than triggered by a width budget, because a budget only ever answers "not yet" until the row is already too wide to read. Fill order is the operator's own, row by row, so the Hierarchy view and Edit Organisation still agree. Connectors are routed from the placed geometry rather than per edge: siblings share one trunk, each row of a block gets its own bus, and a row below the first is reached by a riser dropped through a column gutter, so no line crosses a card. The whole layout is anchored on the root department, so adding or removing an agent or a department extends the chart outward rather than shifting what the operator is looking at.

  • Communication view: Force-directed layout (d3-force) showing inter-agent communication patterns. Edge thickness encodes message volume, animated dashes encode frequency. Data sourced from GET /messages with client-side aggregation. Smooth 400ms animated transition between views.

A department card's header bands (title, budget, status dots, stats) and its "+ Add agent" footer are sized from one shared model (pages/org/card-metrics.ts) that the card renders from and the layout reserves from, so the space held for the chrome is the space it occupies. Two descriptions of the same bands would be two owners of one fact, and the cheaper one to keep correct is the one that never reaches the screen: whatever the layout under-reserves, the card overlaps.

Click agent nodes to open Agent Detail panel.

"Edit Organisation" button enters form-based edit mode (/org/edit) with sub-tabs: General (name, autonomy level, monthly budget, communication pattern), Agents (card grid with add/edit/delete), Departments (card grid with CRUD; nested team editing via the Department Edit drawer with create/rename/delete/reorder teams using @dnd-kit; reporting/policies editing remains deferred). This is the former Company page merged into the Org Chart; same data domain, one destination.

API endpoints: GET /company, GET /company/departments, GET /departments, GET /departments/{name}, GET /departments/{name}/health, GET /agents, GET /agents/{agent_id}, GET /messages (communication view), PATCH /agents/{agent_id} (drag-drop reassignment in hierarchy view). Edit mode adds: PATCH /company, POST /departments, PATCH /departments/{name}, DELETE /departments/{name}, POST /company/reorder-departments, POST /agents, DELETE /agents/{agent_id}, POST /departments/{name}/reorder-agents, POST /departments/{name}/teams, PATCH /departments/{name}/teams/{team_name}, DELETE /departments/{name}/teams/{team_name}, PATCH /departments/{name}/teams/reorder. WS channels: agents (status changes, hired/fired). Communication view uses REST polling for message data (not WS).

Task Board (/tasks)

Kanban view (default) and list view toggle. Filter by status, assignee, department. Task cards show title, assignee, status, priority. Click opens task detail with full context, state transition buttons, and "Coordinate" action (triggers multi-agent coordination via /tasks/{id}/coordinate).

A project filter dropdown narrows the board; the Projects page is the full view of the same domain.

POST /tasks is a board-entry handoff: the controller routes the filing through TaskBoardEntryAdapter and returns HTTP 202 with TaskBoardSubmissionResponse (correlation_id, title, project, status: "submitted"). The spine creates the task inside its background intake phase; the board UI subscribes to the tasks WS channel and inserts the spine-created task on the matching task.created event correlated by correlation_id. Empty-company (no provider / no adapter) returns 409 AgentRuntimeNotConfiguredError. Board column moves remain pure status walks of the spine-created task.

API endpoints: GET /tasks, GET /tasks/{id}, POST /tasks (202), PATCH /tasks/{id}, POST /tasks/{id}/transition, POST /tasks/{id}/cancel, DELETE /tasks/{id}, POST /tasks/{id}/coordinate WS channels: tasks

Budget (/budget)

P&L management dashboard, not a billing tab. Current period spend vs budget, per-agent cost breakdown, per-department rollups, per-prompt-purpose cost and latency breakdown, trend lines, cost anomaly highlights. Forecast sub-view (/budget/forecast) shows projected spend trajectories from the analytics engine.

API endpoints: GET /budget/config, GET /budget/records, GET /budget/agents/{id}, GET /budget/call-analytics, GET /budget/prompt-class-breakdown, GET /analytics/overview, GET /analytics/trends, GET /analytics/forecast, POST /budget/forecast, GET /budget/forecasts/{id}, POST /budget/forecasts/{id}/approve, POST /budget/forecasts/{id}/reject, POST /budget/forecasts/{id}/raise_ceiling, GET /budget/pareto WS channels: budget

Approvals (/approvals)

Pending decisions queue: agents are blocked waiting for human action, so this is the highest-urgency page. Risk-level grouping with collapsible sections, urgency countdown indicators, batch select with approve/reject actions, detail drawer with approval timeline and metadata, filter bar with URL-synced state. Sidebar badge shows live pending count. Plan reviews are excluded from this generic inbox (a source filter): a plan review is decision-gathering, not a binary approval, so it has its own surface and badge on Plan Review.

Each row is evidence-backed and failure-aware: it shows the resolved task title, project, and agent name (never raw UUIDs), a run-outcome badge (succeeded / empty / failed), and the produced-artifact set in the detail drawer. A failed run is styled unmistakably (danger surface) and never as a routine low-risk completion; its buttons relabel Approve/Reject to Acknowledge/Retry (approve acknowledges the failure and leaves the task failed, reject retries it). While an approved task executes, the detail view streams live execution progress (start, tool-call by tool-call, finish/fail) from the task's AG-UI SSE stream, so the completion review is no longer a surprise.

API endpoints: GET /approvals, GET /approvals/{id}, POST /approvals/{id}/approve, POST /approvals/{id}/reject WS channels: approvals

Plan Review (/plans)

Durable-plan review inbox with its own red nav badge (pending plan-review count): when the plan-approval gate is enabled, the decomposed plan for an objective lands here for a human decision before any team builds. The list surfaces plans awaiting review first, then the rest by recency, with client-side status filtering across the whole set. The detail page (/plans/:planId) shows the plan's items and lets an operator rework them (title, description, owner, complexity, stakes), send the plan back for changes with a note, or approve/reject the whole plan inline (the toolbar resolves the plan's parked approval and drives the canonical /approvals path, so approval stays atomic). Per-item discussion is conversational: a comment on an item is answered inline by the responsible role (the item's owner, else the Chief of Staff), rendered as an attributed agent reply. A disconnected-updates banner shows when the live channel drops. See Plan Review.

The detail page also carries the delivery verdict: once the evaluate stage has judged the initiative, the panel shows each objective criterion with the judge's outcome and evidence, newest judgement first, so a plan parked at EVALUATING explains which criteria failed instead of showing a status and nothing else. It is hidden until a judgement exists.

API endpoints: GET /plans, GET /plans/{id}, PATCH /plans/{id}, DELETE /plans/{id}, POST /plans/{id}/request-changes, GET /plans/{id}/comments, POST /plans/{id}/comments/items/{item_id}, GET /plans/{id}/evaluation, plus POST /approvals/{id}/approve / reject (inline whole-plan decision) WS channels: plans

Mission Control (/mission-control)

Three tabs over one live run, switched in page state rather than in the URL. The live cockpit shows what is executing, with stuck and runaway flags and pause / kill interventions. Steering issues a mid-flight directive that in-flight agents adopt at their next safe boundary, and lists the active directives on a project. The flight recorder pages backwards through an execution's recorded turns, seeks to any one of them, and shows the durable red-team verdict for that run.

API endpoints: GET /cockpit/snapshot, GET /cockpit/flight-recorder/{execution_id}/frames, GET /cockpit/flight-recorder/{execution_id}/seek/{turn_index}, GET /cockpit/flight-recorder/{execution_id}/red-team, POST /cockpit/interventions/pause, POST /cockpit/interventions/kill, POST /cockpit/steering, GET /cockpit/steering?project_id=, POST /cockpit/steering/{directive_id}/supersede WS channels: tasks, agents (the cockpit also refreshes through usePolling, which skips a tick while the live channel is fresh)

Roles (/roles)

The distinct role definitions the organisation staffs, derived client-side from the company configuration rather than read from a backend roles endpoint, since none exists. Each role links to its own version timeline at /roles/{roleName}/versions, which is read-only: it lists versions and shows one, with neither diff nor rollback.

API endpoints: the company read behind the company store, plus the role-version reads WS channels: (none)

Reports (/reports)

Generates and lists periodic organisation reports. A report is requested for a period and then browsed by its generated sections (spending, performance, task completion, risk trends), each of which may be absent when the period holds nothing to report.

API endpoints: GET /reports/periods, POST /reports/generate WS channels: (none)

Meta Loop (/meta)

The self-improvement surface: observed signals, generated proposals, the status of the rules in force, the A/B experiments explorer with its assignment history, and the evolution view. The whole page renders a disabled state when the meta loop is switched off, so the off state is stated plainly rather than left to look like an empty page. Custom operator-defined rules live on their own route at /meta/custom-rules.

API endpoints: GET /meta/config and the proposal, alert, signal, A/B and evolution reads beneath /meta WS channels: (none)

Secondary Navigation

Lower-frequency destinations: the collapsible "Workspace" section, the Integrations group, and the tail section below it.

Agents (/agents)

Agent profiles as card grid. Each card shows name, role, department, status dot, hire date. Filtering by department, level, status. Search by name/role. Sort by name, department, level, status, hire date. Click navigates to the Agent Detail page at /agents/{agentId}.

Agent Detail page (/agents/{agentId}): single scrollable page with these sections:

  • Identity header: Large avatar, name, role, department badge, level badge, status with pulse, autonomy level badge, hire date
  • Prose insights: 1-3 generated narrative sentences from performance data (e.g. "Success rate of 94% across 127 completed tasks")
  • Performance metrics: 2x2 grid of MetricCards (tasks completed, avg completion time, success rate, cost per task) with sparklines
  • Tool badges: Horizontal flex-wrap of permitted tools
  • Career timeline: Vertical timeline with coloured dots (hired=green, promoted=blue, demoted=yellow, fired=red)
  • Task history: Gantt-style horizontal bars sorted by time, type-coloured, pulse on in-progress tasks, duration labels
  • Activity log: Paginated chronological event list with type icons, descriptions, timestamps

Deferred to future iteration: Spending breakdown and tabbed layout (Access tab).

API endpoints: GET /agents, GET /agents/{agent_id}, GET /agents/{agent_id}/performance, GET /agents/{agent_id}/activity, GET /agents/{agent_id}/history, GET /agents/{agent_id}/health WS channels: agents, tasks (detail page)

The per-agent autonomy endpoints (GET / POST /agents/{agent_id}/autonomy) exist on the backend and have a typed client, but no page calls them. Per-initiative oversight is set on the Project detail page instead. A per-agent control on this page is intent, not shipped.

Projects (/projects)

Project list with card grid, search, and status filter. "Create Project" button opens a slide-in drawer with name, description, team (tag input), lead, deadline, and budget fields. Each card shows status badge, description, budget, team size, and deadline.

Detail page (/projects/{projectId}) is the initiative cockpit: project header with status badge and key metrics, a plan-progress section (plan status, per-item task status, done / failed / blocked counts, and the critical path through the plan's item DAG), team section with avatar grid and lead badge, an oversight-mode control (sets the initiative's operator-set autonomy tier), and a linked task list with status indicators. Progress is computed server-side and served whole by GET /projects/{id}/progress, so the same view is reachable by any API client. See Project lifecycle.

Living-documentation page (/projects/{projectId}/docs, optional /{slug}) is the per-project wiki: a two-column layout with a doc-list sidebar (type-filter chips for status report / deliverable / knowledge note / codebase analysis / run narrative) and a DocViewer that renders a LivingDocument's typed blocks one renderer per block kind. Docs are written by agents (tools + MCP), git-versioned on the synthorg/docs branch, and chunked into the PROJECT_DOC memory namespace for retrieval. See Living Documentation.

Features:

  • Card grid: responsive 3/2/1 column layout with hover effects, stagger animation
  • Search: client-side filtering by name, description, and ID
  • Status filter: dropdown filtering by project status (planning, active, integrating, evaluating, on_hold, completed, cancelled)
  • Create drawer: 6-field form with validation, optimistic state update
  • Team section: avatar grid with links to agent detail pages, lead badge
  • Oversight mode: sets the initiative's operator-set autonomy tier the SecOps gate resolves against; the gate-off full option is CEO-only and confirmed
  • Task list: linked tasks with status indicators and assignee display
  • Plan progress: per-item task status, done / failed / blocked counts, and critical-path highlighting for the plan the project is executing

API endpoints: GET /projects, GET /projects/{id}, GET /projects/{id}/progress, POST /projects, PATCH /projects/{id}/autonomy-mode, DELETE /projects/{id}, GET /projects/{id}/docs, GET /projects/{id}/docs/{slug}, GET /projects/{id}/docs/{slug}/history, GET /projects/{id}/docs/search WS channels: projects (emits project.created, project.deleted, project.autonomy_mode_changed), tasks, plans (a plan status change refreshes the progress section)

Artifacts (/artifacts)

Artifact list with card grid, search, and filters for type, content type, agent, task, and project. Each card shows path, type badge, content type badge, file size, creation time, and creator.

Detail page (/artifacts/{artifactId}) shows metadata grid (type, size, content type, path, task, creator, project), inline content preview (text via CodeMirror with syntax highlighting, images as blob URLs), download button, and delete with confirmation dialog.

Features:

  • Card grid: responsive 3/2/1 column layout with hover effects, stagger animation
  • Search: client-side filtering by path, description, and ID
  • Type filter: dropdown for artifact type (code, tests, documentation)
  • Content type filter: dropdown for MIME type prefix (text, image, JSON, PDF, application)
  • Agent/task/project filters: text inputs for filtering by creator, task ID, and project ID
  • Content preview: text content in CodeMirror (JSON/YAML syntax highlighting), image content as inline preview, other types show "Preview not available" with download action
  • File size display: human-readable size on cards and detail page, "No content" for 0 bytes
  • Download: blob download with filename derived from artifact path
  • Delete: confirmation dialog, toast notification, redirect to list

API endpoints: GET /artifacts, GET /artifacts/{id}, POST /artifacts, DELETE /artifacts/{id}, GET /artifacts/{id}/content, PUT /artifacts/{id}/content WS channels: artifacts

Messages (/messages)

Channel-filtered message feed for inspecting agent-to-agent communications. Two-column layout: channel list sidebar on the left, main message feed on the right. This is an investigative tool: users examine delegation chains, audit coordination, debug inter-agent communication. Not a chat interface.

Features:

  • Channel sidebar: grouped by type (topic/direct/broadcast), unread badge per channel, active channel highlight
  • Message feed: sender avatar + name, message type badge, priority indicator (high/urgent), relative timestamps
  • Timestamp grouping: messages grouped by date with "Today"/"Yesterday"/date dividers
  • Threading: messages with the same task_id grouped visually with expand/collapse
  • Client-side filtering: type, priority, and text search with URL-synced filter pills
  • Detail drawer: right-side panel showing full message metadata (channel, sender, task/project links, token usage, cost, extra key-value pairs, attachments)
  • Real-time: WebSocket-driven new message arrival with auto-scroll-to-bottom (when user is near bottom)
  • Pagination: "Load earlier messages" button for fetching older messages

URL params: ?channel={name}, ?type={messageType}, ?priority={level}, ?search={query}, ?message={id} (detail drawer). All filter params are optional and combinable independently; channel is not required for type/priority/search filters.

API endpoints: GET /messages, GET /messages/channels WS channels: messages

Providers (/providers)

LLM provider management. CRUD cards for configured providers with health status display (up/degraded/down/unknown) and 24-hour health metrics (average response time, error rate percentage, call count, total tokens, cost). Connection test button. Preset-based creation flow with subscription auth support requiring ToS acceptance for applicable providers. Model auto-discovery with capability badges (tools, vision, streaming) per model. Provider list supports filtering and sorting by health status, name, and model count. Provider detail/edit at /providers/{name}.

No WebSocket subscription; provider changes are low-frequency admin operations, so the page refreshes through the shared usePolling hook.

API endpoints: GET /providers, GET /providers/{name}, GET /providers/{name}/models, GET /providers/{name}/health, POST /providers, PUT /providers/{name}, DELETE /providers/{name}, POST /providers/{name}/test, GET /providers/presets, POST /providers/from-preset, POST /providers/{name}/discover-models, POST /providers/probe-local, GET /providers/discovery-policy, POST /providers/discovery-policy/entries, POST /providers/discovery-policy/remove-entry, POST /providers/{name}/models (manual add), POST /providers/{name}/models/sync (bulk sync), POST /providers/{name}/credentials/rotate, GET /providers/{name}/rate-limits, PATCH /providers/{name}/rate-limits, GET /providers/presets/{preset_name}/override, PATCH /providers/presets/{preset_name}/override, DELETE /providers/presets/{preset_name}/override, GET /providers/{name}/audit

Workflows (/workflows)

Workflow definition list with card grid, search, and type filter. "Create Workflow" button opens a creation drawer with blank or blueprint picker mode (5 starter blueprints). Each card shows name, description, node count, edge count, creation time, and last-modified time. Actions per card: duplicate, delete (with confirmation dialog). Click navigates to the Workflow Editor at /workflows/editor?id={workflowId}.

API endpoints: GET /workflows, POST /workflows, DELETE /workflows/{id}, GET /workflows/blueprints, POST /workflows/from-blueprint WS channels: (none)

Workflow Editor (/workflows/editor)

Visual workflow designer: a DAG-based editor for creating and editing workflow definitions that orchestrate multi-step agent pipelines. Operators build workflows by placing nodes on a canvas, connecting them with edges, and configuring each node's properties via a side drawer.

Key features:

  • 8 node types: start, end, task, agent_assignment, conditional, parallel_split, parallel_join, subworkflow
  • 4 edge types: sequential, conditional_true, conditional_false, parallel_branch
  • Undo/redo: full history stack for node/edge additions, deletions, moves, and config changes
  • YAML preview: live read-only YAML export of the current workflow graph
  • Bidirectional YAML editing: toggle between visual and YAML editor modes; parse YAML back into the visual graph with inline error/warning display and position preservation
  • Validation: client-side structural validation with inline error display
  • Minimap: pannable/zoomable overview of the full graph for navigation in large workflows
  • Copy/paste: clipboard operations for selected node groups with ID remapping and internal edge preservation
  • Condition builder: structured expression editor (Builder mode with field/operator/value rows and AND/OR/NOT logical operators, Advanced mode with free-text) for conditional nodes
  • Workflow selector: switch between saved workflow definitions from the editor toolbar
  • Multi-workflow support: "Save as New" duplicate action, quick-switch between workflows

  • Version history: slide-in drawer listing all saved versions with compare (diff viewer) and restore (rollback) actions per entry

  • Diff viewer: modal overlay showing node changes, edge changes, and metadata changes between any two versions
  • Rollback: restore a previous version's content as a new version (no history lost)

No WebSocket subscription; workflow definitions are persisted via REST and do not require real-time collaboration.

API endpoints: GET /workflows, POST /workflows, GET /workflows/{id}, PATCH /workflows/{id}, DELETE /workflows/{id}, POST /workflows/{id}/validate, POST /workflows/{id}/export, GET /workflows/{id}/versions, GET /workflows/{id}/versions/{version_num}, GET /workflows/{id}/diff?from_version=N&to_version=M, POST /workflows/{id}/rollback WS channels: (none)

Subworkflows (/subworkflows)

Registry listing of reusable subworkflow components. Card grid with search, I/O signature summary (input count / output count), version count, and newest version badge. Click opens a detail drawer showing version history, parent references, and delete action (blocked when parents pin the version).

API endpoints: GET /subworkflows, GET /subworkflows/search?q=, GET /subworkflows/{id}/versions, GET /subworkflows/{id}/versions/{version}, GET /subworkflows/{id}/versions/{version}/parents, POST /subworkflows, DELETE /subworkflows/{id}/versions/{version} WS channels: (none; refreshes via polling, 30s)

Settings (/settings)

Configuration for every setting namespace the backend registry exposes (api, memory, budget, security, coordination, observability, backup, design, and the rest), driven dynamically by the settings schema rather than a fixed list. Navigation uses a horizontal namespace tab bar across the top of the settings page, with each namespace as a clickable tab. Within each namespace, settings are displayed in a single-column layout with sub-group headings, basic/advanced mode, GUI/Code edit toggle (JSON/YAML within Code mode). Each namespace is URL-addressable (/settings/{namespace}) for deep linking from other pages (e.g. Dashboard budget warning links to /settings/budget).

The Code edit mode uses a split-pane diff editor view: the left pane shows the current persisted configuration (read-only), and the right pane is an editable CodeMirror editor for composing changes. This allows operators to see exactly what will change before saving.

Enabling advanced mode for the first time shows a confirmation dialog warning about misconfiguration risk. Both the preference and the fact that the warning has been seen are backend-owned, in the dashboard settings namespace (settings_advanced_mode, settings_advanced_warned), read and written through the dashboard-preferences store. Nothing about them is held in browser storage: the dashboard is a pure API consumer, and a preference the backend cannot see is one no other client can honour.

Dependency indicators are driven by a frontend-maintained SETTING_DEPENDENCIES map in web/src/pages/settings/settings-constants.ts, not by the backend schema. When a controller setting is disabled, its dependent settings display in a muted state.

The observability namespace includes a dedicated Sinks sub-page (/settings/observability/sinks) for managing log sink configuration. The sinks page displays all active sinks (console and file) as cards showing identifier, log level, format, rotation policy, and routing prefixes. Operators can edit sink overrides and define custom sinks with a test-before-save workflow.

The memory namespace includes a dedicated Fine-Tuning sub-page (/settings/memory/fine-tuning) for managing the domain-specific embedding fine-tuning pipeline. The page displays pipeline status (5-stage stepper with live progress bar), run history, preflight validation (dependencies, GPU, documents, disk space), and controls for starting/cancelling fine-tuning runs with optional advanced parameter overrides (epochs, learning rate, batch size). A Checkpoints section lists all fine-tuned model checkpoints with evaluation metrics (NDCG@10, Recall@10), deploy/rollback/delete actions (deploy activates the checkpoint and updates embedder settings; rollback restores the pre-deployment backup config; delete is rejected for the active checkpoint), and an active-checkpoint indicator. All checkpoint actions require CEO or SYSTEM role.

The backup namespace covers backup configuration settings (schedule, retention, path) and links to a dedicated Admin Backups page at /admin/backups (a standalone admin route, reached via a Settings action card from the backup namespace). That page surfaces the full backup lifecycle: create, cursor-paginated list, restore (which swaps the database underneath the process, so the notice says to restart it), and delete.

System-managed settings (e.g. api/setup_complete) are hidden from the GUI. Settings the deployment fixes (compose_set: the container was created with the value, a dashboard write is rejected) are moved out of the inline groups into a per-namespace collapsed "Advanced · set by the deployment" disclosure, marked read-only and badged, so an operator can inspect the value without mistaking an enabled-looking input for something editable. This is distinct from the basic/advanced visibility toggle above. Every setting outside that disclosure applies without a restart once its consumer is wired, on the next call for a per-operation read and on the next dispatch poll for a subscriber-applied one; there is no third state and no restart notice.

API endpoints: GET /settings/_schema, GET /settings/_schema/{ns}, GET /settings, GET /settings/{ns}, GET /settings/{ns}/{key}, PUT /settings/{ns}/{key}, DELETE /settings/{ns}/{key}, GET /settings/observability/sinks, POST /settings/observability/sinks/_test, GET /settings/security/export, POST /settings/security/import, GET /security/audit, GET /coordination/metrics, POST /admin/backups, GET /admin/backups, GET /admin/backups/{id}, DELETE /admin/backups/{id}, POST /admin/backups/restore WS channels: system (system-level notifications)

Documentation (/docs/)

Static HTML served by Caddy, not a React page. The site is built by zensical from mkdocs.yml with the Material theme; the /docs/ Caddy handle block serves the pre-built output directly, bypassing the SPA's try_files fallback. The sidebar "Docs" link renders a plain <a href> for full-page navigation instead of a React Router <NavLink>, and the site's own search, navigation and dark mode work independently of the React app. Theme colours are customised through docs/overrides/extra.css to match the dashboard design system.

API endpoints: (none; static HTML served by Caddy) WS channels: (none)

Standalone Pages

Not in sidebar navigation.

Login (/login)

Full-page authentication. JWT-based. On success, redirects to / (Dashboard) or /setup if setup is not complete (based on GET /setup/status).

API endpoints: POST /auth/setup, POST /auth/login, GET /setup/status, GET /auth/sessions, DELETE /auth/sessions/{session_id}, POST /auth/logout

Setup Wizard (/setup)

Multi-step first-run flow. After account creation (conditional), a mode selection gate asks the user to choose Guided Setup (recommended, full wizard) or Quick Setup (minimal: provider + company name, configure rest later in Settings). Providers are configured before company creation and agents so model assignment is available downstream. Each step is URL-addressable (/setup/{step}). The mode selection step is hidden from the progress bar. Redirects to / if setup is already complete.

Step Route Guided Quick
Account /setup/account conditional conditional
Mode selection /setup/mode yes (hidden from progress) yes (hidden from progress)
Template /setup/template yes no
Providers /setup/providers yes yes
Company /setup/company yes yes
Agents /setup/agents yes no
Capabilities /setup/capabilities yes no
Theme /setup/theme yes no
Review (Complete) /setup/complete yes yes

Agents vs Capabilities split: the Agents step is the agent roster only (per-agent name and model assignment, plus the org chart). All org-wide model defaults and feature toggles live on the Capabilities step: a Models section at the top carries the per-feature model pickers (coordination, embedding, research, Chief-of-Staff chat, request-work, concern-routing, run-narrative, and project-charter; the research picker is shown only while research is enabled), one per per-feature model whose live default is blank so setup provisions every one, followed by grouped capability toggles (Conversational, Knowledge & research on by default; Automation, External network egress, Acts on your behalf collapsed and off). Settings that only take effect on the next server start are not badged in the wizard (they apply when the org first boots).

Provider step layout (web/src/pages/setup/ProvidersStep.tsx): a three-section picker reused on both the wizard and the Settings → Providers page. (a) Cloud providers -- a logo-and-name grid for hosted providers; click a card to open the credential form pre-filled with that preset. (b) Detected on this machine -- only renders when an auto-detect probe found a reachable local server; rows include the URL, model count, and [Add local] / [Add cloud] buttons (the cloud variant is offered when a local preset has a hosted counterpart, e.g. local Ollama → Ollama Cloud). The probe is a single batch call to POST /providers/probe-local issued once on mount, with a manual rescan button. (c) Configure manually -- opens the credential form in custom-endpoint mode. The "Detected" section is hidden entirely when nothing was detected; vLLM is intentionally omitted from auto-detect because its default port (8000) collides with the SynthOrg backend.

API endpoints: GET /setup/status, GET /setup/templates, POST /setup/company, POST /setup/agent, GET /setup/agents, PUT /setup/agents/{agent_index}/name, PUT /setup/agents/{agent_index}/model, POST /setup/agents/{agent_index}/randomize-name, GET /setup/name-locales/available, GET /setup/name-locales, PUT /setup/name-locales, POST /setup/complete

Overlays

Not pages; triggered by user interaction, rendered over current page.

Command Palette

Trigger: Cmd+K (macOS) / Ctrl+K (Windows/Linux) Global search overlay: navigate to any page, search agents by name, search tasks, jump to settings namespaces. Built with cmdk-base (cmdk port on Base UI Dialog).

Notifications Panel

Trigger: Bell icon in sidebar bottom + unread badge Slide-in drawer aggregating system notifications: budget alerts, approval arrivals, agent status changes, system errors. Sources from WS system, approvals, and budget channels.

Category taxonomy: 16 notification categories with routing defaults and severity mappings:

Category Default Route Severity
approvals.pending toast + drawer + browser warning
approvals.expiring toast + drawer warning
approvals.decided drawer only info
budget.threshold toast + drawer warning
budget.exhausted toast + drawer + browser critical
system.error toast + drawer error
system.shutdown toast + drawer + browser critical
agents.hired drawer only info
agents.fired drawer only info
tasks.failed toast + drawer error
tasks.blocked drawer only warning
providers.down toast + drawer + browser error
providers.degraded toast + drawer warning
connection.lost toast only critical
connection.exhausted toast + drawer + browser error

"toast + drawer" categories trigger a brief toast notification in addition to appearing in the drawer. "drawer only" categories appear silently in the drawer and increment the unread badge. Categories with "browser" also fire a browser Notification when the tab is backgrounded. Users can override routing defaults per category via the Notifications section in Settings (per-category toggles for toast, drawer, and browser routes).

Agent Detail Page

Trigger: Click agent in Agents list, Org Chart node, or any agent name link Navigates to a dedicated full page at /agents/{agentId}. Single scrollable page with sections: Identity header, Prose insights, Performance metrics, Tool badges, Career timeline, Task history, Activity log. See the Agents section above for the full layout description.


Sidebar layout (220px expanded, 56px icon rail), defined in web/src/components/layout/SidebarNav.tsx. Four sections, separated by a border; only the middle two carry a label.

  • Brand: Logo / brand mark
  • Primary (no label; the items speak for themselves):
  • Dashboard, LayoutDashboard, /
  • Chat, MessagesSquare, /chat (the unified talk-to-your-org conversation)
  • Mission Control, Radio, /mission-control (live cockpit, steering, flight recorder)
  • Org Chart, GitBranch, /org
  • Roles, Briefcase, /roles
  • Task Board, KanbanSquare, /tasks
  • Budget, DollarSign, /budget
  • Reports, FileText, /reports
  • Approvals, ShieldCheck, /approvals (badge: pending count, excluding plan reviews)
  • Plan Review, ListChecks, /plans (badge: pending plan-review count)
  • Meta Loop, Orbit, /meta
  • Workspace:
  • Agents, Users, /agents
  • Learning, LineChart, /analytics/learning
  • Projects, FolderKanban, /projects
  • Workflows, Workflow, /workflows
  • Subworkflows, Layers, /subworkflows
  • Artifacts, Package, /artifacts
  • Messages, MessageSquare, /messages
  • Providers, Cpu, /providers
  • Ontology, Shapes, /ontology
  • Integrations:
  • Connections, Plug, /connections (external-service credentials plus tunnel providers; the tunnel card mints and reads a tunnel connection and surfaces device-login providers here)
  • OAuth Apps, KeyRound, /integrations/oauth-apps
  • MCP Catalog, LibraryBig, /integrations/mcp-catalog
  • SSRF Violations, ShieldAlert, /providers/ssrf-violations
  • Tail (no label):
  • Docs, BookOpen, /docs/ (external; static HTML, not the SPA)
  • Clients, UserCheck, /clients
  • Request Queue, Inbox, /clients/requests
  • Simulations, Activity, /clients/simulations
  • Fine-Tuning, Sparkles, /settings/memory/fine-tuning
  • Settings, Settings, /settings (does not highlight while Fine-Tuning is active, though that route is nested under it)

The footer sits below the nav: collapse toggle (rendered only in the modes that have one), notifications bell with its badge, the Cmd+K search hint, a connection-status indicator that opens the shared health popover, and the signed-in username with its role and a logout control.

Icon source: Lucide React.

Visual separators: a thin border above Workspace, above Integrations, and above the tail section. The "Workspace" and "Integrations" labels are hidden when the sidebar is collapsed to the icon rail.

Badge behaviours:

  • Approvals: live count of pending approvals from the WS approvals channel, excluding plan reviews, which have their own surface. Red badge, gone at zero.
  • Plan Review: live count of pending plan-review approvals, derived from the same approvals store the Approvals badge reads. Red badge, gone at zero.
  • Messages: the item reserves a badge slot but is wired to a constant zero, so no count renders. Unread-count wiring against the WS messages channel is intent, not shipped.
  • Notifications bell: aggregate unread count across the system, approvals, and budget channels. Gone at zero.

Budget carries no sidebar indicator. A budget threshold reaches the operator through the notifications drawer and its toast, on the budget.threshold and budget.exhausted categories.


URL Routing Map

Application Routes

Route Page Notes
/ Dashboard Home. Redirects to /setup if not configured
/chat Chat One unified conversation with the running system. No mode picker: intent is detected and answered inline (answer / plan draft / group / act), escalating visibly, and surfaces a parked agent question as an answerable card. Backed by POST /meta/chat/turn and /meta/chat/questions
/login Login No sidebar, full page
/setup Setup Wizard No sidebar, full page. Redirects to / if already complete
/setup/:step Setup Wizard step Guided: account (conditional), mode, template, providers, company, agents, capabilities, theme, complete
Quick: account (conditional), mode, providers, company, complete
/org Org Chart Interactive visualisation with Hierarchy (default, drag-drop agent reassignment) and Communication (d3-force) views, 400ms animated transitions
/org/edit Org Chart (edit mode) Form-based company config CRUD. Query params: ?tab=general (default), ?tab=agents, ?tab=departments switch sub-tabs
/org/versions Company versions Read-only version timeline for the company configuration
/roles Roles Distinct role definitions derived from the org structure (no backend GET /roles); each links to its version history
/roles/:roleName/versions Role versions Read-only role-definition version timeline (list + get; no diff/rollback)
/tasks Task Board Kanban default
/tasks?view=list Task Board (list) List view toggle
/tasks?status=:status Task Board (filtered) Filter by task status
/tasks/:taskId Task detail Full-page detail view (direct navigation / deep linking)
/tasks/:taskId/decompose Task decomposition Decomposition view for a single task
/tasks?selected=:taskId Task detail (panel) Panel overlay on board view
/budget Budget P&L dashboard
/budget/forecast Budget forecast Projection charts
/budget/versions Budget versions Read-only version timeline for the budget configuration
/reports Reports Generate and browse periodic organisation reports by period
/mission-control Mission Control Tabbed: live cockpit (stuck/runaway flags, pause/kill), mid-flight steering, and the flight recorder (time-travel seek/replay + durable red-team verdict). The active tab is in-page state, not URL-addressable
/mission-control?executionId=:id Flight recorder (deep link) Auto-loads the execution into the recorder (from a live cockpit agent row); ?taskId=:id is accepted as a fallback key
/mission-control?project=:id Steering (deep link) Seeds the steering project from the URL
/meta Meta Loop Self-improvement surface: signals, proposals, rule status, experiments, and evolution. Renders a disabled state when the meta loop is switched off
/meta/custom-rules Custom Rules Operator-defined rules the meta loop evaluates
/approvals Approvals Pending queue
/approvals?status=:status Approvals (filtered) Filter by approval status
/approvals?risk=:level Approvals (filtered) Filter by risk level
/approvals?type=:type Approvals (filtered) Filter by action type
/approvals?search=:query Approvals (filtered) Search by title/description
/approvals?selected=:id Approvals (detail) Side panel overlay for approval detail
/agents Agents Profile list
/agents/model-recommendations Model recommendations Per-agent model recommendation review. Registered before :agentId so the literal segment is not captured as an agent identifier
/agents/:agentId Agent detail Full page with scrollable sections
/projects Projects List with search/filter
/projects/:projectId Project detail Full page with team, tasks
/projects/:projectId/docs Living docs Per-project wiki: doc list + viewer (status reports, deliverables, knowledge notes, codebase analyses, run narratives)
/projects/:projectId/docs/:slug Living doc detail Full doc view with typed-block rendering
/projects/:projectId/brain Project brain Per-project memory entries
/projects/:projectId/brain/:entryId Project brain entry A single memory entry
/workflows Workflows Card grid list with search, type filter, create (blank or from blueprint)/duplicate/delete
/workflows/editor Workflow Editor Visual DAG editor for workflow definitions (8 node types incl. subworkflow, 4 edge types, YAML preview, validation, version history with diff/rollback)
/workflows/:id/executions Workflow executions Run history for one workflow definition
/workflows/:id/versions Workflow versions Version timeline for one workflow definition with compare and restore actions
/subworkflows Subworkflows Registry card grid with search, I/O signature, version count, and a detail drawer with parents and delete
/artifacts Artifacts List with search/filter
/artifacts/:artifactId Artifact detail Full page with metadata, content preview
/plans Plan Review Durable-plan review inbox with status filter
/plans/:planId Plan detail Item view + rework / request-changes
/messages Messages Channel feed
/messages?channel=:name Messages (filtered) Filtered by channel
/messages?channel=:name&type=:type Messages (filtered) Filtered by message type
/messages?channel=:name&priority=:level Messages (filtered) Filtered by priority
/messages?channel=:name&search=:query Messages (filtered) Search by content/sender
/messages?channel=:name&message=:id Messages (detail) Side drawer for message detail
/providers Providers Provider list
/providers/ssrf-violations SSRF Violations Blocked outbound-request log. Registered before :providerName so the literal segment is not captured as a provider name
/providers/:providerName Provider detail Edit/test provider
/connections Connections External-service credentials and tunnel providers
/integrations/oauth-apps OAuth Apps Registered OAuth applications
/integrations/mcp-catalog MCP Catalog Browsable MCP server catalogue with install
/integrations/webhooks/receipts Webhook receipts Inbound webhook delivery log
/ontology Ontology Entity catalogue plus an admin section (re-derive, sync org memory)
/analytics/coordination Coordination Metrics Per-run efficiency, overhead, and redundancy
/analytics/meta Meta Analytics Cross-deployment patterns
/analytics/learning Learning Learning-curve view over recorded runs
/admin/audit Admin Audit Log Security audit trail
/settings Settings Namespace overview (tab bar navigation)
/settings/:namespace Settings (filtered) Single namespace view via tab bar
/settings/observability/sinks Settings Sinks Observability sink management (card grid with edit/test)
/settings/security/sessions Active Sessions Active-session list with per-row revoke (current device disabled); reached via a Settings action card from the security namespace
/settings/users Users Operator account administration
/settings/memory/fine-tuning Fine-Tuning Embedding fine-tuning pipeline management (status, run history, preflight checks, start/cancel)
/admin/backups Admin Backups System backup lifecycle: create, cursor-paginated list, restore (restart notice), delete; reached via a Settings action card from the backup namespace
/clients Client List Synthetic-client roster with search/filter
/clients/:clientId Client Detail Per-client profile, request history, satisfaction
/clients/requests Request Queue Client-request intake lifecycle (submit, scope, approve, reject). Approve returns 202; the request runs through the work pipeline in the background and reaches its terminal state asynchronously
/clients/simulations Simulation Dashboard Simulation run list, start, detail, cancel
/clients/reviews/:taskId Review Pipeline Per-task review-pipeline stage progress and decisions
/docs/ Documentation Static MkDocs HTML served by Caddy (bypasses React Router)
* 404 Not Found Catch-all

Route Guards

Rule Behaviour
No JWT token Redirect to /login (all routes except /login and /setup)
Setup not complete Redirect to /setup (all routes except /login and /setup)
Setup already complete Redirect to / (when navigating to /setup)
/login with valid JWT Redirect to /

WebSocket Channel Subscription Map

Single WebSocket connection per session, established after login. Each page subscribes only to the channels it needs (see table below). Events are dispatched client-side to Zustand stores based on channel.

Page Channels Events of Interest
Dashboard tasks, agents, budget, system, approvals All; aggregated into health indicators, activity feed, badge counts
Org Chart (hierarchy) agents Agent hired/fired, status changes
Org Chart (communication) agents Agent status changes. Message data via REST polling (GET /messages)
Org Chart (edit mode) agents Agent hired/fired (triggers config refresh)
Task Board tasks Task created/updated/transitioned/cancelled
Budget budget Cost records added, budget alerts
Approvals approvals Approval submitted/approved/rejected/expired
Agents (list) agents Agent status changes
Agents (detail) agents, tasks Agent status and task changes for selected agent
Messages messages New messages sent
Projects (list) projects Project creation events
Projects (detail) projects, tasks Project and task changes
Artifacts (list) artifacts Artifact creation, deletion, upload events
Artifacts (detail) artifacts Artifact changes for selected artifact
Plan Review (list + detail) plans Plan rework and request-changes events
Mission Control tasks, agents Live cockpit rows; usePolling backs the snapshot and skips a tick while the channel is fresh
Providers (none) N/A; refreshes via usePolling
Workflows (list) (none) N/A
Subworkflows (none) N/A; refreshes via usePolling every 30s
Reports (none) N/A; a report is generated on request
Roles (none) N/A; derived from the company store
Meta Loop (none) N/A
Workflow Editor (none) N/A; REST API only, no real-time collaboration
Settings (none) N/A; a write applies live, so there is nothing to be told about later
Notifications panel system, approvals, budget System errors, new approvals, budget alerts

Global subscriptions (active regardless of current page):

  • system: Connection status, shutdown notices
  • approvals: Badge count for sidebar
  • budget: Threshold alert for sidebar indicator
  • messages: inter-agent message traffic. The sidebar unread count it was intended to feed is not wired; the Messages badge reads a constant zero

Responsive Scope

Desktop-first with minimal tablet support. Mobile layout is not in scope.

Breakpoint Sidebar Content Rationale
>=1280px Full (220px) Multi-column layouts Standard desktop
1024--1279px Auto-collapses to icon rail (56px) Full width minus rail Smaller desktops, split-screen
768--1023px Hidden (hamburger toggle, 240px overlay) Single column Tablet landscape
<768px Hidden "Use desktop or CLI" message Not designed for mobile; Go CLI covers quick-check use cases

At tablet (768-1023px), the sidebar hamburger trigger is rendered in the StatusBar (top bar), not in the sidebar itself (which is hidden at that breakpoint). The overlay sidebar uses the shared Drawer component (role="dialog", aria-modal="true") with a blurred semi-transparent backdrop and auto-closes on navigation.

The density system (Dense/Balanced/Medium/Sparse from Brand & UX) provides additional user control over information density at any breakpoint.


The rationale for the activity-feed widget, the dedicated Messages page, and the merged Org Chart / Company view lives in the Architecture Decision Log.


Controller-to-Page Map

Where each principal backend domain surfaces. src/synthorg/api/controllers/__init__.py is the authority on what exists; the registry holds considerably more controllers than the rows below, because a domain is often split across several (providers, settings, setup and the version-history family each span a group). A controller absent here is not necessarily an orphan, but a page absent here is a gap.

Controller Page
HealthController Sidebar (connection status dot)
AuthController Login
SetupController Setup Wizard
CompanyController Org Chart
DepartmentController Org Chart
ActivityController Dashboard
AgentController Agents, Org Chart
TaskController Task Board
BoardController Task Board (WIP-limited Kanban view: GET /board, POST /board/move)
MessageController Messages
BudgetController Budget, Dashboard
ForecastBudgetController Budget forecast (/budget/forecast: approve / reject / raise-ceiling on a brief's projected spend)
AnalyticsController Dashboard, Budget
ProviderController Providers
ApprovalsController Approvals, Dashboard
SettingsController Settings
BackupController Admin Backups page (/admin/backups)
AutonomyController No page. Per-initiative oversight is set on Project detail; the per-agent endpoints are unconsumed
CoordinationController Task Board (task detail action)
CoordinationMetricsController Coordination Metrics page (per-run efficiency / overhead / redundancy table)
ExperimentsController Meta page (read-only Experiments explorer: variants + assignment history)
MetaAnalyticsController Meta Analytics page (Cross-deployment patterns section)
OntologyController / OntologyAdminController Ontology page (entity catalogue + Admin section: re-derive, sync org memory)
InterruptController Mission Control (offline interrupts fallback panel)
EventStreamController Mission Control (per-task AG-UI SSE at /events/stream) + all pages (session-less dashboard SSE fallback at /events/dashboard when the WebSocket is proxy-blocked)
MemoryEntriesController Agent Detail page (memory administration: delete entry, CEO/SYSTEM only)
AuditController Settings (security namespace)
ProjectController Projects page (list, detail, create), Task Board (project filter)
ArtifactController Artifacts page (list, detail, content preview, download)
PlanController Plan Review page (list, detail, rework, request-changes)
WorkflowController Workflows, Workflow Editor
WorkflowVersionController Workflows, Workflow Editor
ClientController Client List, Client Detail
RequestController Request Queue
SimulationController Simulation Dashboard
ReviewController Review Pipeline
ReportsController Reports page (/reports)
MetaController Meta Loop page (/meta)
CustomRuleController Custom Rules page (/meta/custom-rules)
LearningController Learning page (/analytics/learning)
ConnectionsController / TunnelController Connections page (/connections)
OAuthController OAuth Apps page (/integrations/oauth-apps)
MCPCatalogController MCP Catalog page (/integrations/mcp-catalog)
WebhooksActivityController Webhook receipts page (/integrations/webhooks/receipts)
SsrfViolationController SSRF Violations page (/providers/ssrf-violations)
RoleVersionController Roles page and its version timeline
ProjectDocsController Living documentation (/projects/{id}/docs)
ProjectBrainController Project brain (/projects/{id}/brain)
DecompositionController Task decomposition view (/tasks/{id}/decompose)
CockpitController / SteeringController Mission Control
WorkflowExecutionController Workflow executions (/workflows/{id}/executions)
UserController / UserOrgRolesController Users page (/settings/users)
MemoryFineTuneController Fine-Tuning page (/settings/memory/fine-tuning)
TurnController / ChatQuestionsController / ConversationHistoryController / CharterController Chat

Design Principle Compliance

How this page structure supports the dashboard's ten design principles:

# Principle How the structure supports it
1 Data is never just a number Dashboard: sparklines + deltas via /analytics/overview (7-day trend). Budget: forecast projections. Agent detail: career arc narrative
2 Real-time means visible WS subscription map ensures every data-bearing page has live updates. Sidebar badges update in real time
3 Navigation recedes, content shines Collapsible sidebar (220px to 56px). No persistent drawers competing with content
4 Status arrives, doesn't flash WS events update Zustand stores; animation profile is "status-driven" (only changed elements animate)
5 Progressive disclosure Dashboard summary to page detail. Agent list to agent detail page. Org chart node to agent detail
6 Keyboard-first Cmd+K command palette. URL-addressable everything for bookmark/share. Arrow key nav in Task Board
7 Typography carries information Geist Mono for metrics/values/agent names. Geist Sans for labels/descriptions
8 Prose alongside metrics Agent detail: prose insights alongside performance metrics. Budget: cost context explanations
9 Every pixel earns its place No placeholder pages. Every page maps to a live backend domain
10 One component, one look Consistent card/panel/badge patterns across all pages via shadcn/ui primitives

Reference Materials

Resource Location
Brand identity, voice rules, and design system Brand & UX
Implementation specifications UX Guidelines
Framework evaluation behind the stack Dashboard Framework Research
Route path constants web/src/router/routes.ts
Registered route table web/src/router/index.tsx
Sidebar navigation web/src/components/layout/SidebarNav.tsx
WebSocket channel definitions src/synthorg/api/channels.py
API controller registry src/synthorg/api/controllers/__init__.py
API surface Human Interaction Layer