Orchestrata Ultimate / Specs / 016-vizint-command-center
016-vizint-command-center: VizInt Command Center
The VizInt Command Center is the unified dashboard and personal command center for Orchestrata. Built on the VizInt gadget portal framework (cloned at vizint-ui/), it provides a single browser-based interface where the user can observe, control, and interact with the entire orchestration system in real-time. The Command Center connects to Orchestrata via the SPEC-014 WebSocket Gateway (JSON-RPC 2.0 over WebSocket), presenting every orchestration feature as a composable gadget. The system...
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/016-vizint-command-center/ |
| Status line in the spec | Implemented (Core) + Gadgets Implemented |
| Requirement IDs defined | 294 |
With a @traces citation in src/ |
38 (12.9%) |
With a @traces citation in tests/ |
0 (0.0%) |
| Tracked files | 6 |
| RTM page | 016-vizint-command-center |
Reading this spec
The VizInt Command Center is the unified browser dashboard and personal command center for Orchestrata. Built on the VizInt gadget portal framework, it gives one interface to observe and control the orchestration system in real time, with every orchestration feature presented as a composable gadget. It connects through the WebSocket Gateway of spec 014. Before it, all interaction happened through the CLI or code, and the gateway's real-time data had no consumer.
The scope is fourteen user stories: a project dashboard, session management, a real-time CXP feed, a Volk status panel, Claude chat, a task and goal board, a QA dashboard, an audit trail viewer, a notification center, and gateway session and project handlers (priority 1), plus a knowledge graph explorer, personal productivity gadgets, and theme and layout customization (priority 2). Requirement IDs use the REQ-016- prefix.
The design is stated precisely. The portal runs in the browser as static HTML, JS and CSS with zero-build ES modules. A CommandCenterApp bootstraps five subsystems: a WebSocket bridge, a gadget bridge, state sync, a notification manager and a gadget registry. The gadget bridge translates between local events and gateway JSON-RPC 2.0 calls across five namespaces: session.*, cxp.*, volk.*, knowledge.* and governance.*. State sync replaces localStorage-only persistence with gateway-backed synchronization, debounced at 500ms with last-write-wins conflict resolution. Gateway handlers provide Neo4j-backed async queries with 10 second timeouts.
In the code, the server side is in the gateway handlers: orchestrata_ultimate/gateway/handlers/session, orchestrata_ultimate/gateway/handlers/_session_kg, orchestrata_ultimate/gateway/handlers/projects and orchestrata_ultimate/gateway/handlers/cxp, plus orchestrata_ultimate/knowledge_graph/query_engine. The browser gadgets are JavaScript and are not covered by the Python trace table. The per-requirement view is on the RTM page.
The spec's status line reads Implemented (Core) + Gadgets Implemented. It tracks 6 files and defines 294 requirement IDs. The full text follows below.
Measured coverage is 38 of 294 requirements cited by at least one @traces in src/ (12.9%), spread over 14 modules; the module citing the most of them is orchestrata_ultimate/gateway/handlers/session (8 requirements). In tests/, 0 requirements are cited by a test-side @traces.
Coverage gaps: 256 requirements have no citing symbol. The largest untraced groups are REQ-016-* (256). Untraced means no @traces names the ID; the behaviour may still exist in code that was never annotated. Test-side citations are thinner than code-side ones (0 against 38).
Requirements
Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.
| ID | Done | Requirement | Traced by |
|---|---|---|---|
REQ-016-001 |
yes | ProjectExplorer gadget queries knowledge.nodes for the Project node on mount |
none |
REQ-016-002 |
yes | Gadget displays project name, version, description from Project node properties | none |
REQ-016-003 |
yes | Gadget displays aggregate counts: total files, total classes, total functions, total LOC | none |
REQ-016-004 |
yes | Gadget displays session summary: total sessions, active sessions, last session date | none |
REQ-016-005 |
no | Gadget displays iteration summary: total iterations, last iteration number, gap trend | none |
REQ-016-006 |
no | File tree populated via knowledge.nodes RPC with node_type=File and pagination |
1 |
REQ-016-007 |
no | File tree shows directory hierarchy with expand/collapse toggles | none |
REQ-016-008 |
no | File tree supports keyword search with real-time filtering (debounced 300ms) | none |
REQ-016-009 |
no | Each file entry shows: name, path, class count, function count | none |
REQ-016-010 |
no | Click on file navigates to KGExplorer gadget with file-scoped context | none |
REQ-016-011 |
yes | KG summary displays counts by node type: File, Class, Function, Session, Iteration, Spec | none |
REQ-016-012 |
no | Each count displayed with sparkline trend (last 20 data points) | none |
REQ-016-013 |
no | KG summary auto-refreshes every 60 seconds via gateway subscription | none |
REQ-016-014 |
no | Click on node type count opens KGExplorer filtered to that type | none |
REQ-016-015 |
yes | Recent sessions list (last 10) with: id, date, status badge, duration, achievements | none |
REQ-016-016 |
no | Status badges: active (green pulse), closed (grey), error (red) | none |
REQ-016-017 |
no | Recent iterations list (last 10) with: number, date, gap count, pass/fail indicator | none |
REQ-016-018 |
no | Click on session row opens SessionManager gadget with that session selected | none |
REQ-016-019 |
no | Click on iteration row opens IterationBrowser gadget with that iteration selected | none |
REQ-016-020 |
no | Project metrics refresh on session.events and kernel.events subscriptions |
none |
REQ-016-021 |
yes | SessionManager gadget calls session.list on mount to find active session |
none |
REQ-016-022 |
yes | Active session displayed with: id, goals, portfolio, duration (live timer), status | none |
REQ-016-023 |
yes | Session context displayed: current work description, recent achievements | none |
REQ-016-024 |
yes | Session facts displayed as a scrollable list (last 50 facts) | none |
REQ-016-025 |
yes | "No active session" placeholder shown when no session is active | none |
REQ-016-026 |
yes | "Start Session" button opens dialog: goals (text area), portfolio (dropdown), purpose (text) | none |
REQ-016-027 |
yes | Start Session sends session.open RPC with user-provided parameters |
none |
REQ-016-028 |
yes | Start Session button disabled when a session is already active | none |
REQ-016-029 |
yes | "Close Session" button opens dialog: summary (text area), carryover tasks (checklist) | none |
REQ-016-030 |
yes | Close Session sends session.close RPC with summary and carryover |
none |
REQ-016-031 |
yes | Close Session button disabled when no session is active | none |
REQ-016-032 |
yes | Session open/close results displayed as success/error toast notification | none |
REQ-016-033 |
no | Deferred work items displayed in a prioritized list (critical > high > medium > low) | none |
REQ-016-034 |
no | Each item shows: description, priority badge, status, session added, notes | none |
REQ-016-035 |
no | "Add Item" button opens inline form: description, priority dropdown, notes | none |
REQ-016-036 |
no | Click on item opens inline editor for description, priority, and notes | none |
REQ-016-037 |
no | "Mark Done" button on each item updates status to done | none |
REQ-016-038 |
no | "Remove" button with confirmation dialog for item deletion | 1 |
REQ-016-039 |
no | Deferred work changes sent to gateway for persistence in context.json | 1 |
REQ-016-040 |
no | "Log Work" text input with send button in the session panel | none |
REQ-016-041 |
no | Log work sends description to session context via RPC | none |
REQ-016-042 |
no | Recent work log entries displayed below the input (last 10) | none |
REQ-016-043 |
yes | Gadget subscribes to session.events for real-time updates |
none |
REQ-016-044 |
yes | Session open event updates display to show new active session | none |
REQ-016-045 |
yes | Session close event updates display to show "no active session" | none |
REQ-016-046 |
yes | Session history table accessible via "History" tab | none |
REQ-016-047 |
yes | History table columns: id, date, duration, status, achievements (truncated) | none |
REQ-016-048 |
no | History supports search across achievements and descriptions | none |
REQ-016-049 |
no | History supports date-range filter | none |
REQ-016-050 |
no | Click on history row shows full session detail in a side panel | none |
REQ-016-051 |
yes | CXPFeed gadget subscribes to cxp.traffic via GadgetBridge on mount |
1 |
REQ-016-052 |
yes | Subscription re-established automatically on gateway reconnect | none |
REQ-016-053 |
yes | Gadget unsubscribes from cxp.traffic on unmount |
1 |
REQ-016-054 |
yes | Packets displayed as rows in a scrolling list | none |
REQ-016-055 |
yes | Each row shows: timestamp, from (volk alias), to (volk alias), subject, status, thread_id | none |
REQ-016-056 |
yes | Delivery status color-coded: green (delivered), yellow (pending), red (failed), grey (expired) | none |
REQ-016-057 |
yes | Click on row expands to show full CXP payload (all 11 fields) | none |
REQ-016-058 |
yes | Expanded view shows JSON payload with syntax highlighting | none |
REQ-016-059 |
yes | Maximum 5000 packets retained in memory (oldest discarded) | none |
REQ-016-060 |
yes | Volk filter dropdown (populated from volk.list) for from/to filtering |
none |
REQ-016-061 |
yes | Thread filter text input with debounced search (300ms) | none |
REQ-016-062 |
yes | Subject filter text input supporting glob patterns (e.g., "code_*") | none |
REQ-016-063 |
yes | Delivery status filter dropdown (all, delivered, pending, failed, expired) | none |
REQ-016-064 |
yes | Multiple filters combine with AND semantics | none |
REQ-016-065 |
yes | Active filter count shown in filter bar | none |
REQ-016-066 |
yes | "Clear Filters" button resets all filters | none |
REQ-016-067 |
yes | Filters applied client-side for instant response | none |
REQ-016-068 |
yes | Auto-scroll to bottom for new packets when scrolled to bottom | none |
REQ-016-069 |
yes | Auto-scroll pauses when user scrolls up (manual inspection) | none |
REQ-016-070 |
yes | "Jump to Bottom" floating button appears when paused | none |
REQ-016-071 |
yes | Auto-scroll resumes on "Jump to Bottom" click or manual scroll to bottom | none |
REQ-016-072 |
yes | Packet count badge shows total packets since gadget mount | none |
REQ-016-073 |
yes | Throughput indicator shows packets/sec (rolling 10-second average) | none |
REQ-016-074 |
yes | Filtered packet count shown when filters active (e.g., "42 / 1234") | none |
REQ-016-075 |
yes | VolkStatus gadget calls volk.list on mount to populate initial state |
none |
REQ-016-076 |
yes | Each volk rendered as a card with: alias, role title, health indicator, current task | 1 |
REQ-016-077 |
yes | Health indicator: green circle (healthy), yellow circle (degraded), red circle (unhealthy) | none |
REQ-016-078 |
yes | Current task shown as status text with elapsed time (live timer) | none |
REQ-016-079 |
yes | Idle volks show "Idle" with grey status text | none |
REQ-016-080 |
yes | Gadget subscribes to volk.lifecycle for real-time updates |
none |
REQ-016-081 |
yes | Health changes animate with CSS color transition (300ms fade) | none |
REQ-016-082 |
yes | New volk registration adds card with slide-in animation | none |
REQ-016-083 |
yes | Volk deregistration removes card with fade-out animation | none |
REQ-016-084 |
yes | Task start/complete events update the current task display | none |
REQ-016-085 |
yes | Click on volk card opens detail panel (slide-out right side) | none |
REQ-016-086 |
yes | Detail panel shows: alias, role, capabilities list, protocols, registration time | none |
REQ-016-087 |
yes | Detail panel shows: session_id, resource_usage (tokens, time), last_activity | none |
REQ-016-088 |
yes | Detail panel shows: output artifacts list (files generated, CXP packets sent count) | none |
REQ-016-089 |
no | Detail panel updated in real-time via volk.lifecycle events |
none |
REQ-016-090 |
yes | Default mode: volk cards in a grid (responsive columns based on gadget width) | none |
REQ-016-091 |
no | Compact mode: horizontal bars with color-coded health (for width < 400px) | none |
REQ-016-092 |
no | Layout mode auto-switches based on gadget container width | none |
REQ-016-093 |
no | Manual mode toggle in gadget titlebar (grid/compact icon) | none |
REQ-016-094 |
yes | ClaudeChat gadget renders message history as a scrollable conversation view | none |
REQ-016-095 |
yes | User messages aligned right, Claude responses aligned left | none |
REQ-016-096 |
yes | Message input area with multiline support (Shift+Enter for newline, Enter to send) | none |
REQ-016-097 |
yes | Send button enabled only when input is non-empty | none |
REQ-016-098 |
yes | Message timestamps displayed on hover | none |
REQ-016-099 |
yes | User messages sent via cxp.send RPC with destination set to Claude-backed agent |
1 |
REQ-016-100 |
yes | Each chat thread uses a unique CXP thread_id | 1 |
REQ-016-101 |
yes | Responses received via cxp.traffic subscription filtered to the chat thread_id |
none |
REQ-016-102 |
yes | Work status tracked: "sent" -> "processing" -> "delivered" | 1 |
REQ-016-103 |
yes | Error responses displayed inline with red error styling | none |
REQ-016-104 |
yes | Code blocks rendered with syntax highlighting (language detection) | none |
REQ-016-105 |
yes | Inline code rendered with monospace font and background | none |
REQ-016-106 |
yes | Lists (ordered and unordered) rendered with proper indentation | none |
REQ-016-107 |
yes | Bold, italic, and links rendered correctly | none |
REQ-016-108 |
yes | Markdown parser sanitizes HTML (no script tags, no event handlers) | none |
REQ-016-109 |
yes | "New Thread" button creates a fresh CXP thread_id and clears display | none |
REQ-016-110 |
yes | Thread selector dropdown lists recent threads (last 10) by first message preview | none |
REQ-016-111 |
yes | Switching threads loads history from localStorage | none |
REQ-016-112 |
yes | Chat history persisted in localStorage (last 100 messages per thread) | none |
REQ-016-113 |
yes | Chat history synced via StateSync for cross-device persistence | none |
REQ-016-114 |
yes | Typing indicator (animated dots) shown while awaiting response | none |
REQ-016-115 |
yes | Typing indicator triggered by work_status change to "processing" | none |
REQ-016-116 |
yes | Connection status shown in chat header (connected/disconnected) | 1 |
REQ-016-117 |
yes | "Reconnecting..." overlay shown when gateway is disconnected | none |
REQ-016-118 |
no | Message search via keyword filter (search icon in chat header) | none |
REQ-016-119 |
yes | TaskBoard gadget displays tasks as kanban columns: Not Started, In Progress, Completed | none |
REQ-016-120 |
yes | Tasks displayed as cards within columns, sorted by priority (critical first) | none |
REQ-016-121 |
yes | Card shows: title, priority badge, assigned volk (avatar), brief description | none |
REQ-016-122 |
yes | Column header shows task count per status | none |
REQ-016-123 |
yes | "Deferred" column displays deferred work items from context.json | none |
REQ-016-124 |
yes | Tasks draggable between status columns (HTML5 Drag and Drop API) | 1 |
REQ-016-125 |
yes | Drop zones highlighted during drag (visual affordance) | 1 |
REQ-016-126 |
yes | Status change on drop sends RPC update to gateway | none |
REQ-016-127 |
yes | Drag-and-drop works on touch devices (pointer events) | none |
REQ-016-128 |
yes | Undo available for 5 seconds after status change (toast with "Undo" button) | none |
REQ-016-129 |
yes | "New Task" button opens modal dialog | none |
REQ-016-130 |
yes | Task form fields: title (required), description, priority dropdown | none |
REQ-016-131 |
yes | Task creation sends RPC to gateway for persistence | none |
REQ-016-132 |
yes | New task appears in "Not Started" column immediately | none |
REQ-016-133 |
yes | "New Task" button within each column opens modal dialog | none |
REQ-016-134 |
yes | Task form fields: title (required), description, assigned volk (dropdown), priority | none |
REQ-016-135 |
yes | Task creation sends RPC to gateway for persistence | none |
REQ-016-136 |
yes | New task appears in the appropriate column immediately | none |
REQ-016-137 |
no | Click on task card opens detail panel (slide-out right side) | none |
REQ-016-138 |
no | Detail panel shows: title, description, priority, assigned volk, parent goal | none |
REQ-016-139 |
no | Detail panel shows: history (status changes with timestamps) | none |
REQ-016-140 |
no | Detail panel shows: linked CXP threads, time spent | none |
REQ-016-141 |
no | Inline editing of title, description, priority, assigned volk in detail panel | 1 |
REQ-016-142 |
no | Dashboard task edits flow to context.json via gateway RPC | none |
REQ-016-143 |
no | CLI/external edits to context.json appear in dashboard via session.events subscription | none |
REQ-016-144 |
no | Conflict resolution: last-write-wins with user notification of override | none |
REQ-016-145 |
yes | QADashboard gadget displays current test count as a large number with label | none |
REQ-016-146 |
yes | Gadget displays pass rate as percentage with color (green >=99%, yellow >=95%, red <95%) | none |
REQ-016-147 |
yes | Gadget displays coverage percentage with color coding | none |
REQ-016-148 |
yes | Metrics fetched from project state via knowledge.query or configuration |
none |
REQ-016-149 |
yes | Metrics displayed as metric cards with current value and delta since last session | none |
REQ-016-150 |
yes | Coverage trend rendered as sparkline chart (last 20 data points) | none |
REQ-016-151 |
yes | Sparkline rendered using Canvas 2D API (no external chart library) | none |
REQ-016-152 |
yes | Hover on sparkline shows tooltip with exact value and date | none |
REQ-016-153 |
yes | Trend data fetched from knowledge graph (Iteration nodes with coverage property) | 1 |
REQ-016-154 |
yes | Gate status displayed as pass/fail indicator | none |
REQ-016-155 |
yes | Pass: green checkmark, Fail: red X, Partial: yellow warning triangle | none |
REQ-016-156 |
yes | Hover on gate icon shows: iteration number, date, test count, gap count | none |
REQ-016-157 |
yes | Click on gate icon shows detailed iteration results | none |
REQ-016-158 |
yes | Failed tests section expandable (collapsed by default) | none |
REQ-016-159 |
yes | Each failed test shows: test name, assertion message, file:line location | none |
REQ-016-160 |
yes | Failed tests grouped by test module | none |
REQ-016-161 |
yes | Click on file:line opens relevant context in ProjectExplorer gadget | none |
REQ-016-162 |
yes | RTM progress bar: verified requirements / total requirements | 1 |
REQ-016-163 |
yes | RTM percentage displayed as text alongside progress bar | none |
REQ-016-164 |
yes | Click on RTM progress bar opens RTM Viewer gadget | none |
REQ-016-165 |
yes | Test execution events received via kernel.events subscription (test_completed) |
none |
REQ-016-166 |
yes | Test count and pass rate updated in real-time during test runs | 5 |
REQ-016-167 |
yes | "Run Tests" button sends test execution command via gateway RPC | 3 |
REQ-016-168 |
yes | Test run progress bar shown during execution | 1 |
REQ-016-169 |
yes | AuditTrail gadget queries governance.query on mount with default time range |
none |
REQ-016-170 |
yes | Query results displayed in a sortable table | none |
REQ-016-171 |
yes | Table columns: timestamp, actor, action, resource, result, latency_ms | none |
REQ-016-172 |
yes | Table sortable by any column (click column header, toggle asc/desc) | none |
REQ-016-173 |
yes | Pagination: 50 items per page, next/prev buttons, page number display | none |
REQ-016-174 |
yes | Full-text search input searches across all audit fields (debounced 300ms) | none |
REQ-016-175 |
yes | Date range filter with date picker (from date, to date) | none |
REQ-016-176 |
yes | Actor filter dropdown (populated from volk.list + gateway client IDs) | none |
REQ-016-177 |
yes | Action type filter dropdown (CXP send, session open, governance check, etc.) | none |
REQ-016-178 |
yes | Result filter dropdown (allow, deny, escalated, error) | none |
REQ-016-179 |
yes | Constitutional article filter dropdown (I through XI) | none |
REQ-016-180 |
yes | Active filter summary bar showing applied filters with remove buttons | none |
REQ-016-181 |
yes | Constitutional article violations highlighted with red left border and article reference | none |
REQ-016-182 |
yes | Escalation events displayed with escalation chain (involved parties, path) | none |
REQ-016-183 |
yes | Governance decisions show Prolog query and evaluation latency | none |
REQ-016-184 |
yes | Click on audit row expands to show full event detail (JSON formatted) | none |
REQ-016-185 |
no | "Export CSV" button exports current filtered results as CSV download | none |
REQ-016-186 |
no | "Export JSON" button exports current filtered results as JSON download | none |
REQ-016-187 |
no | Export respects current filters and sort order | none |
REQ-016-188 |
no | Export includes all fields (not just visible columns) | none |
REQ-016-189 |
yes | KGExplorer renders a force-directed graph using Canvas 2D API | none |
REQ-016-190 |
yes | Nodes displayed with type-based styling (table view with node type column) | none |
REQ-016-191 |
yes | Node size proportional to relationship count (more connected = larger) | none |
REQ-016-192 |
yes | Relationships rendered as labeled directed edges with arrowheads | none |
REQ-016-193 |
yes | Node labels show name/alias (truncated to 20 chars) | none |
REQ-016-194 |
yes | Zoom via scroll wheel (min 0.1x, max 5x) | none |
REQ-016-195 |
yes | Pan via mouse drag on background | none |
REQ-016-196 |
yes | Node drag repositions node (simulation continues around dragged node) | none |
REQ-016-197 |
yes | Click on node selects it and shows property panel | none |
REQ-016-198 |
yes | Double-click on node expands its relationships (loads connected nodes) | none |
REQ-016-199 |
yes | Property panel shows all node properties as key-value pairs | none |
REQ-016-200 |
yes | Property panel shows node labels and type | none |
REQ-016-201 |
yes | Property panel shows relationship list (type, direction, target node) | none |
REQ-016-202 |
yes | Property panel links to related gadgets (file -> ProjectExplorer, session -> SessionManager) | none |
REQ-016-203 |
yes | Cypher input area for query entry | none |
REQ-016-204 |
yes | Auto-complete for node types, relationship types, and property names | none |
REQ-016-205 |
yes | "Run Query" button executes via knowledge.query RPC |
1 |
REQ-016-206 |
yes | Query results rendered as tabular data | none |
REQ-016-207 |
yes | Query history dropdown (last 20 queries) for re-execution | none |
REQ-016-208 |
yes | Query error messages displayed inline below the input | none |
REQ-016-209 |
yes | NotificationManager subscribes to governance.decisions for escalation events |
none |
REQ-016-210 |
yes | NotificationManager subscribes to kernel.events for error and warning events |
none |
REQ-016-211 |
yes | NotificationManager subscribes to session.events for decision_needed events |
none |
REQ-016-212 |
yes | Subscriptions established on CommandCenter initialization | none |
REQ-016-213 |
yes | Subscriptions re-established on gateway reconnect | none |
REQ-016-214 |
yes | Notification API permission requested on first critical event | none |
REQ-016-215 |
yes | Desktop notification shown when browser tab is not focused | none |
REQ-016-216 |
yes | Desktop notification includes: title, body (truncated to 100 chars), icon | none |
REQ-016-217 |
yes | Click on desktop notification focuses the browser tab and opens relevant gadget | none |
REQ-016-218 |
yes | Desktop notifications sent only for warning priority and above | none |
REQ-016-219 |
yes | Notification bell icon in dashboard header with unread count badge | none |
REQ-016-220 |
yes | Click on bell opens notification dropdown (last 50 notifications) | none |
REQ-016-221 |
yes | Each notification shows: timestamp, type icon, title, body preview | none |
REQ-016-222 |
yes | Click on notification navigates to relevant gadget (audit trail, session manager, etc.) | none |
REQ-016-223 |
yes | "Mark All Read" button clears unread count | none |
REQ-016-224 |
yes | Per-notification dismiss (X button) removes from list | none |
REQ-016-225 |
yes | Notification priority styling: info (blue), warning (yellow), error (red), critical (pulsing red) | none |
REQ-016-226 |
yes | Settings panel for notification preferences (accessible from bell dropdown) | none |
REQ-016-227 |
yes | Toggle desktop notifications on/off | none |
REQ-016-228 |
yes | Toggle notification sound on/off (with sound file selection) | none |
REQ-016-229 |
yes | Minimum priority filter (show only warnings and above, errors and above, etc.) | none |
REQ-016-230 |
yes | Preferences persisted via StateSync | none |
REQ-016-231 |
yes | PrayerTimes gadget wraps existing VizInt portal PrayerTimes gadget | none |
REQ-016-232 |
yes | Connects to Chronus provider for accurate prayer calculations | none |
REQ-016-233 |
yes | Displays next prayer name and countdown timer (HH:MM:SS) | none |
REQ-016-234 |
yes | Displays all five daily prayer times in a compact table | none |
REQ-016-235 |
no | TodoistGadget authenticates via personal API token (stored encrypted in localStorage) | none |
REQ-016-236 |
no | Displays today's tasks grouped by project | none |
REQ-016-237 |
no | Task completion toggle (checkbox) sends PATCH to Todoist API | none |
REQ-016-238 |
no | Quick-add task input at bottom of list (POST to Todoist API) | 1 |
REQ-016-239 |
no | EmailGadget shows unread count and top 10 sender/subject previews | none |
REQ-016-240 |
no | CalendarGadget shows today's events with time blocks | 1 |
REQ-016-241 |
no | API tokens encrypted with Web Crypto API before localStorage storage | none |
REQ-016-242 |
no | All personal gadgets function independently when gateway is disconnected | none |
REQ-016-243 |
yes | Theme toggle (dark/light) in dashboard header with smooth CSS variable transition | none |
REQ-016-244 |
yes | Gadget grid supports drag-to-reposition and resize handles on chrome | none |
REQ-016-245 |
yes | SessionHandler registered with gateway RPC router | 7 |
REQ-016-246 |
yes | session.active RPC returns the currently active session or null |
13 |
REQ-016-247 |
yes | session.list RPC returns all sessions with pagination |
4 |
REQ-016-248 |
yes | session.get RPC returns a single session by ID |
5 |
REQ-016-249 |
yes | session.open RPC creates and starts a new session |
7 |
REQ-016-250 |
yes | session.close RPC closes the active session with summary |
9 |
REQ-016-251 |
yes | session.events subscription pushes session lifecycle events |
7 |
REQ-016-252 |
yes | session.facts.subscribe subscription pushes session facts in real-time |
2 |
REQ-016-253 |
yes | ProjectsHandler registered with gateway RPC router | 1 |
REQ-016-254 |
yes | projects.list RPC returns all projects |
2 |
REQ-016-255 |
yes | projects.get RPC returns a single project by ID |
2 |
REQ-016-256 |
yes | projects.tasks RPC returns tasks for a project |
2 |
REQ-016-257 |
yes | projects.taskCreate RPC creates a new task for a project |
2 |
REQ-016-258 |
yes | WebSocketBridge implements JSON-RPC 2.0 over WebSocket | none |
REQ-016-259 |
yes | Auto-reconnect with exponential backoff on connection loss | none |
REQ-016-260 |
yes | Request queue buffers calls during disconnection for replay on reconnect | none |
REQ-016-261 |
yes | Authentication token sent on connection handshake | none |
REQ-016-262 |
yes | GadgetBridge maps EventBus events to WebSocket RPC calls | none |
REQ-016-263 |
yes | Supports session, CXP, volk, knowledge, and governance event domains | none |
REQ-016-264 |
yes | Bidirectional mapping: outbound events become RPC requests, inbound RPC responses become events | none |
REQ-016-265 |
yes | EventBus uses CustomEvent pub/sub with vizint: prefix namespace |
none |
REQ-016-266 |
yes | Compatible with standard addEventListener API | none |
REQ-016-267 |
yes | Supports wildcard subscriptions within event domains | none |
REQ-016-268 |
yes | Dynamic ES module loading of gadgets at runtime | none |
REQ-016-269 |
yes | Manifest validation ensures gadget metadata is complete | none |
REQ-016-270 |
yes | basePath configuration for loading gadgets from different directories | none |
REQ-016-271 |
yes | Gadget lifecycle management: mount, unmount, destroy | none |
REQ-016-272 |
yes | Chrome factory provides consistent gadget window decoration (titlebar, controls) | none |
REQ-016-273 |
yes | localStorage persistence for offline/quick-load state | none |
REQ-016-274 |
yes | Gateway sync for cross-device state consistency | 1 |
REQ-016-275 |
yes | 500ms debounce on state writes to prevent thrashing | none |
REQ-016-276 |
yes | Last-write-wins conflict resolution strategy | none |
REQ-016-277 |
yes | Desktop notification support via Notification API | 1 |
REQ-016-278 |
yes | In-app notification queue with priority-based rendering | none |
REQ-016-279 |
yes | Governance, kernel, and session event subscriptions for alert sources | 1 |
REQ-016-280 |
yes | Light and dark theme support via CSS custom properties | 1 |
REQ-016-281 |
yes | System preference detection (prefers-color-scheme media query) | none |
REQ-016-282 |
yes | Theme preference persisted in localStorage | none |
REQ-016-283 |
yes | Development layout profile: 5 gadgets (ProjectExplorer, SessionManager, CXPFeed, VolkStatus, ClaudeChat) | none |
REQ-016-284 |
yes | Monitoring layout profile: 4 gadgets (CXPFeed, VolkStatus, AuditTrail, NotificationCenter) | none |
REQ-016-285 |
yes | command-center.json configuration file with gateway, state_sync, notifications, layout sections |
none |
REQ-016-286 |
yes | Playwright E2E tests: page load, header, connection status, theme toggle, layout switching, WebSocket states | none |
REQ-016-287 |
yes | Vitest unit tests: EventBus, WebSocketBridge, StateSync, NotificationManager, Registry, Chrome, Shared | none |
REQ-016-288 |
yes | WsTestServer: Custom JSON-RPC mock server for testing | none |
REQ-016-289 |
yes | Flashcards gadget: Arabic/Italian learning with CSV data (50KB) | none |
REQ-016-290 |
yes | Iqama Countdown gadget: prayer time countdown (31KB) | none |
REQ-016-291 |
yes | Time-to-POI gadget: point-of-interest countdown (1135 LOC) | none |
REQ-016-292 |
yes | Chronus Sequencer gadget: timeline sequencer | none |
REQ-016-293 |
yes | Settings gadget: settings panel (1125 LOC) | none |
REQ-016-294 |
yes | Embed gadgets: iframe embedding for external content | none |
Code that traces this spec
Checklists
checklists/README.md
VizInt Command Center Checklists
Project: Orchestrata VizInt Command Center (Spec 016) Component: Command Center Dashboard Status: Planning Phase Owner: Architecture Team
Overview
The VizInt Command Center is the unified dashboard and personal command center for Orchestrata. Built on the VizInt gadget portal framework, it connects to the SPEC-014 WebSocket Gateway (JSON-RPC 2.0 over WebSocket) to provide real-time observation, control, and interaction with the entire orchestration system — alongside personal productivity gadgets for a unified workspace.
Checklist Summary
| Checklist | Total Items | Completed | Progress |
|---|---|---|---|
| Requirements | 244 | 0 | 0% |
| Constitutional Compliance | 140 | 0 | 0% |
| Testing Plan | 374 | 0 | 0% |
| TOTAL | 758 | 0 | 0% |
Key Responsibilities
1. WebSocket Bridge and Gateway Connection
- Establish and maintain WebSocket connection to SPEC-014 gateway
- Authenticate using configured strategy (static token, HMAC)
- Auto-reconnect with exponential backoff on disconnect
- Queue outbound RPC calls during reconnection
- Display connection status indicator in dashboard header
2. Gadget Lifecycle and Registry
- Dynamically load gadgets from registry as ES modules
- Validate gadget manifests against schema (id, name, version, entry, dependencies)
- Resolve gadget dependencies before mounting
- Manage gadget mount/unmount lifecycle with error boundaries
- Support multi-instance gadgets and hot-reload for development
3. Real-Time Data Visualization
- Subscribe to gateway event topics (CXP traffic, volk lifecycle, governance, session, kernel)
- Render live data feeds with virtualized scrolling for performance
- Apply client-side and server-side filters on event streams
- Display real-time metrics (packet throughput, test results, coverage)
- Animate state changes with CSS transitions
4. Session and Task Management
- Start/close sessions via gateway RPC
- Create and manage goals, tasks, deferred work items
- Kanban board with drag-and-drop status changes
- Bidirectional sync with context.json via gateway
- Session history browsing with search and filter
5. Claude Chat Interface
- Send messages via CXP protocol through gateway
- Receive responses via CXP traffic subscription
- Render markdown in responses (code blocks, lists, links)
- Thread management with persistent chat history
- Typing indicator during response generation
6. Notification System
- Subscribe to escalation, error, and decision-request events
- Desktop notifications via Notification API
- In-dashboard notification bell with unread count
- Priority-based styling (info, warning, error, critical)
- Click-to-navigate to relevant gadget
7. Personal Productivity Integration
- Prayer times via existing Chronus provider
- Todoist task management via REST API
- Email preview via Gmail API or IMAP
- Calendar events via Google Calendar or CalDAV
- All personal gadgets independent of gateway connection
8. Theme and Layout Customization
- Dark/light theme via CSS custom properties
- Gadget grid: drag to reposition, resize handles
- Named layout profiles with save/switch/reset
- Minimize, maximize, wide modes per gadget
- Theme and layout persisted via StateSync
Performance Targets
| Metric | Target | Critical Threshold |
|---|---|---|
| Gadget Initial Render | <100ms | <200ms |
| WebSocket Reconnect | <3s | <10s |
| RPC Round-Trip | <200ms p95 | <500ms p99 |
| CXP Feed Scroll | 60fps | 30fps minimum |
| Theme Switch | <50ms | <100ms |
| Initial Page Load | <2MB | <4MB |
| Memory (10 gadgets) | <100MB | <200MB |
| Event Delivery | <200ms from gateway | <500ms |
| Notification Display | <1s from event | <3s |
Checklist Files
1. requirements.md
Functional requirements organized by user stories:
- US-001: Project Dashboard
- US-002: Session Management
- US-003: Real-Time CXP Feed
- US-004: Volk Status Panel
- US-005: Claude Chat
- US-006: Task & Goal Board
- US-007: QA Dashboard
- US-008: Audit Trail Viewer
- US-009: Knowledge Graph Explorer
- US-010: Notification Center
- US-011: Personal Productivity Gadgets
- US-012: Theme & Layout Customization
2. constitutional.md
Compliance with all 11 constitutional articles:
- Article I: Agent Autonomy
- Article II: Prolog as Single Source of Truth
- Article III: Session Isolation
- Article IV: Hooks for Extensibility
- Article V: Minimal Core, Maximal Extension
- Article VI: Python 3.14t Implementation (adapted for JavaScript ES2024)
- Article VII: Testing Without Mocks
- Article VIII: Metrics and Observability
- Article IX: Graceful Degradation
- Article X: Version Compatibility
- Article XI: Documentation First
3. testing.md
Comprehensive testing strategy:
- Unit Tests (130+ tests): WebSocket bridge, gadget bridge, state sync, notification manager, theming
- Integration Tests (100+ tests): Gateway connection, gadget lifecycle, event subscriptions, RPC calls
- Contract Tests (30 tests): JSON-RPC compliance, event schema, gadget manifest validation
- Performance Tests (60+ tests): Render latency, scroll performance, memory, bundle size
- Accessibility Tests (20+ tests): Keyboard navigation, screen reader, color contrast
- Security Tests (15+ tests): XSS prevention, CSP, token storage, eval prevention
- Failure Scenario Tests (40+ tests): Disconnect handling, degraded mode, error boundaries
Integration Points
Upstream Dependencies
- SPEC-014 WebSocket Gateway: All data flows through the gateway (JSON-RPC 2.0 over WebSocket)
- VizInt Portal Framework: Gadget lifecycle, chrome, ctx.bus, providers, grid layout, CSS theming
- Redis (via Gateway): State sync persistence, notification storage
- Neo4j (via Gateway): Knowledge graph queries, audit trail queries
Downstream Consumers
- User (Browser): Primary consumer — visual dashboard in the browser
- Desktop Notifications: OS-level notifications via Notification API
External API Integrations
- Todoist REST API v2: Personal task management
- Gmail API / IMAP: Email preview
- Google Calendar / CalDAV: Calendar events
- Aladhan Prayer API: Prayer time calculations (via Chronus provider)
Dependencies
Required Services
- SPEC-014 WebSocket Gateway (running on configurable port)
- VizInt portal framework (gadget runtime)
Required Browser APIs
- WebSocket API
- Notification API
- Web Crypto API (token encryption)
- localStorage / sessionStorage
- Canvas 2D API (charts, KG visualization)
Optional Services
- Todoist API (personal tasks)
- Gmail API / IMAP (email preview)
- Google Calendar / CalDAV (calendar)
References
- SPEC-014: WebSocket Gateway
- SPEC-015: Plugin SDK
- SPEC-001: Orchestration Kernel
- SPEC-004: CXP Protocol
- SPEC-006: Session Management
- SPEC-007: Prolog Governance
- SPEC-008: Knowledge Graph
Last Updated: 2026-03-28 Version: 1.0.0 Maintained By: Architecture Team
checklists/constitutional.md
VizInt Command Center - Constitutional Compliance
Component: Command Center Dashboard Spec: 016-vizint-command-center Status: Compliance Review Total Compliance Items: 140
Overview
This document tracks compliance of the VizInt Command Center with all 11 articles of the Orchestrata Constitution. The Command Center is the primary user-facing interface, making constitutional compliance critical — it must faithfully represent system state without distortion, enforce governance visibility, and never bypass the kernel or PAM++ authorization chain.
Article I: Agent Autonomy
Principle: Volks (agents) retain autonomy; the Command Center observes but does not override agent decisions.
Compliance Requirements
Autonomy Preservation
- [x] CONST-I-001: Command Center displays volk decisions but does not modify or override them
- [x] CONST-I-002: CXP feed shows packets as-is, without editing payload content
- [x] CONST-I-003: Volk status panel reflects actual health, not Command Center's interpretation
- [x] CONST-I-004: Commands sent via dashboard are routed through the gateway to the kernel, not directly to volks
- [x] CONST-I-005: Dashboard does not inject CXP packets that impersonate a volk's identity
- [x] CONST-I-006: Claude chat messages are sent as user messages, not as volk-to-volk CXP packets
- [x] CONST-I-007: Task assignments via TaskBoard are suggestions routed through the kernel, not direct commands
- [ ] CONST-I-008: Volk deregistration via dashboard requires admin scope and kernel confirmation
- [x] CONST-I-009: Dashboard does not suppress or hide volk-generated events
- [x] CONST-I-010: Dashboard does not prioritize display of one volk's output over another without user action
Priority: Critical Verification: Integration tests + manual review
Article II: Prolog as Single Source of Truth
Principle: All governance rules are in Prolog; the Command Center queries governance through the gateway, never hardcodes authorization.
Compliance Requirements
Governance Fidelity
- [x] CONST-II-001: All gateway RPC calls respect PAM++ authorization enforced by the gateway
- [x] CONST-II-002: Command Center does not hardcode which methods require which scope
- [x] CONST-II-003: Audit trail viewer displays governance decisions exactly as returned by Prolog
- [x] CONST-II-004: Governance dry-run (
governance.evaluate) results shown without modification - [ ] CONST-II-005: Constitutional article references in audit trail match actual Prolog article definitions
- [x] CONST-II-006: Command Center does not cache governance decisions locally beyond gateway response TTL
- [x] CONST-II-007: Dashboard UI disables actions when gateway returns unauthorized (-32001) error
- [x] CONST-II-008: Governance rule listing (
governance.rules) displayed without interpretation or summarization - [x] CONST-II-009: Escalation paths displayed as returned by Prolog, not reordered or filtered by dashboard
- [x] CONST-II-010: Command Center does not present governance bypass options to the user
Priority: Critical Verification: Governance integration tests + policy compliance review
Article III: Session Isolation
Principle: Sessions are isolated; the Command Center does not leak state between sessions.
Compliance Requirements
State Isolation
- [x] - [ ] CONST-III-001: SessionManager displays only the selected session's state (not cross-session data)
- [x] - [ ] CONST-III-002: CXP feed subscription scoped to active session when session filter is applied
- [x] - [ ] CONST-III-003: Session history shows individual session details without merging data across sessions
- [x] - [ ] CONST-III-004: Deferred work items attributed to their originating session
- [x] - [ ] CONST-III-005: Task board tasks scoped to their associated session
- [x] - [ ] CONST-III-006: Chat threads linked to the session in which they were created
- [x] - [ ] CONST-III-007: Session open via dashboard creates a properly isolated session (validated by gateway)
- [x] - [ ] CONST-III-008: Session close via dashboard performs full teardown without orphaning resources
- [x] - [ ] CONST-III-009: Notification events include session_id for unambiguous attribution
- [x] - [ ] CONST-III-010: Gadget state (filters, scroll position) does not carry over between session switches
- [x] - [ ] CONST-III-011: Portfolio statistics aggregate across sessions without exposing per-session internals to unauthorized clients
- [x] - [ ] CONST-III-012: Knowledge graph queries scoped appropriately (no cross-session data leak in query results)
Priority: Critical Verification: Session isolation tests + state leak detection
Article IV: Hooks for Extensibility
Principle: The Command Center provides extension points for customization without core modification.
Compliance Requirements
Extension Points
- [x] CONST-IV-001: Third-party gadgets loadable via manifest URL (plugin gadget registration)
- [x] CONST-IV-002: Custom gadgets can register for ctx.bus events without core modification
- [x] CONST-IV-003: Custom gadgets can use GadgetBridge.call() and GadgetBridge.subscribe() APIs
- [x] CONST-IV-004: Custom themes definable via CSS custom property override files
- [x] CONST-IV-005: Custom layout profiles creatable and saveable by the user
- [x] CONST-IV-006: GadgetRegistry supports adding gadgets at runtime
- [x] CONST-IV-007: NotificationManager supports custom notification handlers via hook registration
- [x] CONST-IV-008: WebSocketBridge.onStateChange supports multiple listener registrations
- [ ] CONST-IV-009: Gadget chrome provides standard extension slot (custom buttons in titlebar)
- [x] CONST-IV-010: Event bus supports custom event types beyond predefined gateway topics
Priority: High Verification: Plugin gadget tests + extension API tests
Article V: Minimal Core, Maximal Extension
Principle: Command Center core is minimal; features are added via gadgets (extensions).
Compliance Requirements
Minimal Core
- [x] CONST-V-001: Core handles only: WebSocket bridge, gadget registry, layout grid, theming, notifications
- [x] CONST-V-002: All orchestrata features are gadgets, not core (CXP feed, session manager, etc.)
- [x] CONST-V-003: Personal productivity features are gadgets, not core (prayer times, Todoist, etc.)
- [x] CONST-V-004: KG Explorer is a gadget, not core
- [x] CONST-V-005: Audit Trail is a gadget, not core
- [x] CONST-V-006: Core has zero business logic about orchestrata internals
- [x] CONST-V-007: Core dependencies are minimal: no charting library, no UI framework beyond portal
- [x] CONST-V-008: Core JavaScript is < 5000 lines (excluding gadgets)
- [x] CONST-V-009: Core API is stable and versioned (CommandCenter.API_VERSION)
- [x] CONST-V-010: Gadgets loaded dynamically via ES module import(), not bundled in core
Priority: High Verification: Core size metrics + dependency audit
Article VI: Implementation Standards (JavaScript ES2024)
Principle: Code follows modern standards with proper async patterns and type safety.
Compliance Requirements
Language Standards
- [x] CONST-VI-001: Code uses ES2024 module syntax (import/export)
- [x] CONST-VI-002: Async/await for all asynchronous operations (WebSocket, fetch, timers)
- [ ] CONST-VI-003: No blocking operations on the main thread (heavy computation offloaded to Web Workers)
- [x] CONST-VI-004: Promise.all for concurrent independent operations
- [x] CONST-VI-005: structuredClone for deep object copies (no JSON.parse(JSON.stringify()))
- [ ] CONST-VI-006: WeakRef for preventing memory leaks in subscription callbacks
- [ ] CONST-VI-007: AbortController for cancellable fetch and subscription operations
- [x] CONST-VI-008: Proper error handling: try/catch on all async operations, no unhandled rejections
- [x] CONST-VI-009: No var declarations (const by default, let when reassignment needed)
- [x] CONST-VI-010: Template literals for string interpolation (no string concatenation)
Code Quality
- [x] CONST-VI-011: ESLint configuration with strict rules (no-unused-vars, no-implicit-globals)
- [x] CONST-VI-012: Prettier formatting enforced
- [x] CONST-VI-013: JSDoc comments on all public classes and methods
- [x] CONST-VI-014: No console.log in production (use structured logging utility)
- [ ] CONST-VI-015: Functions < 40 lines
- [ ] CONST-VI-016: No global mutable state (all state in class instances or closures)
- [x] CONST-VI-017: No
eval(),new Function(), orsetTimeout(string) - [x] CONST-VI-018: Event listeners properly removed on gadget unmount (no memory leaks)
- [x] CONST-VI-019: CSS classes follow BEM naming convention (block__element--modifier)
- [x] CONST-VI-020: No inline styles; all styling via CSS classes and custom properties
Priority: High Verification: ESLint + Prettier CI checks + code review
Article VII: Testing Without Mocks
Principle: Tests use real implementations, not mocks.
Compliance Requirements
Real Systems Testing
- [x] CONST-VII-001: Tests use real WebSocket connections to a test gateway server
- [x] CONST-VII-002: Tests use real browser APIs (localStorage, Notification, Canvas)
- [x] CONST-VII-003: Tests use real DOM (JSDOM or headless browser, not virtual DOM simulation)
- [x] CONST-VII-004: Tests use real event dispatch (CustomEvent on window, not synthetic stubs)
- [x] CONST-VII-005: No jest.mock, sinon.stub, or equivalent mock libraries
- [x] CONST-VII-006: Test fixtures create real gadget instances with real lifecycle
- [x] CONST-VII-007: Integration tests connect to a real SPEC-014 gateway instance
- [ ] CONST-VII-008: Performance tests measure real rendering time in a real browser environment
- [x] CONST-VII-009: Tests validate real race conditions (concurrent subscriptions, rapid reconnects)
- [ ] CONST-VII-010: Tests validate real scroll behavior with real DOM measurements
Priority: Critical Verification: Test code review + mock detector
Article VIII: Metrics and Observability
Principle: All operations are observable and measurable.
Compliance Requirements
Client-Side Metrics
- [x] CONST-VIII-001: Gadget render time tracked per gadget (mount to first paint)
- [x] CONST-VIII-002: RPC call latency tracked per method (call to response)
- [x] CONST-VIII-003: Event delivery latency tracked (gateway push to gadget render)
- [x] CONST-VIII-004: WebSocket connection state transitions logged
- [x] CONST-VIII-005: Reconnection attempts and durations tracked
- [x] CONST-VIII-006: Subscription count per topic tracked
- [x] CONST-VIII-007: Notification delivery tracked (created, displayed, clicked)
- [x] CONST-VIII-008: Memory usage sampled periodically (performance.memory if available)
- [x] CONST-VIII-009: Frame rate monitored during scroll and animation (requestAnimationFrame timing)
- [x] CONST-VIII-010: Error count tracked per gadget
Observability
- [x] CONST-VIII-011: Structured logging utility (JSON format) for all Command Center operations
- [x] CONST-VIII-012: Log levels: debug, info, warn, error (configurable filter)
- [x] CONST-VIII-013: Correlation IDs on RPC calls (cc-req-{id}) for tracing through gateway
- [x] CONST-VIII-014: Connection status visible in dashboard header at all times
- [x] CONST-VIII-015: Gadget health visible in gadget chrome (error state, loading state)
- [x] CONST-VIII-016: Debug panel (togglable) showing: active subscriptions, RPC queue, event bus traffic
- [x] CONST-VIII-017: Performance overlay (togglable) showing: FPS, memory, render times
- [x] CONST-VIII-018: Console warnings for deprecated API usage in gadgets
- [x] CONST-VIII-019: Error boundary captures per-gadget exceptions with stack trace
- [x] CONST-VIII-020: Metrics exportable as JSON for external analysis
Priority: High Verification: Metrics tests + observability review
Article IX: Graceful Degradation
Principle: System degrades gracefully under failure, does not crash.
Compliance Requirements
Failure Handling
- [x] CONST-IX-001: Gateway disconnected: all gadgets switch to read-only mode with cached data
- [x] CONST-IX-002: Gateway disconnected: connection indicator shows "disconnected" state
- [x] CONST-IX-003: Gateway disconnected: RPC calls queued (up to 100, oldest discarded)
- [x] CONST-IX-004: Gateway disconnected: personal gadgets continue functioning independently
- [ ] CONST-IX-005: Gateway auth failure: clear error message with re-authentication option
- [x] CONST-IX-006: Gadget error: error boundary catches exception, shows error state in gadget chrome
- [x] CONST-IX-007: Gadget error: other gadgets unaffected (isolation)
- [x] CONST-IX-008: Subscription lost: automatic re-subscription on reconnect
- [x] CONST-IX-009: RPC timeout: structured error shown to user, retry option available
- [x] CONST-IX-010: localStorage quota exceeded: oldest cached data evicted, warning shown
Recovery
- [x] CONST-IX-011: Automatic WebSocket reconnection with exponential backoff (1s, 2s, 4s, max 30s)
- [x] CONST-IX-012: Reconnect re-authenticates and re-subscribes all active subscriptions
- [x] CONST-IX-013: Queued RPC calls flushed on successful reconnect
- [x] CONST-IX-014: Gadget error: retry button in error state to re-mount the gadget
- [x] CONST-IX-015: Browser refresh restores full state from localStorage
- [x] CONST-IX-016: Partial gateway failure: healthy gadgets continue, unhealthy show degraded state
- [x] CONST-IX-017: External API failure (Todoist, Gmail): personal gadgets show cached data with stale indicator
- [ ] CONST-IX-018: Canvas rendering failure: fallback to table-based display (KG Explorer, charts)
- [x] CONST-IX-019: Notification API denied: in-dashboard notifications still function
- [x] CONST-IX-020: Recovery events logged for debugging
Priority: High Verification: Failure injection tests + disconnect simulation
Article X: Version Compatibility
Principle: APIs are versioned; breaking changes are avoided.
Compliance Requirements
API Versioning
- [x] CONST-X-001: CommandCenter.API_VERSION set and checked against gadget manifest min_api_version
- [x] CONST-X-002: Gadget manifests declare min_api_version for compatibility checking
- [x] CONST-X-003: Gateway protocol version checked on connection (from gateway.info response)
- [x] CONST-X-004: Incompatible gateway version: warning displayed, graceful feature disabling
- [x] CONST-X-005: GadgetBridge API methods are additive (new methods added, existing not removed)
- [x] CONST-X-006: State sync keys are namespaced (commandcenter.state.*) to avoid collisions
- [x] CONST-X-007: Event bus event types are namespaced (cc.* for command center, gadget.* for gadgets)
- [ ] CONST-X-008: CSS custom properties prefixed (--cc-* for command center specific)
- [ ] CONST-X-009: Deprecated gadget APIs emit console warnings for one major version before removal
- [x] CONST-X-010: Gadget manifest schema versioned independently of API version
Priority: Medium Verification: Compatibility tests + version migration tests
Article XI: Documentation First
Principle: Documentation precedes implementation.
Compliance Requirements
Design Documentation
- [x] CONST-XI-001: Command Center architecture documented before implementation (this spec)
- [x] CONST-XI-002: Gadget API documented before implementation (GadgetBridge, WebSocketBridge)
- [x] CONST-XI-003: Gadget manifest schema documented with examples
- [x] CONST-XI-004: WebSocket bridge protocol documented (reconnection, auth, queuing)
- [x] CONST-XI-005: State sync protocol documented (conflict resolution, debouncing)
- [x] CONST-XI-006: Notification schema documented with examples for each priority level
- [x] CONST-XI-007: Theme system documented (CSS custom properties, theme switching)
- [x] CONST-XI-008: Layout profile format documented (gadget positions, sizes)
- [x] CONST-XI-009: Plugin gadget development guide written before plugin API is finalized
- [x] CONST-XI-010: Performance budget documented (bundle size, render targets, memory limits)
Priority: High Verification: Documentation review + doc completeness check
Summary Statistics
| Article | Total Items | Completed | Percentage |
|---|---|---|---|
| Article I (Autonomy) | 10 | 0 | 0% |
| Article II (Prolog) | 10 | 0 | 0% |
| Article III (Isolation) | 12 | 0 | 0% |
| Article IV (Hooks) | 10 | 0 | 0% |
| Article V (Minimal Core) | 10 | 4 | 40% |
| Article VI (JS ES2024) | 20 | 8 | 40% |
| Article VII (No Mocks) | 10 | 1 | 10% |
| Article VIII (Observability) | 20 | 4 | 20% |
| Article IX (Degradation) | 20 | 2 | 10% |
| Article X (Versioning) | 10 | 2 | 20% |
| Article XI (Documentation) | 10 | 1 | 10% |
| TOTAL | 142 | 22 | 15.5% |
Last Updated: 2026-05-26 Version: 1.0.0 Maintained By: Architecture Team
checklists/requirements.md
The requirement list above comes from this file; 242 of 294 checkbox items are ticked.
checklists/testing.md
VizInt Command Center - Testing Checklist
Component: Command Center Dashboard Spec: 016-vizint-command-center Updated: 2026-03-29 Total Test Cases: 62 implemented, 6 categories planned
Test Results Summary
| Category | Count | Status | Tool |
|---|---|---|---|
| E2E Dashboard | 11 | Implemented | Playwright (Firefox) |
| Unit EventBus | 8 | Implemented | Vitest |
| Unit WebSocketBridge | 12 | Implemented | Vitest |
| Unit StateSync | 8 | Implemented | Vitest |
| Unit NotificationManager | 7 | Implemented | Vitest |
| Unit Registry | 5 | Implemented | Vitest |
| Unit Chrome | 4 | Implemented | Vitest |
| Unit Shared | 4 | Implemented | Vitest |
| Contract Gateway RPC | 0 | Planned | Vitest |
| Perf Rendering | 0 | Planned | Playwright |
Implemented: 62 tests across 10 suites Planned: Contract, Performance, Gadget Integration, Gateway Integration, Cross-browser, Accessibility
Test Infrastructure
| Component | Path | Purpose |
|---|---|---|
| Playwright config | playwright.config.js |
Firefox browser, baseURL http://<test-fleet-host>:5000 (e.g. http://10.53.2.13:5000 with ORCHESTRATA_ENV_PROFILE=test) |
| Vitest config | vitest.config.js |
jsdom environment, ES module resolution |
| WS test server | tests/helpers/ws-test-server.js |
Custom WebSocket server for JSON-RPC mock testing |
| E2E tests | tests/e2e/dashboard.spec.js |
Playwright end-to-end suite |
| Unit tests | tests/unit/*.test.js |
Vitest unit suites |
E2E Tests - Playwright (11 tests)
File: tests/e2e/dashboard.spec.js
- [x] TEST-E2E-001: Page loads and renders title
- [x] TEST-E2E-002: Header renders with title and controls
- [x] TEST-E2E-003: Connection status shows initially
- [x] TEST-E2E-004: Theme toggle persists to localStorage
- [x] TEST-E2E-005: Layout switching between profiles
- [x] TEST-E2E-006: WebSocket connection state tracking
- [x] TEST-E2E-007: Notification bell renders
- [x] TEST-E2E-008: Gadget loading from registry
- [x] TEST-E2E-009: Multiple gadget mount/unmount lifecycle
- [x] TEST-E2E-010: Layout profile gadget visibility
- [x] TEST-E2E-011: Error handling for failed gadget loads
Unit Tests - EventBus (8 tests)
File: tests/unit/bus.test.js
- [ ] TEST-UNIT-001: emit dispatches CustomEvent with
vizint:prefix - [ ] TEST-UNIT-002: on subscribes handler to event
- [ ] TEST-UNIT-003: off unsubscribes handler from event
- [ ] TEST-UNIT-004: once fires handler only once then auto-removes
- [ ] TEST-UNIT-005: addEventListener compatibility with DOM API
- [ ] TEST-UNIT-006: removeEventListener compatibility with DOM API
- [ ] TEST-UNIT-007: destroy removes all listeners
- [ ] TEST-UNIT-008: Multiple handlers on same event all invoked
Unit Tests - WebSocketBridge (12 tests)
File: tests/unit/websocket-bridge.test.js
- [ ] TEST-UNIT-009: connect establishes WebSocket connection
- [ ] TEST-UNIT-010: call sends JSON-RPC 2.0 request format
- [ ] TEST-UNIT-011: call receives and resolves JSON-RPC 2.0 response
- [ ] TEST-UNIT-012: auto-reconnect triggers on disconnect
- [ ] TEST-UNIT-013: reconnect uses exponential backoff
- [ ] TEST-UNIT-014: state transitions disconnected to connected
- [ ] TEST-UNIT-015: state transitions connected to reconnecting
- [ ] TEST-UNIT-016: subscribe sends subscription RPC to gateway
- [ ] TEST-UNIT-017: unsubscribe removes push notification handler
- [ ] TEST-UNIT-018: request queue buffers calls during reconnect
- [ ] TEST-UNIT-019: request queue enforces max 100 entries
- [ ] TEST-UNIT-020: timeout handling rejects RPC calls after deadline
Unit Tests - StateSync (8 tests)
File: tests/unit/state-sync.test.js
- [ ] TEST-UNIT-021: get reads value from localStorage
- [ ] TEST-UNIT-022: set writes value to localStorage
- [ ] TEST-UNIT-023: delete removes value from localStorage
- [ ] TEST-UNIT-024: sync to gateway is debounced at 500ms
- [ ] TEST-UNIT-025: pullRemote fetches state from gateway
- [ ] TEST-UNIT-026: pushLocal sends state to gateway
- [ ] TEST-UNIT-027: conflict resolution uses last-write-wins
- [ ] TEST-UNIT-028: keys use
commandcenter.state.prefix
Unit Tests - NotificationManager (7 tests)
File: tests/unit/notification-manager.test.js
- [ ] TEST-UNIT-029: subscribe to governance.decisions channel
- [ ] TEST-UNIT-030: subscribe to kernel.events channel
- [ ] TEST-UNIT-031: subscribe to session.events channel
- [ ] TEST-UNIT-032: priority ordering info < warning < error < critical
- [ ] TEST-UNIT-033: desktop notification dispatched via Notification API
- [ ] TEST-UNIT-034: max stored notifications capped at 200
- [ ] TEST-UNIT-035: unread count tracking increments and resets
Unit Tests - Registry (5 tests)
File: tests/unit/registry.test.js
- [ ] TEST-UNIT-036: manifest validation rejects missing required fields
- [ ] TEST-UNIT-037: dynamic module loading via import()
- [ ] TEST-UNIT-038: basePath resolution for gadget entry points
- [ ] TEST-UNIT-039: error handling for invalid manifests
- [ ] TEST-UNIT-040: valid manifest passes all required field checks
Unit Tests - Chrome (4 tests)
File: tests/unit/chrome.test.js
- [ ] TEST-UNIT-041: title bar creation with gadget name
- [ ] TEST-UNIT-042: minimize button toggles body visibility
- [ ] TEST-UNIT-043: close button action triggers unmount
- [ ] TEST-UNIT-044: status bar rendering with connection info
Unit Tests - Shared Utilities (4 tests)
File: tests/unit/shared.test.js
- [ ] TEST-UNIT-045: generateId produces unique IDs
- [ ] TEST-UNIT-046: generateId IDs do not collide across calls
- [ ] TEST-UNIT-047: debounce delays execution by specified interval
- [ ] TEST-UNIT-048: formatTimestamp formats ISO date strings
Contract Tests - Gateway RPC (planned)
- [ ] TEST-CONTRACT-001: session.list request schema matches gateway SessionHandler
- [ ] TEST-CONTRACT-002: session.list response schema matches expected format
- [ ] TEST-CONTRACT-003: session.get request includes valid session_id parameter
- [ ] TEST-CONTRACT-004: project.list request schema matches gateway ProjectsHandler
- [ ] TEST-CONTRACT-005: subscribe request uses valid channel name enum
- [ ] TEST-CONTRACT-006: unsubscribe request references valid subscription_id
- [ ] TEST-CONTRACT-007: RPC error response codes match gateway error catalog
- [ ] TEST-CONTRACT-008: push notification envelope matches documented schema
Performance Tests (planned)
- [ ] TEST-PERF-001: 60fps maintained during gadget panel scrolling
- [ ] TEST-PERF-002: Initial render completes in under 100ms
- [ ] TEST-PERF-003: Event dispatch latency under 16ms
- [ ] TEST-PERF-004: Gadget mount/unmount cycle under 50ms
- [ ] TEST-PERF-005: WebSocket reconnect under 2s on network restore
Integration Tests (planned)
- [ ] TEST-INTEG-001: SessionHandler returns live session data from gateway
- [ ] TEST-INTEG-002: ProjectsHandler returns project list from gateway
- [ ] TEST-INTEG-003: Gadget receives real-time push notification via WebSocket
- [ ] TEST-INTEG-004: State round-trips through localStorage and remote sync
- [ ] TEST-INTEG-005: Each P1 gadget loads, renders, and responds to events
- [ ] TEST-INTEG-006: Cross-browser validation (Chrome, Safari — currently Firefox only)
- [ ] TEST-INTEG-007: Accessibility audit passes ARIA landmark checks
- [ ] TEST-INTEG-008: Accessibility audit passes keyboard navigation
Other tracked files
specs/016-vizint-command-center/compliance-audit.md
Full spec text
Verbatim from specs/016-vizint-command-center/spec.md; headings are pushed down two levels.
SPEC-016: VizInt Command Center
Metadata
- Spec ID: 016-vizint-command-center
- Title: VizInt Command Center
- Version: 2.0.0
- Author: Mohamed
- Contributors: MiniMax (model), OpenCode (plugin integration)
- Status: Implemented (Core) + Gadgets Implemented
- Created: 2026-03-28
- Last Updated: 2026-03-29
- Priority: P1
- Components: CommandCenterApp, GadgetBridge, WebSocketBridge, StateSync, GadgetRegistry, NotificationManager, EventBus, Portal, Chrome
- Dependencies: VizInt portal framework, SPEC-014 WebSocket Gateway, JavaScript ES2024, CSS3, HTML5
- API Version: 1.0.0
- Contract Version: 1.0.0
- Backward Compatibility: Backward compatible with 1.0.0 contracts; new gateway handlers are additive
Overview
What
The VizInt Command Center is the unified dashboard and personal command center for Orchestrata. Built on the VizInt gadget portal framework (cloned at vizint-ui/), it provides a single browser-based interface where the user can observe, control, and interact with the entire orchestration system in real-time. The Command Center connects to Orchestrata via the SPEC-014 WebSocket Gateway (JSON-RPC 2.0 over WebSocket), presenting every orchestration feature as a composable gadget. The system ships with 31 gadgets spanning orchestration production dashboards, personal productivity tools, developer utilities, and example templates. Zero-build ES modules via import maps in HTML eliminate the need for any bundler.
Why
- Orchestrata lacks a visual interface -- all interaction happens through CLI or code, making observation and control cumbersome
- The SPEC-014 WebSocket Gateway exposes rich real-time data (CXP traffic, volk lifecycle, governance decisions, session events) but no consumer exists to visualize it
- Multi-agent coordination with 8 volks, Prolog governance, dual storage, and complex session state demands a visual dashboard for effective monitoring
- Session management (start, close, deferred work, achievements) requires manual CLI commands -- a dashboard streamlines this workflow
- The VizInt gadget portal framework already provides a mature foundation: gadget lifecycle, chrome, registry, pub/sub event bus, theming, and grid layout
- No unified place to see QA gates, test coverage, RTM progress, and version bumps as they happen
- Notifications for escalations and decision requests currently go unnoticed without active CLI monitoring
- Personal productivity tools (prayer times, tasks, calendar) fragmented across separate browser tabs
- The knowledge graph (558K+ nodes) needs a visual exploration interface for developers and architects
How
- VizInt portal runs in the browser as static HTML/JS/CSS with zero server-side rendering and zero-build ES modules (import maps in HTML, no bundler)
CommandCenterAppinapp.jsbootstraps 5 subsystems: WebSocketBridge, GadgetBridge, StateSync, NotificationManager, and GadgetRegistry- Connects to Orchestrata via SPEC-014 WebSocket Gateway on configurable port (default: 18790)
- Portal's
ctx.bus(EventBus via CustomEvents withvizint:prefix) bridges bidirectionally to WebSocket pub/sub topics via GadgetBridge - GadgetBridge translates between gadget-local events and gateway JSON-RPC 2.0 method calls across five RPC namespaces:
session.*,cxp.*,volk.*,knowledge.*,governance.* - StateSync replaces localStorage-only persistence with WebSocket-backed state synchronization (debounced 500ms, last-write-wins conflict resolution)
- Gadgets are ES module classes loaded dynamically from GadgetRegistry with manifest-declared dependencies
- Each Orchestrata feature is a dedicated gadget: ProjectExplorer, SessionManager, CXPFeed, VolkStatus, ClaudeChat, TaskBoard, QADashboard, AuditTrail, KGExplorer, NotificationCenter
- Personal and specialized gadgets provide prayer times, language flashcards, timeline sequencing, point-of-interest countdowns, and settings management
- NotificationManager surfaces gateway escalation and decision-request events as desktop notifications and in-dashboard alerts (max 200 stored)
- Theme and layout customization via CSS variables (light/dark with system preference detection + toggle), grid arrangement persistence, and named layout profiles
- Gateway handlers (SessionHandler, ProjectsHandler) provide Neo4j-backed async queries with 10s timeouts
User Scenarios & Stories
US-001: Project Dashboard (P1)
As a developer or project lead I want to open a project and see its knowledge graph nodes, source files, sessions, and iterations at a glance So that I have immediate situational awareness of the project state
Acceptance Criteria:
- [x] Client opens ProjectExplorer gadget (173 LOC) showing project metadata (name, version, file count, LOC)
- [x] Gadget displays KG node summary: files, classes, functions, sessions, iterations (counts and sparkline trends)
- [x] Gadget provides a file tree browser with search, powered by
knowledge.nodesRPC (node_type=File) - [x] Gadget shows recent sessions (last 10) with status badges (active, closed, error)
- [ ] Gadget shows recent iterations (last 10) with gap/pass indicators
- [ ] Click-through navigation from file tree to KG Explorer gadget with file-scoped context
- [x] Project metrics auto-refresh every 60 seconds via WebSocket subscription
US-002: Session Management (P1)
As a developer I want to start and close sessions, see deferred work, and log work through the dashboard So that I can manage orchestration sessions without CLI commands
Acceptance Criteria:
- [x] SessionManager gadget (198 LOC) displays the active
session_idprominently in the gadget header (monospace, copyable) - [x] SessionManager gadget shows active session with full state (session_id, session number, goals, duration, context, portfolio)
- [x] "Start Session" button sends
session.openRPC with configurable goals and portfolio - [x] "Close Session" button sends
session.closeRPC with summary and carryover tasks - [x] Deferred work items displayed in a prioritized list (critical > high > medium > low)
- [ ] Inline editing of deferred work items (add, remove, reprioritize, mark done)
- [ ] "Log Work" input sends work description to session context via RPC
- [x] Session event stream (
session.eventssubscription) updates gadget in real-time - [ ] Session history table with search and date-range filter
US-003: Real-Time CXP Feed (P1)
As a developer or system operator I want to watch CXP packets flow between volks in real-time So that I can observe agent communication and debug routing issues
Acceptance Criteria:
- [x] CXPFeed gadget (161 LOC) subscribes to
cxp.trafficvia WebSocket bridge - [x] Packets displayed as a scrolling feed with: timestamp, from, to, subject, delivery_status, thread_id
- [x] Feed supports filtering by volk (dropdown), thread (text input), subject (glob pattern), status (dropdown)
- [ ] Filters applied client-side for instant response, with server-side filter sync for bandwidth efficiency
- [x] Click on a packet row expands to show full CXP payload (all 11 fields)
- [x] Feed pauses on scroll-up, auto-resumes on scroll-to-bottom
- [x] Packet count badge and throughput indicator (packets/sec) in gadget titlebar
- [x] Color-coded delivery status: green (delivered), yellow (pending), red (failed), grey (expired)
US-004: Volk Status Panel (P1)
As a system operator I want to see all volks with their health, current task, and output artifacts So that I can monitor agent activity and detect failures
Acceptance Criteria:
- [x] VolkStatus gadget (192 LOC) calls
volk.liston mount and subscribes tovolk.lifecycle - [x] Each volk displayed as a card with: alias, role, health indicator (green/yellow/red), current task
- [x] Health changes animate with color transition (CSS transition)
- [x] Task progress shown as status text with elapsed time
- [ ] Click on volk card opens detail panel: capabilities, protocols, registration time, session, resource usage
- [ ] Output artifacts listed per volk (files generated, CXP packets sent)
- [x] Volk registration/deregistration events update the panel in real-time
- [ ] Compact mode: horizontal bar per volk with color-coded health (for small viewports)
US-005: Claude Chat (P1)
As a developer I want to chat with Claude directly through the dashboard So that I can get AI assistance without leaving the command center
Acceptance Criteria:
- [x] ClaudeChat gadget (226 LOC) provides a chat interface with message input, send button, and message history
- [x] Messages sent via
cxp.sendRPC with destination volk set to the Claude-backed agent - [x] Responses received via
cxp.trafficsubscription filtered to the chat thread - [x] Chat supports markdown rendering in responses (code blocks, lists, bold, links)
- [x] Chat thread persisted in localStorage and synced via StateSync
- [x] "New Thread" button creates a fresh CXP thread_id
- [ ] Typing indicator shown while awaiting response (subscription to work_status changes)
- [ ] Chat history searchable with keyword filter
US-006: Task & Goal Board (P1)
As a project lead I want to create and manage tasks, goals, and deferred work items through the dashboard So that work items flow into context.json and the goal runner without manual file editing
Acceptance Criteria:
- [x] TaskBoard gadget (224 LOC) displays goals as kanban columns (Not Started, In Progress, Completed)
- [x] Tasks displayed as cards within columns, sortable by priority
- [x] Drag-and-drop to move tasks between status columns (sends RPC update)
- [x] "New Goal" dialog: title, description, acceptance criteria, priority
- [x] "New Task" dialog: title, description, assigned volk, parent goal, priority
- [ ] Deferred work items from context.json displayed in a dedicated "Deferred" column
- [ ] Changes sync bidirectionally: dashboard edits flow to context.json, CLI edits appear in dashboard
- [ ] Task detail panel shows: history, comments, linked CXP threads, time spent
US-007: QA Dashboard (P1)
As a developer or QA lead I want to see test results, coverage trends, and gate status per iteration So that I know the quality state of the project at a glance
Acceptance Criteria:
- [x] QADashboard gadget (179 LOC) displays current test count, pass rate, coverage percentage, and total test duration
- [x] Test duration displayed as total elapsed time (e.g., "4m 16s") with per-batch breakdown (unit, prolog-half1, prolog-half2)
- [ ] Duration trend sparkline alongside coverage trend (last 20 iterations)
- [ ] Per-test timing available in expanded test detail: test name, duration (ms), assertion message, file:line
- [x] Coverage trend chart (last 20 iterations) as a sparkline or mini line chart
- [x] Gate status per iteration: pass (green check), fail (red X), partial (yellow warning)
- [x] Failed test details expandable: test name, duration, assertion message, file:line
- [ ] Slowest tests highlighted (top 10 by duration) with performance regression indicator
- [ ] Iteration selector dropdown to view historical QA results
- [x] RTM progress bar: verified requirements / total requirements with percentage
- [ ] Test execution status updated in real-time via kernel event subscription
- [ ] One-click "Run Tests" button sends test execution command via gateway
US-008: Audit Trail Viewer (P1)
As a compliance auditor or developer I want to see every event, decision, and escalation with search and filter So that I can trace actions and verify governance compliance
Acceptance Criteria:
- [x] AuditTrail gadget (202 LOC) queries
governance.queryfor historical decisions - [x] Events displayed in a sortable table: timestamp, actor, action, resource, result, latency
- [x] Full-text search across all audit fields
- [x] Filter by: date range, actor (volk/client), action type, result (allow/deny), article
- [x] Constitutional article violations highlighted with article reference
- [ ] Escalation events shown with full escalation path (chain of involved parties)
- [ ] Pagination for large result sets (50 items per page, next/prev controls)
- [ ] Export filtered results as CSV or JSON
US-009: Knowledge Graph Explorer (P2)
As a developer or architect I want to visually browse the knowledge graph and run Cypher queries So that I can explore relationships between files, classes, sessions, and specs
Acceptance Criteria:
- [x] KGExplorer gadget (194 LOC) renders a graph visualization
- [x] Nodes colored by type: File (blue), Class (green), Function (yellow), Session (purple), Spec (orange)
- [x] Relationships rendered as labeled directed edges
- [x] Click on node shows property panel with all node properties
- [ ] Cypher query input with syntax highlighting and auto-complete for node types
- [ ] Full-text search bar: search across all node types by name, docstring, or content (uses the
search_namesandmessage_searchfulltext indexes) - [ ] Search results grouped by node type with relevance scores
- [x] Query results rendered as both graph visualization and tabular data
- [x] Graph supports zoom, pan, and node drag
- [x] Queries executed via
knowledge.queryRPC with read-only validation
US-010: Notification Center (P1)
As a developer I want to receive alerts when orchestrata needs decisions or when escalations occur So that I can respond promptly without constant CLI monitoring
Acceptance Criteria:
- [x] NotificationManager subscribes to
governance.decisions(escalation events),kernel.events(errors), andsession.events - [x] Desktop notifications via Notification API when browser tab is not focused
- [x] In-dashboard notification bell with unread count badge
- [x] Notification dropdown shows last 50 notifications with timestamp, type, and summary
- [ ] Click on notification navigates to relevant gadget (audit trail for governance, session manager for session events)
- [x] Notification priority levels: info (blue), warning (yellow), error (red), critical (pulsing red)
- [x] "Mark all read" and per-notification dismiss controls
- [ ] Notification sound (configurable, default: off) for critical priority
US-011: Personal Productivity Gadgets (P2)
As a developer I want to see prayer times, language flashcards, and timers alongside orchestrata gadgets So that I have a unified personal command center without switching between apps
Acceptance Criteria:
- [x] PrayerTimes gadgets (prayer_vizint, prayertimes-chronus) display next prayer with countdown, integrate via Chronus provider
- [x] Flashcards gadget (50KB) provides Italian/Arabic language learning with CSV data
- [x] Iqama-countdown gadget (31KB) provides prayer time countdown timer
- [x] Time-to-POI gadget (1135 LOC) provides point-of-interest countdown
- [x] Chronus Sequencer gadget (14KB) provides timeline sequencing
- [x] Settings gadget (1125 LOC) provides settings panel for Command Center configuration
- [x] All personal gadgets respect the portal's theme (dark/light)
- [x] Personal gadgets function independently when gateway is disconnected
US-012: Theme & Layout Customization (P2)
As a developer I want to customize the dashboard theme, gadget arrangement, and save layout profiles So that the command center fits my workflow and preferences
Acceptance Criteria:
- [x] Theme toggle: dark mode and light mode via CSS variable swap
- [x] Theme preference persisted in localStorage and synced via StateSync
- [x] System preference detection via
prefers-color-schememedia query - [x] Gadget grid layout: drag to reposition, resize handles on gadget chrome
- [x] Gadget minimize to titlebar-only, maximize to full viewport, wide (2-column span)
- [x] Named layout profiles: save current arrangement as a named profile
- [x] Switch between profiles via dropdown (e.g., "Monitoring", "Development")
- [x] Default profile auto-loads on startup
- [ ] Reset to default layout button
US-013: Gateway Session Handlers (P1)
As a Command Center frontend I want to call session and project RPC methods backed by Neo4j So that I can display real-time session and project data without direct database access
Acceptance Criteria:
- [x]
session.activereturns current active session info - [x]
session.listreturns all active sessions - [x]
session.getreturns session by ID with context and facts - [x]
session.opencreates a new session with type and metadata - [x]
session.closecloses a session by ID - [x]
session.eventssubscribes to session lifecycle events - [x]
session.facts.subscribesubscribes to fact emissions - [x] All session RPC calls backed by Neo4j with async queries and 10s timeouts
US-014: Gateway Project Handlers (P1)
As a Command Center frontend I want to query project data, tasks, and create tasks via RPC So that the ProjectExplorer and TaskBoard gadgets have backend support
Acceptance Criteria:
- [x]
projects.listreturns projects from Neo4j (name, path, status, language) - [x]
projects.getreturns project by name with tasks and sessions - [x]
projects.tasksreturns tasks with filtering by status (limit 1000) - [x]
projects.taskCreatecreates a task in Neo4j - [x] All project RPC calls backed by Neo4j with async queries and 10s timeouts
Functional Requirements
Core Platform
FR-001: WebSocket Bridge (P1)
- System SHALL establish a WebSocket connection to the SPEC-014 gateway on CommandCenterApp initialization
- System SHALL authenticate using the configured auth strategy (static token from user settings)
- System SHALL implement JSON-RPC 2.0 over WebSocket with request ID prefix
cc-req-{monotonic_counter} - System SHALL automatically reconnect on disconnect with exponential backoff (1s, 2s, 4s, max 30s)
- System SHALL display connection status indicator in the dashboard header (connected/reconnecting/disconnected)
- System SHALL queue outbound RPC calls during reconnection (max 100 in queue, oldest discarded on overflow) and flush on successful reconnect
FR-002: State Synchronization (P1)
- System SHALL synchronize shared settings (theme, layout, notification preferences) via gateway state RPC
- System SHALL use localStorage as the primary cache with WebSocket-backed remote persistence
- System SHALL resolve conflicts using last-write-wins with client timestamps
- System SHALL batch state sync writes with 500ms debounce to avoid excessive RPC calls
- System SHALL fall back to localStorage-only mode when gateway is disconnected
FR-003: Gadget Bridge (P1)
- System SHALL translate gadget-local
ctx.busevents to gateway JSON-RPC 2.0 method calls - System SHALL translate gateway push notifications to gadget-local
ctx.busevents - System SHALL maintain a mapping table from bus event types to RPC methods across five namespaces:
session.*,cxp.*,volk.*,knowledge.*,governance.* - System SHALL provide a
GadgetBridge.call(method, params)API returning a Promise for RPC responses - System SHALL provide a
GadgetBridge.subscribe(topic, filters, callback)API for event streams
FR-004: Gadget Registry (P1)
- System SHALL maintain a registry of available gadgets with manifest metadata
- System SHALL support dynamic gadget loading via ES module
import()from registry URLs with basePath parameter - System SHALL validate gadget manifests against a schema (id, name, version, entry, dependencies)
- System SHALL resolve gadget dependencies before mounting (e.g., KGExplorer depends on WebSocketBridge)
- System SHALL support gadget hot-reload for development (file watcher + re-import)
FR-005: Notification Manager (P1)
- System SHALL subscribe to escalation events via
governance.decisionstopic (where result includes escalation) - System SHALL subscribe to error events via
kernel.eventstopic (where severity >= warning) - System SHALL subscribe to session events via
session.eventstopic (where type = decision_needed) - System SHALL display in-dashboard notifications with priority-based styling
- System SHALL request desktop notification permission and send Notification API alerts for critical events
- System SHALL store a maximum of 200 notifications, discarding oldest on overflow
FR-006: Theming Engine (P1)
- System SHALL support light and dark themes via CSS custom properties (--bg-primary, --text-primary, etc.)
- System SHALL persist theme preference in localStorage under
commandcenter.theme - System SHALL apply theme on page load before first paint (no flash of unstyled content)
- System SHALL emit
theme.changedevent onctx.busso gadgets can react to theme changes - System SHALL respect
prefers-color-schememedia query as the default when no preference is saved - System SHALL support toggle via UI control in the dashboard header
FR-007: Portal Framework (P1)
- System SHALL provide
lib/portal.jsfor gadget lifecycle management (mount/unmount) - System SHALL provide
lib/bus.jsimplementing EventBus via CustomEvents withvizint:prefix and addEventListener/removeEventListener compatibility - System SHALL provide
lib/registry.jsfor dynamic gadget loading with manifest validation and basePath parameter - System SHALL provide
lib/chrome.jsfor gadget chrome: title bar, minimize/close buttons, status bar - System SHALL provide
lib/shared.jsfor utilities: generateId, debounce, formatTimestamp
Project & Session Gadgets
FR-008: ProjectExplorer Gadget (P1)
- System SHALL display project metadata by querying
knowledge.nodesRPC for the Project node - System SHALL display a file tree by querying
knowledge.nodeswith node_type=File and pagination - System SHALL display KG node counts by type (File, Class, Function, Session, Iteration, Spec)
- System SHALL display recent sessions by querying
session.listwith limit=10 - System SHALL support click-through from file to KGExplorer with file-scoped Cypher query
FR-009: SessionManager Gadget (P1)
- System SHALL display active session state by calling
session.activeandsession.getwith the active session_id - System SHALL send
session.openRPC on "Start Session" with user-provided type and metadata - System SHALL send
session.closeRPC on "Close Session" with session ID - System SHALL subscribe to
session.eventsfor real-time session state updates - System SHALL subscribe to
session.facts.subscribefor fact emissions - System SHALL display deferred work items from session context with inline edit capabilities
FR-010: TaskBoard Gadget (P1)
- System SHALL display tasks in a kanban board layout with three columns: Not Started, In Progress, Completed
- System SHALL support drag-and-drop between columns, sending status update RPCs
- System SHALL support creating new tasks via
projects.taskCreateRPC - System SHALL query tasks via
projects.tasksRPC with status filtering (limit 1000) - System SHALL synchronize task state with the gateway
FR-011: RTM Viewer Gadget (P2)
- System SHALL query
knowledge.queryfor Spec and Requirement nodes with traceability relationships - System SHALL display requirements grouped by specification with verified/unverified status
- System SHALL show RTM coverage as a progress bar per spec and overall
- System SHALL support filtering by spec, verification status, and keyword search
- System SHALL link requirements to their traced test files via knowledge graph relationships
Real-Time Monitoring Gadgets
FR-012: CXP Feed Gadget (P1)
- System SHALL subscribe to
cxp.traffictopic via GadgetBridge on gadget mount - System SHALL render CXP packets as a virtualized scrolling list (render only visible rows for performance)
- System SHALL support client-side filtering by volk, thread, subject pattern, and delivery status
- System SHALL pause auto-scroll when user scrolls up, resume on scroll-to-bottom
- System SHALL display packet throughput (packets/sec) as a live counter in the gadget titlebar
FR-013: Volk Status Gadget (P1)
- System SHALL call
volk.liston mount and subscribe tovolk.lifecyclefor real-time updates - System SHALL render each volk as a card with alias, role, health indicator (green/yellow/red dot), and current task
- System SHALL animate health changes with CSS transitions (color fade over 300ms)
- System SHALL support compact mode (horizontal bars) for narrow viewports (< 400px gadget width)
- System SHALL display volk detail panel on card click with full metadata from
volk.get
FR-014: QA Dashboard Gadget (P1)
- System SHALL display current test count, pass rate, coverage percentage, and total test duration from project metrics
- System SHALL render coverage and duration trends as sparkline charts using Canvas 2D API
- System SHALL display gate status per iteration with pass/fail/partial indicators
- System SHALL show failed test details (name, duration_ms, assertion, location) in an expandable section
- System SHALL highlight slowest 10 tests by duration with regression indicator (>20% slower than previous run)
- System SHALL update test results in real-time via
kernel.eventssubscription (test_completed events)
FR-015: Audit Trail Gadget (P1)
- System SHALL query
governance.querywith filters for historical governance decisions - System SHALL render audit events in a sortable, paginated table (50 items per page)
- System SHALL support full-text search across all audit fields
- System SHALL highlight constitutional article violations with article reference and severity
- System SHALL support CSV and JSON export of filtered audit results
Interaction Gadgets
FR-016: Claude Chat Gadget (P1)
- System SHALL provide a chat interface with message input area, send button, and scrollable message history
- System SHALL send chat messages via
cxp.sendRPC with a dedicated chat thread_id - System SHALL receive responses via
cxp.trafficsubscription filtered to the chat thread - System SHALL render markdown in responses using a lightweight markdown parser (code blocks, lists, bold, links)
- System SHALL persist chat history in localStorage (last 100 messages per thread) with StateSync backup
FR-017: Task Board Interactions (P1)
- System SHALL support inline task editing (click-to-edit title, description, priority)
- System SHALL support task deletion with confirmation dialog
- System SHALL support task assignment to a specific volk via dropdown
- System SHALL display task history (status changes, comments) in a detail panel
- System SHALL link tasks to CXP threads for traceability
FR-018: Metrics Dashboard Gadget (P2)
- System SHALL display key project metrics: test count, coverage, LOC, file count, requirement coverage
- System SHALL render metrics as cards with current value and delta since last session
- System SHALL display a version history timeline (version bumps from context.json)
- System SHALL auto-refresh metrics every 60 seconds
- System SHALL support drill-down from metric card to relevant gadget (test count -> QA dashboard)
Knowledge & Data Gadgets
FR-019: Knowledge Graph Explorer Gadget (P2)
- System SHALL render a force-directed graph using Canvas 2D API with WebGL fallback for large graphs
- System SHALL color nodes by type using the portal's theme palette
- System SHALL support zoom (scroll wheel), pan (mouse drag on background), and node drag
- System SHALL execute Cypher queries via
knowledge.queryRPC with results rendered as graph and table - System SHALL provide a Cypher input with syntax highlighting and node-type auto-complete
FR-020: RTM Coverage Viewer (P2)
- System SHALL query knowledge graph for Spec, Story, and Requirement nodes with TRACES relationships
- System SHALL display coverage as a hierarchical tree: Spec > Story > Requirement
- System SHALL color-code requirements: green (verified), red (unverified), yellow (partial)
- System SHALL display overall RTM coverage percentage in the gadget titlebar
- System SHALL support filtering by spec and verification status
FR-021: Session History Gadget (P2)
- System SHALL query session archive for all historical sessions
- System SHALL display sessions in a timeline view (vertical, newest on top)
- System SHALL show per-session: date, duration, achievements, deferred work, test delta
- System SHALL support search across session achievements and descriptions
- System SHALL support date-range filtering
FR-022: Iteration Browser Gadget (P2)
- System SHALL query knowledge graph for Iteration nodes with relationships to Session and TestRun
- System SHALL display iterations in a list with: number, date, gap count, test delta
- System SHALL show iteration detail: scenario, gaps with remedies, conversation summary
- System SHALL link iterations to their parent session
- System SHALL highlight iterations with unresolved gaps
Personal & Specialized Gadgets
FR-023: Prayer Times Gadgets (P2)
- System SHALL provide
prayer_vizintgadget for prayer times display - System SHALL provide
prayertimes-chronusgadget integrating via Chronus time provider - System SHALL provide
iqama-countdowngadget (31KB) for prayer time countdown timer - System SHALL display next prayer name and countdown timer
- System SHALL display all five daily prayer times in a compact table
FR-024: Language & Learning Gadgets (P2)
- System SHALL provide
flashcardsgadget (50KB) for Italian/Arabic language learning - System SHALL load vocabulary data from CSV files
- System SHALL support card flipping, progress tracking, and review scheduling
FR-025: Timeline & Utility Gadgets (P2)
- System SHALL provide
chronus_sequencergadget (14KB) for Chronus timeline sequencing - System SHALL provide
time-to-poigadget (1135 LOC) for point-of-interest countdown - System SHALL provide
runway-viewportgadget (356 LOC) for timeline visualization - System SHALL provide
chronus-devgadget for Chronus development tools - System SHALL provide
atlas-debuggadget for Atlas debugging - System SHALL provide
dailygadget for daily overview - System SHALL provide
worldtzgadget for world timezone display - System SHALL provide
eomgadget for end-of-month tracking
FR-026: Embedding & Extension Gadgets (P2)
- System SHALL provide
embed.jsandembed-web.jsgadgets for web iframe embedding - System SHALL provide
helloworld,helloworld2, andhelloworld-settingsas example gadgets for developers - System SHALL provide
settingsgadget (1125 LOC) as the settings panel for Command Center configuration
Gateway Handlers
FR-027: SessionHandler (P1)
- System SHALL implement
session.activeRPC method returning current active session info - System SHALL implement
session.listRPC method returning all active sessions - System SHALL implement
session.getRPC method returning session by ID with context and facts - System SHALL implement
session.openRPC method creating a new session with type and metadata - System SHALL implement
session.closeRPC method closing a session by ID - System SHALL implement
session.eventsRPC method for subscribing to session events - System SHALL implement
session.facts.subscribeRPC method for subscribing to fact emissions - System SHALL back all session methods with Neo4j knowledge graph via async queries with 10s timeout
FR-028: ProjectsHandler (P1)
- System SHALL implement
projects.listRPC method returning projects from Neo4j (name, path, status, language) - System SHALL implement
projects.getRPC method returning project by name with tasks and sessions - System SHALL implement
projects.tasksRPC method returning tasks with filtering by status (limit 1000) - System SHALL implement
projects.taskCreateRPC method creating a task in Neo4j - System SHALL back all project methods with Neo4j knowledge graph via async queries with 10s timeout
Non-Functional Requirements
Performance
NFR-001: Responsiveness
- Gadget initial render: < 100ms from mount
- WebSocket reconnect: < 3s after disconnect detection
- RPC call round-trip (gateway): < 200ms p95 (including network)
- CXP feed scroll: 60fps during continuous packet stream
- Theme switch: < 50ms with no visible flicker
Reliability
NFR-002: Offline Resilience
- Offline-first: all gadget state cached in localStorage
- Graceful degradation: read-only mode when gateway is disconnected
- Connection status visible at all times (header indicator)
- Queued RPC calls flushed on reconnect (max queue: 100 calls, oldest discarded)
- No data loss on browser refresh (localStorage persistence)
Accessibility
NFR-003: WCAG 2.1 AA Compliance
- Keyboard navigation: all gadget controls accessible via Tab/Enter/Escape
- Screen reader support: ARIA labels on all interactive elements and live regions
- Color contrast ratio: minimum 4.5:1 for text, 3:1 for large text
- Focus indicators visible on all interactive elements
- No information conveyed by color alone (icons/text supplementary)
Performance Budget
NFR-004: Bundle and Runtime
- Initial page load: < 2MB total (HTML + CSS + JS + assets)
- Gadgets lazy-loaded on demand (not included in initial bundle)
- Maximum gadget bundle size: 200KB per gadget (uncompressed)
- Memory usage: < 100MB with 10 gadgets active
- 60fps scrolling and animation in all gadgets
Extensibility
NFR-006: Plugin Gadgets
- Third-party gadgets loadable via manifest URL pointing to an ES module
- Gadget sandboxing: gadgets run in same origin but with restricted
ctx.bustopic access - Plugin manifest schema documented and validated before load
- Gadget API versioned:
CommandCenter.API_VERSIONchecked against manifestmin_api_version - Broken gadgets cannot crash the portal (error boundary per gadget mount)
Technical Design
Architecture
+------------------------------------------------------------------------+
| VizInt Command Center (Browser) |
+------------------------------------------------------------------------+
| |
| +------------------+ |
| | CommandCenterApp | Entry point: app.js |
| | Bootstraps 5 | Zero-build ES modules (import maps in HTML) |
| | subsystems | |
| +--------+---------+ |
| | |
| +--------v---------+ +---------------+ +--------------------+ |
| | WebSocketBridge | | GadgetBridge | | NotificationManager| |
| | JSON-RPC 2.0/WS | | bus <-> RPC | | Desktop + in-app | |
| | Auto-reconnect | | 5 namespaces: | | Subscribes to: | |
| | Exp backoff 30s | | session.* | | governance.decisions| |
| | Queue max 100 | | cxp.* | | kernel.events | |
| +------------------+ | volk.* | | session.events | |
| | knowledge.* | | Max 200 stored | |
| +------------------+ | governance.* | +--------------------+ |
| | StateSync | +---------------+ |
| | localStorage + | |
| | gateway sync | +---------------+ |
| | Debounce 500ms | | GadgetRegistry| |
| | Last-write-wins | | Dynamic load | |
| +------------------+ | Manifest valid | |
| | basePath param | |
| +---------------+ |
| |
| +---------- Portal Framework (lib/) --------------------+ |
| | portal.js - Gadget lifecycle (mount/unmount) | |
| | bus.js - EventBus via CustomEvents, vizint: prefix | |
| | registry.js - Dynamic loading, manifest validation | |
| | chrome.js - Title bar, minimize/close, status bar | |
| | shared.js - generateId, debounce, formatTimestamp | |
| +--------------------------------------------------------+ |
| |
| +---------- Gadget Grid Layout ---------------------------+ |
| | | |
| | P1 Production Gadgets (10): | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | |Project | |Session | |CXP | |Volk | | |
| | |Explorer | |Manager | |Feed | |Status | | |
| | |173 LOC | |198 LOC | |161 LOC | |192 LOC | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | |Claude | |Task | |QA | |Audit | | |
| | |Chat | |Board | |Dashboard | |Trail | | |
| | |226 LOC | |224 LOC | |179 LOC | |202 LOC | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | +----------+ +----------+ | |
| | |KG | |Notif | | |
| | |Explorer | |Center | | |
| | |194 LOC | |194 LOC | | |
| | +----------+ +----------+ | |
| | | |
| | Personal/Specialized Gadgets (21): | |
| | flashcards, iqama-countdown, prayer_vizint, | |
| | time-to-poi, chronus_sequencer, settings, | |
| | embed, embed-web, runway-viewport, chronus-dev, | |
| | atlas-debug, helloworld, helloworld2, | |
| | helloworld-settings, daily, worldtz, eom, | |
| | prayertimes-chronus | |
| +----------------------------------------------------------+ |
+------------------------------------------------------------------------+
| |
v v
+--------------------+ +---------------------+
| SPEC-014 WebSocket | | External APIs |
| Gateway | | Aladhan Prayer API |
| ws://host:18790 | | (via Chronus) |
| JSON-RPC 2.0 | +---------------------+
+----+----------+----+
| |
v v
+----------+ +------------------+
| Redis | | Memgraph KG |
| 10.93. | | 10.53.2.10:7687 |
| 53.10 | | 558K+ nodes |
| Session | | 223K CXP packets |
| state, | | 156K test results|
| caching | | 6K sessions |
+----------+ | 2.7K requirements|
| 439 source files |
| 934 classes |
| 522 functions |
| 28K Prolog rules |
+------------------+
Gadget Inventory (31 Total)
P1 Production Gadgets (10 -- All Implemented)
| # | Gadget | LOC | Description | Primary RPC |
|---|---|---|---|---|
| 1 | project-explorer | 173 | Projects, KG nodes, recent sessions | knowledge.nodes |
| 2 | session-manager | 198 | Session CRUD, lifecycle management | session.* |
| 3 | cxp-feed | 161 | CXP traffic monitor | cxp.traffic subscription |
| 4 | volk-status | 192 | Agent cards with health dots | volk.list, volk.lifecycle |
| 5 | claude-chat | 226 | Chat with Claude, markdown rendering | cxp.send |
| 6 | task-board | 224 | Kanban board with drag-drop | projects.tasks, projects.taskCreate |
| 7 | qa-dashboard | 179 | QA metrics, coverage, gate status | knowledge.query |
| 8 | audit-trail | 202 | Event audit log | governance.query |
| 9 | kg-explorer | 194 | Knowledge graph exploration | knowledge.query |
| 10 | notification-center | 194 | Notification hub | governance.decisions, kernel.events |
Personal & Specialized Gadgets (21 -- All Implemented)
| # | Gadget | Size | Description |
|---|---|---|---|
| 11 | flashcards | 50KB | Italian/Arabic language learning with CSV data |
| 12 | iqama-countdown | 31KB | Prayer time countdown timer |
| 13 | prayer_vizint | -- | Prayer times display |
| 14 | time-to-poi | 1135 LOC | Point-of-interest countdown |
| 15 | chronus_sequencer | 14KB | Chronus timeline sequencer |
| 16 | settings | 1125 LOC | Settings panel |
| 17 | embed | -- | Iframe embedding (native) |
| 18 | embed-web | -- | Iframe embedding (web) |
| 19 | runway-viewport | 356 LOC | Timeline visualization |
| 20 | chronus-dev | -- | Chronus development tools |
| 21 | atlas-debug | -- | Atlas debugging |
| 22 | helloworld | -- | Example gadget |
| 23 | helloworld2 | -- | Example gadget (variant) |
| 24 | helloworld-settings | -- | Example gadget with settings |
| 25 | daily | -- | Daily overview |
| 26 | worldtz | -- | World timezone display |
| 27 | eom | -- | End-of-month tracking |
| 28 | prayertimes-chronus | -- | Prayer times via Chronus provider |
Package Structure
The VizInt Command Center is a pure JavaScript frontend -- no Python backend package. The SPEC-014 WebSocket Gateway serves as the backend. The frontend connects directly to the gateway over WebSocket.
vizint-ui/ # Root directory (VizInt portal)
|-- index.html # Entry point (import maps, zero-build)
|-- app.js # CommandCenterApp bootstraps 5 subsystems
|-- lib/ # Portal framework
| |-- portal.js # Gadget lifecycle (mount/unmount)
| |-- bus.js # EventBus via CustomEvents, vizint: prefix
| |-- registry.js # Dynamic gadget loading, manifest validation
| |-- chrome.js # Title bar, minimize/close, status bar
| |-- shared.js # generateId, debounce, formatTimestamp
| |-- atlas.js # Geolocation service
| +-- chronus.js # Time engine
|-- bridge/ # Gateway bridge layer
| |-- websocket-bridge.js # WebSocket connection + JSON-RPC 2.0
| |-- gadget-bridge.js # ctx.bus <-> gateway translation
| |-- state-sync.js # localStorage + remote sync (500ms debounce)
| +-- notification-manager.js # Desktop + in-app notifications (max 200)
|-- gadgets/ # 31 gadget modules
| |-- project-explorer/ # US-001 (173 LOC)
| |-- session-manager/ # US-002 (198 LOC)
| |-- cxp-feed/ # US-003 (161 LOC)
| |-- volk-status/ # US-004 (192 LOC)
| |-- claude-chat/ # US-005 (226 LOC)
| |-- task-board/ # US-006 (224 LOC)
| |-- qa-dashboard/ # US-007 (179 LOC)
| |-- audit-trail/ # US-008 (202 LOC)
| |-- kg-explorer/ # US-009 (194 LOC)
| |-- notification-center/ # US-010 (194 LOC)
| |-- flashcards/ # 50KB, Italian/Arabic flashcards
| |-- iqama-countdown/ # 31KB, prayer countdown
| |-- prayer_vizint/ # Prayer times
| |-- time-to-poi/ # 1135 LOC, POI countdown
| |-- chronus_sequencer/ # 14KB, timeline sequencer
| |-- settings/ # 1125 LOC, settings panel
| |-- embed/ # Iframe embedding
| |-- embed-web/ # Web iframe embedding
| |-- runway-viewport/ # 356 LOC, timeline viz
| |-- chronus-dev/ # Chronus dev tools
| |-- atlas-debug/ # Atlas debugging
| |-- helloworld/ # Example gadget
| |-- helloworld2/ # Example gadget variant
| |-- helloworld-settings/ # Example with settings
| |-- daily/ # Daily overview
| |-- worldtz/ # World timezone
| |-- eom/ # End-of-month
| +-- prayertimes-chronus/ # Prayer times via Chronus
|-- styles/
| |-- common.css # CSS variables, colors, shadows, fonts
| | # Light/dark theme (system pref + toggle)
| +-- command-center.css # CSS Grid layout, header, gadget chrome, badges
|-- providers/
| |-- chronus_civil_provider.js
| +-- chronus_prayerTimes_provider.js
|-- Specs/ # 23 internal spec files
| |-- chronus-anchors/
| |-- portal-1.1/ through portal-1.3/
| |-- atlas/
| +-- gadget-specs/
|-- res/ # Assets
|-- configs/
| +-- command-center.json # Runtime configuration
+-- tests/ # Frontend tests
|-- vitest.config.js
|-- unit/ # Vitest unit tests
+-- e2e/ # Playwright E2E tests
packages/orchestrata-gateway/ # Backend gateway handlers
|-- src/orchestrata/gateway/
| |-- handlers/
| | |-- session.py # SessionHandler (7 RPC methods)
| | +-- projects.py # ProjectsHandler (4 RPC methods)
| |-- server.py
| |-- session.py
| +-- rpc.py
Gateway Handler Design
SessionHandler (handlers/session.py)
class SessionHandler:
"""Handles session.* RPC methods for the Command Center."""
async def session_active(self, params: dict) -> dict:
"""Get current active session info."""
async def session_list(self, params: dict) -> dict:
"""List all active sessions."""
async def session_get(self, params: dict) -> dict:
"""Get session by ID with context and facts."""
async def session_open(self, params: dict) -> dict:
"""Create new session with type and metadata."""
async def session_close(self, params: dict) -> dict:
"""Close session by ID."""
async def session_events(self, params: dict) -> dict:
"""Subscribe to session lifecycle events."""
async def session_facts_subscribe(self, params: dict) -> dict:
"""Subscribe to fact emissions."""
ProjectsHandler (handlers/projects.py)
class ProjectsHandler:
"""Handles projects.* RPC methods for the Command Center."""
async def projects_list(self, params: dict) -> dict:
"""List projects from Neo4j (name, path, status, language)."""
async def projects_get(self, params: dict) -> dict:
"""Get project by name with tasks and sessions."""
async def projects_tasks(self, params: dict) -> dict:
"""List tasks with filtering by status (limit 1000)."""
async def projects_task_create(self, params: dict) -> dict:
"""Create task in Neo4j."""
Both handlers are backed by the Neo4j knowledge graph via async queries with 10-second timeouts.
Styles
common.css: Defines CSS custom properties for the full design system:
- Color tokens (--bg-primary, --text-primary, --accent, --border, etc.)
- Shadow tokens (--shadow-sm, --shadow-md, --shadow-lg)
- Font tokens (--font-family, --font-size-sm/md/lg)
- Light theme (default) and dark theme via
[data-theme="dark"]selector - System preference detection via
@media (prefers-color-scheme: dark) - Toggle support via JavaScript
data-themeattribute on<html>
command-center.css: Layout and component styles:
- CSS Grid for the gadget layout (auto-fill, minmax columns)
- Header bar with connection status, theme toggle, notification bell
- Gadget chrome: border, title bar, minimize/close buttons, status bar
- Badge styles for notification counts and status indicators
- Responsive breakpoints for mobile and tablet
For testing requirements, see ## Testing.
Key Interfaces
/**
* CommandCenterApp -- Top-level application entry point (app.js).
* Bootstraps 5 subsystems: WebSocketBridge, GadgetBridge,
* StateSync, NotificationManager, GadgetRegistry.
*/
class CommandCenterApp {
/** Initialize: connect gateway, load registry, apply theme. */
async initialize(config) {}
/** Mount all default gadgets into the grid layout. */
async mountDefaultLayout() {}
/** Shut down: disconnect gateway, persist state, unmount gadgets. */
async shutdown() {}
/** Get the WebSocket bridge instance. */
getWebSocketBridge() {}
/** Get the gadget registry instance. */
getGadgetRegistry() {}
/** Get the notification manager instance. */
getNotificationManager() {}
/** Get the state sync instance. */
getStateSync() {}
}
/**
* WebSocketBridge -- Manages the WebSocket connection to SPEC-014 gateway.
* JSON-RPC 2.0 over WebSocket with auto-reconnect (exponential backoff,
* max 30s) and request queue (max 100).
*/
class WebSocketBridge {
/**
* Connect to the gateway.
* @param {string} url - WebSocket URL (e.g., "ws://10.53.2.13:8765")
* @param {Object} authCredentials - Auth payload for auth.authenticate
* @returns {Promise<void>}
*/
async connect(url, authCredentials) {}
/**
* Send an RPC call and return the result.
* @param {string} method - RPC method name (e.g., "session.active")
* @param {Object} params - Method parameters
* @returns {Promise<Object>} - JSON-RPC result
*/
async call(method, params) {}
/**
* Subscribe to a gateway event topic.
* @param {string} topic - Event topic (e.g., "cxp.traffic")
* @param {Object} filters - Subscription filters
* @param {Function} callback - Called with each event payload
* @returns {Promise<string>} - Subscription ID
*/
async subscribe(topic, filters, callback) {}
/**
* Unsubscribe from a topic.
* @param {string} subscriptionId - Subscription ID from subscribe()
* @returns {Promise<void>}
*/
async unsubscribe(subscriptionId) {}
/** Disconnect from the gateway. */
async disconnect() {}
/** Get current connection state: "connected" | "reconnecting" | "disconnected". */
getState() {}
/**
* Register a connection state change listener.
* @param {Function} listener - Called with new state string
*/
onStateChange(listener) {}
}
/**
* GadgetBridge -- Translates between portal ctx.bus events and
* gateway RPC/subscriptions across 5 namespaces.
*/
class GadgetBridge {
/**
* Map a ctx.bus event type to a gateway RPC call.
* @param {string} busEventType - Portal bus event name
* @param {string} rpcMethod - Gateway RPC method
* @param {Function} paramsMapper - Transforms bus event detail to RPC params
*/
mapEventToRPC(busEventType, rpcMethod, paramsMapper) {}
/**
* Map a gateway subscription topic to a ctx.bus event type.
* @param {string} topic - Gateway event topic
* @param {string} busEventType - Portal bus event name to emit
* @param {Function} payloadMapper - Transforms gateway payload to bus detail
*/
mapSubscriptionToEvent(topic, busEventType, payloadMapper) {}
/**
* Convenience: call an RPC method and return result.
* @param {string} method - RPC method
* @param {Object} params - Parameters
* @returns {Promise<Object>}
*/
async call(method, params) {}
/**
* Convenience: subscribe to topic with callback.
* @param {string} topic - Event topic
* @param {Object} filters - Subscription filters
* @param {Function} callback - Event callback
* @returns {Promise<string>} - Subscription ID
*/
async subscribe(topic, filters, callback) {}
}
/**
* StateSync -- Synchronizes application state between localStorage
* and gateway. Debounced 500ms, last-write-wins conflict resolution.
*/
class StateSync {
/**
* Get a value (checks localStorage first, then remote).
* @param {string} key - State key
* @returns {*} - Stored value or null
*/
get(key) {}
/**
* Set a value (writes to localStorage immediately,
* debounced sync to gateway after 500ms).
* @param {string} key - State key
* @param {*} value - Value to store (must be JSON-serializable)
*/
set(key, value) {}
/**
* Delete a value from both localStorage and remote.
* @param {string} key - State key
*/
delete(key) {}
/**
* Force a full sync from remote to local.
* @returns {Promise<void>}
*/
async pullRemote() {}
/**
* Force a full sync from local to remote.
* @returns {Promise<void>}
*/
async pushLocal() {}
}
/**
* EventBus (lib/bus.js) -- Portal event system.
* CustomEvents with vizint: prefix, addEventListener/removeEventListener
* compatibility.
*/
class EventBus {
/**
* Emit an event on the bus.
* @param {string} type - Event type (vizint: prefix added automatically)
* @param {Object} detail - Event payload
*/
emit(type, detail) {}
/**
* Subscribe to an event type.
* @param {string} type - Event type
* @param {Function} handler - Event handler
*/
on(type, handler) {}
/**
* Unsubscribe from an event type.
* @param {string} type - Event type
* @param {Function} handler - Event handler
*/
off(type, handler) {}
}
/**
* NotificationManager -- Desktop + in-app notifications.
* Subscribes to governance.decisions, kernel.events, session.events.
* Max 200 stored notifications.
*/
class NotificationManager {
/**
* Add a notification.
* @param {NotificationEntry} entry - Notification to add
*/
add(entry) {}
/**
* Get all stored notifications.
* @returns {NotificationEntry[]}
*/
getAll() {}
/**
* Mark a notification as read.
* @param {string} id - Notification ID
*/
markRead(id) {}
/**
* Mark all notifications as read.
*/
markAllRead() {}
/**
* Get unread count.
* @returns {number}
*/
getUnreadCount() {}
}
/**
* GadgetManifest -- Metadata for a gadget in the registry.
*/
const GadgetManifest = {
id: "string", // Unique gadget identifier
name: "string", // Display name
version: "string", // Semver version
description: "string", // Short description
entry: "string", // ES module URL (relative to gadgets/)
icon: "string", // Icon identifier or SVG path
category: "string", // "orchestrata" | "productivity" | "plugin"
dependencies: ["string"], // Required provider/bridge IDs
min_api_version: "string", // Minimum CommandCenter API version
default_size: { // Default grid size
columns: 1, // 1-4 columns
rows: 1, // 1-4 rows
},
supports_multi_instance: false, // Whether multiple instances are allowed
config_schema: {}, // JSON Schema for gadget-specific settings
};
/**
* NotificationEntry -- A single notification in the notification center.
*/
const NotificationEntry = {
id: "string", // Unique notification ID
timestamp: "ISO8601 string", // When the notification was created
type: "string", // "escalation" | "error" | "decision_needed" | "info"
priority: "string", // "info" | "warning" | "error" | "critical"
title: "string", // Short notification title
body: "string", // Notification body text
source_topic: "string", // Gateway topic that generated this
source_event: {}, // Original gateway event payload
read: false, // Whether the user has seen this
gadget_target: "string|null", // Gadget ID to navigate to on click
};
WebSocket Bridge Protocol
The WebSocket bridge maps directly to SPEC-014 JSON-RPC 2.0:
Outbound (browser -> gateway):
{
"jsonrpc": "2.0",
"id": "cc-req-001",
"method": "session.active",
"params": {}
}
Inbound response (gateway -> browser):
{
"jsonrpc": "2.0",
"id": "cc-req-001",
"result": {
"session_id": "session-089",
"session_number": 89,
"status": "active",
"started_at": "2026-03-29T08:00:00Z"
}
}
Inbound push (gateway -> browser):
{
"jsonrpc": "2.0",
"method": "cxp.traffic",
"params": {
"sequence": 142,
"timestamp": "2026-03-29T10:30:22Z",
"payload": {
"to": "U:Cd",
"from": "U:Ox",
"thread_id": "thread-042",
"subject": "code_review_result",
"delivery_status": "delivered"
}
}
}
Request ID generation: cc-req-{monotonic_counter} -- prefixed to distinguish from other gateway clients.
Reconnection protocol:
- WebSocket
closeevent detected - State set to
reconnecting, indicator updated - Exponential backoff: 1s, 2s, 4s, 8s, 16s, max 30s
- On connect: re-authenticate, re-subscribe all active subscriptions
- State set to
connected, flush queued RPC calls (max 100 in queue) - Emit
gateway.reconnectedonctx.bus
State Sync Protocol
State synchronization uses a simple key-value model:
Local write (immediate):
stateSync.set("theme", "dark");
// 1. Write to localStorage immediately: commandcenter.state.theme = "dark"
// 2. Debounce 500ms, then send to gateway:
Remote sync (debounced):
{
"jsonrpc": "2.0",
"id": "cc-req-042",
"method": "state.set",
"params": {
"key": "commandcenter.state.theme",
"value": "dark",
"timestamp": "2026-03-29T10:30:22.456Z"
}
}
Conflict resolution: Last-write-wins based on timestamp. On reconnect, state.pull retrieves all remote state; keys with newer remote timestamps overwrite local.
Redis-Backed Shared State
State sync persists through the gateway to Redis:
orchestrata:commandcenter:state:{client_id}:{key} -- HASH {value, timestamp}
orchestrata:commandcenter:state:{client_id}:keys -- SET of all keys
TTL: None (persistent until explicitly deleted).
Configuration
Runtime configuration via configs/command-center.json:
{
"gateway": {
"url": "ws://10.53.2.13:8765",
"auth_strategy": "static_token",
"reconnect_max_interval_seconds": 30,
"rpc_timeout_seconds": 10,
"rpc_queue_max": 100
},
"state_sync": {
"debounce_ms": 500,
"conflict_resolution": "last_write_wins"
},
"notifications": {
"desktop_enabled": true,
"max_stored": 200
},
"layout": {
"default_profile": "development",
"profiles": {
"development": {
"gadgets": [
{"id": "orchestrata-session-manager", "position": {"col": 0, "row": 0}, "size": {"columns": 1, "rows": 1}},
{"id": "orchestrata-cxp-feed", "position": {"col": 1, "row": 0}, "size": {"columns": 2, "rows": 2}},
{"id": "orchestrata-volk-status", "position": {"col": 3, "row": 0}, "size": {"columns": 1, "rows": 1}},
{"id": "orchestrata-claude-chat", "position": {"col": 0, "row": 1}, "size": {"columns": 1, "rows": 2}},
{"id": "orchestrata-task-board", "position": {"col": 3, "row": 1}, "size": {"columns": 1, "rows": 1}}
]
},
"monitoring": {
"gadgets": [
{"id": "orchestrata-cxp-feed", "position": {"col": 0, "row": 0}, "size": {"columns": 2, "rows": 2}},
{"id": "orchestrata-volk-status", "position": {"col": 2, "row": 0}, "size": {"columns": 2, "rows": 1}},
{"id": "orchestrata-qa-dashboard", "position": {"col": 2, "row": 1}, "size": {"columns": 2, "rows": 1}},
{"id": "orchestrata-audit-trail", "position": {"col": 0, "row": 2}, "size": {"columns": 4, "rows": 1}}
]
}
}
},
"theme": {
"default": "system"
},
"gadgets": {
"registry_path": "gadgets/",
"max_instances": 20,
"hot_reload": false
}
}
Integration Points
| Component | Integration |
|---|---|
| SPEC-014 WebSocket Gateway | Primary data channel -- all RPC calls and event subscriptions |
| VizInt Portal Framework | Gadget lifecycle, chrome, ctx.bus, providers, grid layout |
| orchestrata-session | Session management via session.* RPC methods (7 methods) |
| orchestrata-cxp | CXP traffic observation via cxp.* RPC methods |
| orchestrata-governance | Governance decisions via governance.* RPC methods |
| orchestrata-knowledge | Knowledge graph queries via knowledge.* RPC methods |
| orchestrata-kernel | Kernel events via kernel.events subscription |
| SessionHandler | handlers/session.py -- Neo4j-backed session RPC |
| ProjectsHandler | handlers/projects.py -- Neo4j-backed project/task RPC |
| context.json | Deferred work and session state (read via session RPC) |
| Redis (test fleet 10.53.2.11; from active env profile) | State sync persistence, notification storage, session caching |
Memgraph KG (test fleet 10.53.2.10:7687, orchkg database) |
Knowledge graph (558K+ nodes), project data, task storage |
| Aladhan Prayer API | Prayer time calculations (via Chronus provider) |
Knowledge Graph Statistics
The Memgraph knowledge graph backing the Command Center contains:
| Category | Count |
|---|---|
| Total nodes | 558K+ |
| CXP packets | 223K |
| Test results | 156K |
| Sessions | 6K |
| Requirements | 2.7K |
| User stories | 147 |
| Source files | 439 |
| Classes | 934 |
| Functions | 522 |
| Packages | 23 |
| Prolog rules | 28K |
Deployment
| Component | Address | Details |
|---|---|---|
| VizInt UI | http://10.53.2.13:5000 (test fleet example) |
python3 -m http.server 5000 on container |
| WebSocket Gateway | ws://10.53.2.13:8765 (test fleet example) |
SPEC-014 gateway, JSON-RPC 2.0 |
| Redis | 10.53.2.11 (test fleet) |
Session state, caching |
| Memgraph KG | 10.53.2.10:7687 (test fleet) |
Knowledge graph (558K+ nodes), orchkg database |
Endpoints come from the active env profile (ORCHESTRATA_ENV_PROFILE, default test); the addresses above are the test fleet (10.53.2.x).
Development mode: Set GATEWAY_ALLOW_ANONYMOUS=true to bypass authentication.
Verified: Playwright E2E tests on Firefox confirm full connection lifecycle, gadget rendering, theme toggle, and WebSocket state management.
Internal Specs Directory
The vizint-ui/Specs/ directory contains 23 internal specification files:
- Chronus anchor specifications
- Portal version specs (1.1 through 1.3)
- Atlas geolocation specs
- Individual gadget specifications
These are internal to the VizInt portal framework and pre-date the Orchestrata spec system.
Success Criteria
- Gateway Connection: Command Center connects to SPEC-014 gateway at
ws://10.53.2.13:8765, authenticates, and maintains connection with automatic reconnection (exponential backoff, max 30s) - Real-Time Visualization: CXP traffic, volk lifecycle events, and governance decisions displayed in their respective gadgets within 200ms of occurrence
- Session Control: Users can start, close, and manage sessions entirely through the dashboard via
session.*RPC methods without CLI commands - Task Management: Tasks created and managed through the dashboard via
projects.*RPC methods with Neo4j backing - Claude Chat: Users can converse with Claude through the chat gadget (226 LOC) with markdown rendering and thread management
- QA Visibility: Test results, coverage trends, and gate status visible and updated in real-time
- Notifications: Escalations and decision requests surface as desktop and in-dashboard notifications within 1 second (max 200 stored)
- Offline Resilience: Dashboard functions in read-only mode when gateway is disconnected, using cached localStorage state
- Performance: Initial load < 2MB, gadget render < 100ms, 60fps scrolling, < 100MB memory with 10 active gadgets
- Gadget Coverage: All 10 P1 production gadgets and 21 personal/specialized gadgets implemented and functional
- Gateway Handlers: SessionHandler (7 methods) and ProjectsHandler (4 methods) operational with Neo4j backing and 10s timeouts
- Test Coverage: Playwright E2E tests (11+ on Firefox) and Vitest unit tests for all bridge layer components pass
Visual Architecture
Class Diagram
Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 12:).
classDiagram-direction LR
class VizIntWebUI {
+__init__(host: str = 'localhost', port: int = 8765)
+async start()
+async shutdown()
+async add_project(project_data: dict[str, Any])
+async broadcast_edit_complete(file_path: str, result: dict[str, Any])
+async update_task_status(task_id: str, status: str)
+async get_projects(): list[dict[str, Any]]
}
GadgetManifest Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GadgetManifest",
"type": "object",
"required": ["id", "name", "version", "description", "entry", "category"],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z][a-z0-9-]*$",
"description": "Unique gadget identifier."
},
"name": {
"type": "string",
"description": "Human-readable display name."
},
"version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$"
},
"description": {
"type": "string",
"maxLength": 200
},
"entry": {
"type": "string",
"description": "ES module URL relative to gadgets/ directory."
},
"icon": {
"type": "string",
"description": "Icon identifier or SVG path."
},
"category": {
"type": "string",
"enum": ["orchestrata", "productivity", "plugin"]
},
"dependencies": {
"type": "array",
"items": {"type": "string"},
"description": "Required bridge or provider IDs."
},
"min_api_version": {
"type": "string",
"pattern": "^\\d+\\.\\d+\\.\\d+$"
},
"default_size": {
"type": "object",
"properties": {
"columns": {"type": "integer", "minimum": 1, "maximum": 4},
"rows": {"type": "integer", "minimum": 1, "maximum": 4}
}
},
"supports_multi_instance": {
"type": "boolean",
"default": false
},
"config_schema": {
"type": "object",
"description": "JSON Schema for gadget-specific settings."
}
},
"additionalProperties": false
}
WebSocketBridge Message Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "WebSocketBridgeOutboundMessage",
"type": "object",
"required": ["jsonrpc", "method"],
"properties": {
"jsonrpc": {"type": "string", "const": "2.0"},
"id": {
"type": "string",
"pattern": "^cc-req-\\d+$",
"description": "Client-generated request ID with cc-req- prefix."
},
"method": {"type": "string"},
"params": {"type": "object"}
}
}
StateSyncEntry Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "StateSyncEntry",
"type": "object",
"required": ["key", "value", "timestamp"],
"properties": {
"key": {
"type": "string",
"pattern": "^commandcenter\\.state\\..+$"
},
"value": {
"description": "Any JSON-serializable value."
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "Used for last-write-wins conflict resolution."
}
}
}
NotificationEntry Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "NotificationEntry",
"type": "object",
"required": ["id", "timestamp", "type", "priority", "title", "body"],
"properties": {
"id": {"type": "string"},
"timestamp": {"type": "string", "format": "date-time"},
"type": {
"type": "string",
"enum": ["escalation", "error", "decision_needed", "info"]
},
"priority": {
"type": "string",
"enum": ["info", "warning", "error", "critical"]
},
"title": {"type": "string", "maxLength": 200},
"body": {"type": "string", "maxLength": 1000},
"source_topic": {"type": "string"},
"source_event": {"type": "object"},
"read": {"type": "boolean", "default": false},
"gadget_target": {
"type": ["string", "null"],
"description": "Gadget ID to navigate to on click."
}
}
}
LayoutProfile Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "LayoutProfile",
"type": "object",
"required": ["name", "gadgets"],
"properties": {
"name": {"type": "string"},
"gadgets": {
"type": "array",
"items": {
"type": "object",
"required": ["id", "position", "size"],
"properties": {
"id": {"type": "string"},
"position": {
"type": "object",
"required": ["col", "row"],
"properties": {
"col": {"type": "integer", "minimum": 0},
"row": {"type": "integer", "minimum": 0}
}
},
"size": {
"type": "object",
"required": ["columns", "rows"],
"properties": {
"columns": {"type": "integer", "minimum": 1, "maximum": 4},
"rows": {"type": "integer", "minimum": 1, "maximum": 4}
}
}
}
}
}
}
}
Error Conditions
| ID | Condition | Handling |
|---|---|---|
| ERR-001 | WebSocket connection to SPEC-014 gateway fails on initial connect | Display connection error overlay, retry with exponential backoff (1s, 2s, 4s, 8s, 16s, max 30s) |
| ERR-002 | Authentication with gateway fails (error code -32001) | Display authentication error with gateway's data.reason, prompt user to verify token |
| ERR-003 | Gateway connection drops during operation | Transition to reconnecting state, display visual indicator, queue outbound RPC calls (max 100), attempt reconnection with exponential backoff |
| ERR-004 | Gadget ES module fails to import (404 or syntax error) | Display error boundary message within chrome frame without affecting other gadgets |
| ERR-005 | Gadget mount() lifecycle method throws exception |
Unmount gadget, log error, display error card in grid cell |
| ERR-006 | Gadget declares min_api_version higher than CommandCenter.API_VERSION |
Do not load gadget, show version mismatch warning in registry panel |
| ERR-007 | localStorage is unavailable or full | Fall back to in-memory storage, log warning, continue remote sync via gateway |
| ERR-008 | State sync detects conflict (both local and remote have newer timestamps) | Resolve via last-write-wins strategy based on timestamp |
| ERR-009 | Desktop notifications denied by browser | Fall back to in-app notifications only, do not re-prompt |
| ERR-010 | RPC call queue exceeds 100 pending requests during disconnection | Reject subsequent calls with QueueOverflowError for calling gadget to handle |
| ERR-011 | More than 20 gadgets mounted simultaneously (exceeding max_instances) |
Reject additional mounts with capacity error |
| ERR-012 | Gateway sends event for topic with no local subscribers | Silently discard event without error |
| ERR-013 | Gadget configuration fails validation against manifest config_schema |
Use default values, log configuration warning |
| ERR-014 | Reconnection exhausts all retry attempts (10 at max interval) | Display persistent connection failure banner with manual retry button |
| ERR-015 | Neo4j query in SessionHandler or ProjectsHandler exceeds 10s timeout | Return timeout error to client |
| ERR-016 | NotificationManager storage exceeds 200 entries | Discard oldest notifications to maintain cap |
Performance Requirements
- [PR-001] Initial page load (HTML + CSS + core JS) SHALL complete within 2MB total transfer size.
- [PR-002] Individual gadget render (mount to first paint) SHALL complete within 100ms.
- [PR-003] The dashboard SHALL maintain 60fps scrolling and animation performance with up to 10 active gadgets.
- [PR-004] Total browser memory consumption with 10 active gadgets SHALL remain below 100MB.
- [PR-005] WebSocket Bridge authentication and initial subscription setup SHALL complete within 500ms.
- [PR-006] RPC call round-trip (browser to gateway and back) SHALL be < 200ms at the 95th percentile over localhost.
- [PR-007] Real-time event display latency (gateway push to gadget DOM update) SHALL be < 200ms at the 95th percentile.
- [PR-008] State sync debounce delay SHALL be configurable (default: 500ms) to prevent excessive remote writes.
- [PR-009] Gadget grid layout recalculation after resize or gadget add/remove SHALL complete within 50ms.
- [PR-010] Theme toggle (light/dark) SHALL apply within 100ms without page reload.
- [PR-011] Notification classification and routing SHALL complete within 10ms per notification.
- [PR-012] Offline mode transition (gateway disconnect to read-only cached state display) SHALL complete within 1 second.
- [PR-013] Neo4j queries in SessionHandler and ProjectsHandler SHALL complete within 10 seconds (timeout enforced).
For testing requirements, see ## Testing.
Definition of Done
- [DoD-001] All acceptance criteria across all user stories (US-001 through US-014) are met and verified with automated tests.
- [DoD-002] Vitest unit test coverage >= 90% for all Command Center modules (WebSocket Bridge, Gadget Bridge, State Sync, Notification Manager, EventBus, Gadget Registry, Chrome, Shared).
- [DoD-003] Playwright E2E tests (11+ on Firefox) pass with a real browser connecting to a real SPEC-014 gateway instance.
- [DoD-004] Performance benchmarks meet or exceed all PR-001 through PR-013 thresholds under specified conditions.
- [DoD-005] This specification document is updated to reflect the final implemented design, including any deviations.
- [DoD-006] Gadget developer documentation is published, including manifest format, lifecycle hooks, Bridge API, and example gadgets (helloworld, helloworld2, helloworld-settings).
- [DoD-007] Security review completed covering: WebSocket token handling, localStorage sensitive data, CSP headers, origin validation, and XSS prevention.
- [DoD-008] All changes are backward compatible with the stated API version, or migration guidance is provided for breaking changes.
- [DoD-009] SessionHandler (7 methods) and ProjectsHandler (4 methods) are operational with Neo4j backing and 10s query timeouts.
- [DoD-010] All 31 gadgets (10 P1 production + 21 personal/specialized) load and render without errors.
Examples
Example: Command Center Initialization
import { CommandCenterApp } from './app.js';
const config = await fetch('configs/command-center.json').then(r => r.json());
const cc = new CommandCenterApp();
await cc.initialize(config);
// 1. WebSocketBridge connects to ws://10.53.2.13:8765
// 2. Authenticates with static_token
// 3. GadgetRegistry loads manifests from gadgets/
// 4. StateSync pulls remote state (debounced 500ms, last-write-wins)
// 5. NotificationManager requests desktop notification permission
await cc.mountDefaultLayout();
// Mounts gadgets from the active layout profile into the grid
// Development profile: 5 gadgets
// Monitoring profile: 4 gadgets
Example: Gadget Subscribing to CXP Events
// Inside cxp-feed.js gadget
export default class CXPFeedGadget {
async mount(ctx) {
this.bridge = ctx.resolve('GadgetBridge');
this.subscriptionId = await this.bridge.subscribe(
'cxp.traffic',
{ volk_id: 'U:Cd' },
(event) => this.renderPacket(event)
);
}
renderPacket(event) {
const row = document.createElement('div');
row.className = 'cxp-packet-row';
row.textContent = `${event.payload.from} -> ${event.payload.to}: ${event.payload.subject}`;
this.container.prepend(row);
}
async unmount() {
await this.bridge.unsubscribe(this.subscriptionId);
}
}
Example: Session RPC via Gateway Handler
// Frontend: Get active session
const result = await bridge.call('session.active', {});
// Returns: { session_id: string, session_number: number, status: string, started_at: string, ended_at: string|null, metadata: object }
// Frontend: Create a new task
const task = await bridge.call('projects.taskCreate', {
project: 'orchestrata',
title: 'Implement compact volk view',
status: 'not_started',
priority: 'medium'
});
// Returns: { task_id: string, created_at: string, updated_at: string, status: string, priority: string }
Example: State Sync Usage
// Save gadget-specific settings
stateSync.set('commandcenter.state.cxp-feed.filters', { volk_id: 'U:Cd' });
// Writes to localStorage immediately, debounced sync to gateway after 500ms
// Read settings (local-first)
const filters = stateSync.get('commandcenter.state.cxp-feed.filters');
// Returns from localStorage if available, otherwise null
Example: Notification from Governance Escalation
{
"id": "notif-2026-03-29-042",
"timestamp": "2026-03-29T10:30:22Z",
"type": "escalation",
"priority": "critical",
"title": "Governance Escalation: U:Cd budget exceeded",
"body": "CodeDirector agent exceeded token budget for session-089. Requires approval to continue.",
"source_topic": "governance.decisions",
"source_event": {
"volk_id": "U:Cd",
"action": "token_request",
"result": "escalated",
"article": "III",
"details": "Budget limit 50000 tokens exceeded (current: 52340)"
},
"read": false,
"gadget_target": "orchestrata-audit-trail"
}
Security
Client-Side Security
NFR-005: Client-Side Security
- No
eval(),new Function(), orinnerHTMLwith untrusted content - Content Security Policy headers:
script-src 'self'; style-src 'self' 'unsafe-inline' - Gateway auth token stored in sessionStorage (not localStorage) for session-scoped lifetime
- Personal API tokens encrypted with Web Crypto API before localStorage storage
- XSS prevention: all dynamic content inserted via
textContentor DOM API, neverinnerHTML GATEWAY_ALLOW_ANONYMOUS=truesupported for development mode only
Plugin Security
NFR-006: Plugin Gadgets
- Third-party gadgets loadable via manifest URL pointing to an ES module
- Gadget sandboxing: gadgets run in same origin but with restricted
ctx.bustopic access - Plugin manifest schema documented and validated before load
- Gadget API versioned:
CommandCenter.API_VERSIONchecked against manifestmin_api_version - Broken gadgets cannot crash the portal (error boundary per gadget mount)
Governance
Prolog Governance Predicates
%% Command Center client access
commandcenter_access(ClientId, dashboard) :-
gateway_access(ClientId, read_only).
commandcenter_access(ClientId, control) :-
gateway_access(ClientId, read_write).
commandcenter_access(ClientId, admin) :-
gateway_access(ClientId, admin).
%% Gadget-level permissions
commandcenter_can_mount(ClientId, GadgetId) :-
commandcenter_access(ClientId, _),
gadget_registered(GadgetId),
\+ gadget_restricted(GadgetId).
commandcenter_can_mount(ClientId, GadgetId) :-
commandcenter_access(ClientId, admin),
gadget_registered(GadgetId).
%% Restricted gadgets require elevated access
gadget_restricted('orchestrata-kg-explorer').
gadget_restricted('orchestrata-audit-trail').
%% Notification routing
commandcenter_notify(ClientId, escalation) :-
commandcenter_access(ClientId, control).
commandcenter_notify(ClientId, error) :-
commandcenter_access(ClientId, dashboard).
commandcenter_notify(ClientId, decision_needed) :-
commandcenter_access(ClientId, control).
Testing
Test Framework
Vitest Unit Tests: ESM-native, fast, Jest-compatible API
- EventBus: event emission, subscription, unsubscription, vizint: prefix
- WebSocketBridge: RPC call/response, connection state, reconnection logic
- StateSync: local/remote merge, debounce, conflict resolution
- NotificationManager: priority classification, max storage, desktop fallback
- Registry: manifest validation, dynamic loading, basePath parameter
- Chrome: title bar rendering, button handlers, status bar updates
- Shared: generateId uniqueness, debounce timing, formatTimestamp output
Playwright E2E Tests (dashboard.spec.js): 11+ tests on Firefox
- Page load and initial render
- Title and header verification
- Connection status indicator display
- Theme toggle (light <-> dark)
- Layout switching between profiles
- WebSocket connection states (connected, reconnecting, disconnected)
- Notification bell display and interaction
- Gadget chrome rendering
Custom WsTestServer: Lightweight JSON-RPC mock server for unit tests
- Responds to RPC calls with configurable responses
- Emits push notifications on configurable topics
- Supports connection/disconnection simulation
No mocking policy enforced: Tests use real WebSocket connections, real DOM (JSDOM for Vitest, real browser for Playwright), real localStorage.
Testability Considerations
- [TC-001] The WebSocket Bridge SHALL be testable using a custom WsTestServer (lightweight JSON-RPC mock) that echoes JSON-RPC responses, not mocked WebSocket objects.
- [TC-002] Gadget lifecycle tests (mount, unmount, error boundary) SHALL use real DOM via JSDOM in Vitest, with actual gadget modules imported from disk.
- [TC-003] State sync tests SHALL use real localStorage (via JSDOM) and a real WebSocket connection to verify bidirectional synchronization.
- [TC-004] E2E tests SHALL use Playwright on Firefox with a real browser, connecting to a real SPEC-014 gateway instance, mounting real gadgets, and verifying real-time event rendering.
- [TC-005] Notification tests SHALL verify desktop notification API calls and in-app notification rendering with real browser permissions.
- [TC-006] Reconnection tests SHALL simulate real WebSocket disconnection (close the server) and verify the full reconnect, re-authenticate, re-subscribe cycle.
- [TC-007] Layout persistence tests SHALL verify that gadget positions and sizes survive a full page reload by checking real localStorage and restoring state.
- [TC-008] Performance tests SHALL measure actual frame rates and memory consumption using browser performance APIs (Performance Observer, performance.memory).
- [TC-009] Gadget registry tests SHALL verify that manifests are validated against the GadgetManifest JSON Schema and that invalid manifests are rejected.
- [TC-010] Theme switching tests SHALL verify that CSS custom property values change correctly and that all gadgets re-render with the new theme.
- [TC-011] Vitest unit tests SHALL cover: EventBus, WebSocketBridge, StateSync, NotificationManager, Registry, Chrome, and Shared utilities.
- [TC-012] Playwright E2E suite (
dashboard.spec.js) SHALL include 11+ tests covering: page load, title, header, connection status, theme toggle, layout switching, WebSocket states, and notification bell.
API Contracts
Contract: Command Center Bridge Protocol (contracts/commandcenter/bridge-v1.0.0.yaml)
info:
title: VizInt Command Center Bridge Protocol
version: 1.0.0
spec_id: 016-vizint-command-center
spec_version: 2.0.0
maturity: stable
transport: websocket
protocol: json-rpc-2.0
consumer: vizint-command-center
provider: 014-websocket-gateway
connection:
url_pattern: "ws://{host}:{port}"
default_port: 18790
auth_strategy: static_token
request_id_prefix: "cc-req-"
reconnect:
backoff_initial_ms: 1000
backoff_max_ms: 30000
backoff_multiplier: 2
max_attempts: null
rpc_methods:
session:
- method: session.active
description: Get current active session info
handler: SessionHandler
- method: session.list
description: List all active sessions
handler: SessionHandler
- method: session.get
description: Get session by ID with context and facts
handler: SessionHandler
params: [session_id]
- method: session.open
description: Create new session with type and metadata
handler: SessionHandler
params: [type, metadata]
- method: session.close
description: Close session by ID
handler: SessionHandler
params: [session_id]
- method: session.events
description: Subscribe to session lifecycle events
handler: SessionHandler
- method: session.facts.subscribe
description: Subscribe to fact emissions
handler: SessionHandler
projects:
- method: projects.list
description: List projects from Neo4j (name, path, status, language)
handler: ProjectsHandler
- method: projects.get
description: Get project by name with tasks and sessions
handler: ProjectsHandler
params: [name]
- method: projects.tasks
description: List tasks with filtering by status (limit 1000)
handler: ProjectsHandler
params: [status, limit]
- method: projects.taskCreate
description: Create task in Neo4j
handler: ProjectsHandler
params: [project, title, status, priority]
subscriptions:
cxp.traffic:
consumer_gadgets: [cxp-feed, claude-chat]
filters_supported: [volk_id, thread_id, subject, delivery_status]
volk.lifecycle:
consumer_gadgets: [volk-status]
filters_supported: [volk_alias]
governance.decisions:
consumer_gadgets: [audit-trail, notification-center]
filters_supported: [volk_id, result, action]
session.events:
consumer_gadgets: [session-manager, notification-center]
filters_supported: [session_id, event_type]
kernel.events:
consumer_gadgets: [notification-center]
filters_supported: []
gateway.presence:
consumer_gadgets: [notification-center]
filters_supported: []
state_sync:
key_prefix: "commandcenter.state."
conflict_resolution: last_write_wins
debounce_ms: 500
rpc_methods:
set: "state.set"
get: "state.get"
delete: "state.delete"
pull: "state.pull"
notifications:
max_stored: 200
classification_rules:
- topic: "governance.decisions"
condition: "result == 'escalated'"
type: escalation
priority: critical
- topic: "governance.decisions"
condition: "result == 'deny'"
type: decision_needed
priority: warning
- topic: "kernel.events"
condition: "event_type == 'error'"
type: error
priority: error
- topic: "session.events"
condition: "event_type == 'closed'"
type: info
priority: info
gadget_manifests:
- id: orchestrata-project-explorer
category: orchestrata
gateway_methods: [knowledge.nodes, session.list]
gateway_subscriptions: []
- id: orchestrata-session-manager
category: orchestrata
gateway_methods: [session.active, session.open, session.close, session.get, session.list]
gateway_subscriptions: [session.events, session.facts.subscribe]
- id: orchestrata-cxp-feed
category: orchestrata
gateway_methods: [cxp.subscribe, cxp.unsubscribe, cxp.status]
gateway_subscriptions: [cxp.traffic]
- id: orchestrata-volk-status
category: orchestrata
gateway_methods: [volk.list, volk.get]
gateway_subscriptions: [volk.lifecycle]
- id: orchestrata-claude-chat
category: orchestrata
gateway_methods: [cxp.send]
gateway_subscriptions: [cxp.traffic]
- id: orchestrata-task-board
category: orchestrata
gateway_methods: [projects.tasks, projects.taskCreate]
gateway_subscriptions: [session.events]
- id: orchestrata-qa-dashboard
category: orchestrata
gateway_methods: [knowledge.query]
gateway_subscriptions: [session.events]
- id: orchestrata-audit-trail
category: orchestrata
gateway_methods: [governance.query]
gateway_subscriptions: [governance.decisions]
- id: orchestrata-kg-explorer
category: orchestrata
gateway_methods: [knowledge.query, knowledge.nodes, knowledge.relationships]
gateway_subscriptions: []
- id: orchestrata-notification-center
category: orchestrata
gateway_methods: []
gateway_subscriptions: [governance.decisions, kernel.events, session.events]
performance:
initial_load_max_bytes: 2097152
gadget_render_p95_ms: 100
rpc_roundtrip_p95_ms: 200
event_display_p95_ms: 200
max_memory_mb: 100
target_fps: 60
neo4j_query_timeout_ms: 10000
security:
token_storage: localStorage
csp_required: true
xss_prevention: true
origin_validation: true
anonymous_dev_mode: GATEWAY_ALLOW_ANONYMOUS
spec_traceability:
spec_id: "016-vizint-command-center"
spec_version: "2.0.0"
user_stories:
- "US-001"
- "US-002"
- "US-003"
- "US-004"
- "US-005"
- "US-006"
- "US-007"
- "US-008"
- "US-009"
- "US-010"
- "US-011"
- "US-012"
- "US-013"
- "US-014"
Observability
Logging Requirements
- Component Logging
- Log all major operations with appropriate log levels
- Include correlation IDs for request tracing
- Log performance metrics for critical operations
- Log errors with full context for debugging
Metrics Requirements
- Performance Metrics
- Operation duration histograms
- Request/error rate counters
- Resource utilization gauges
- Business metrics relevant to domain
Tracing Requirements
- Distributed Tracing
- Trace propagation across component boundaries
- Span attributes for domain-specific context
- Trace sampling based on operational needs
Alerting Requirements
- Critical Alerts
- Error rate spikes
- Performance degradation
- Resource exhaustion
- Business metric anomalies
Dashboard Requirements
- Operational Dashboard
- Real-time system health
- Performance trends
- Error analysis
- Resource monitoring
Revision History
| Date | Version | Author | Changes |
|---|---|---|---|
| 2026-03-28 | 1.0.0 | Mohamed | Initial specification |
| 2026-03-28 | 1.0.0 | Mohamed | Added Data Models, Error Conditions, Performance Requirements, Testability, DoD, Terminology, Examples, Contracts sections per spec standard improvements |
| 2026-03-29 | 2.0.0 | Mohamed | Major update: documented all 31 gadgets (10 P1 + 21 personal/specialized), added SessionHandler (7 methods) and ProjectsHandler (4 methods) gateway integration, added US-013/US-014 for gateway handlers, updated acceptance criteria checkboxes to reflect implementation state, documented portal framework (bus.js, portal.js, registry.js, chrome.js, shared.js), added KG statistics (558K+ nodes), documented deployment addresses, added configuration as JSON, documented test infrastructure (Playwright E2E on Firefox, Vitest units, WsTestServer), added MiniMax and OpenCode as contributors, updated contract with full RPC method inventory |