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 /messageswith 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
fulloption 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_idgrouped 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.
Navigation Hierarchy¶
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
approvalschannel, 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
messageschannel 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, completeQuick: 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 noticesapprovals: Badge count for sidebarbudget: Threshold alert for sidebar indicatormessages: 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 |