Orchestrata Ultimate / Specs / 051-vizint-ui
051-vizint-ui: VizInt UI - Visual Interface Dashboard
VizInt (Visual Interface) is a modern web-based dashboard for the Ultimate Hybrid system, providing project management, task orchestration, agent configuration, and governance rule editing through a visual interface.
At a glance
| Item | Value |
|---|---|
| Spec directory | specs/051-vizint-ui/ |
| Status line in the spec | Deprecated — superseded by SPEC-016 |
| Requirement IDs defined | 93 |
With a @traces citation in src/ |
0 (0.0%) |
With a @traces citation in tests/ |
0 (0.0%) |
| Tracked files | 2 |
| RTM page | 051-vizint-ui |
Reading this spec
This spec describes VizInt, a web dashboard for the Ultimate Hybrid system that gives people who do not work in a terminal a visual way to manage projects and tasks, configure agents and edit governance rules. The spec is deprecated: its status line reads "Deprecated — superseded by SPEC-016", and its first line points readers to SPEC-016, the VizInt Command Center, where all VizInt requirements, architecture and guidance now live. This document is kept for historical context.
The design it records is a FastAPI backend serving an HTMX and TailwindCSS front end, a WebSocket channel for real-time updates, Neo4j for persistence, and integration with the Orchestrata kernel over CXP. The four user stories are a project manager viewing the dashboard, a developer configuring agents, visual task management, and offline support. The functional requirements run from FR-001 to FR-020: project dashboard display, real-time updates, a task Kanban board with drag-and-drop, agent configuration and live model switching, a governance rule editor, WebSocket connection management with reconnection, offline support with a change queue, authentication, role-based access control, CSRF protection, project and task CRUD, filtering and search, audit logging, rate limiting, multi-project support, task dependencies and agent status monitoring.
The 93 requirement IDs, all numbered REQ-051-NNN, also cover the API contracts (a shared ErrorResponse schema with error, message and timestamp, resource schemas for projects, tasks and agent configurations, and versioning), the error conditions (for example automatic WebSocket reconnect with exponential backoff, and an offline indicator with a change queue that syncs when the connection returns), and authorization that combines PAM++ policy with Admin, User and Viewer roles.
No code module cites this spec, which fits its deprecated status. The requirements traceability matrix lists every ID. The spec tracks 2 files. No src/ symbol cites any of the 93 requirements, so measured trace coverage is 0.0%, and in tests/, 0 requirements are cited by a test-side @traces. All 93 requirements have no citing symbol; untraced means no @traces names the ID, and the behaviour may still exist in code that was never annotated.
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-051-001 |
- | Every error response SHALL conform to the ErrorResponse schema: it SHALL carry the required fields error, message and timestamp (date-time), and it admits the optional fields request_id, trace_id and details. |
none |
REQ-051-002 |
- | All APIs SHALL use path-based versioning (/api/v1/). A breaking change SHALL require an increment to v2. |
none |
REQ-051-003 |
- | The dashboard SHALL show project cards with status, SHALL update in real time when tasks change, SHALL allow projects to be reordered by drag-and-drop, and SHALL support filtering by status, agent and priority. | none |
REQ-051-004 |
- | The agent configuration interface SHALL present a form covering all agent settings, SHALL support real-time model switching, SHALL provide tool enable/disable toggles, and SHALL validate the configuration before save. | none |
REQ-051-005 |
- | The task view SHALL provide a Kanban board with backlog, in-progress, review and done columns, SHALL support drag-and-drop task movement, SHALL open a task detail modal on click, and SHALL support bulk operations on selected tasks. | none |
REQ-051-006 |
- | A service worker SHALL cache the UI assets, the UI SHALL display an offline indicator, changes made offline SHALL be queued for sync when the connection returns, and the pending changes SHALL be shown to the user. | none |
REQ-051-007 |
- | A Project resource SHALL conform to the Project schema: id, name and status are required; id SHALL match ^proj_[a-zA-Z0-9]+$; name SHALL be 1 to 100 characters; status SHALL be one of active, paused, completed, archived; and description, agents, created_at and updated_at (date-time) are optional. |
none |
REQ-051-008 |
- | A Task resource SHALL conform to the Task schema: id, title, status and priority are required; id SHALL match ^T:[0-9]+$; title SHALL be 1 to 200 characters; status SHALL be one of pending, in_progress, in_review, completed, blocked; priority SHALL be an integer from 1 to 5; and description, agent_id, project_id (matching ^proj_[a-zA-Z0-9]+$), dependencies, created_at and updated_at are optional. |
none |
REQ-051-009 |
- | An AgentConfig resource SHALL conform to the AgentConfig schema: id, type and model are required; id SHALL match ^U:[A-Za-z]+$; type SHALL be one of coding, review, research, orchestration; max_concurrent_tasks SHALL be an integer of at least 1; and timeout_seconds SHALL be an integer of at least 60. |
none |
REQ-051-010 |
- | The system MUST display a dashboard showing all projects with their current status, task counts, and agent assignments. | none |
REQ-051-011 |
- | The system MUST provide real-time updates to the dashboard when project status changes, using WebSocket connections. | none |
REQ-051-012 |
- | The system MUST display tasks in a Kanban board format with columns for backlog, in-progress, review, and completed states. | none |
REQ-051-013 |
- | The system MUST allow users to move tasks between columns using drag-and-drop, updating task status in real-time. | none |
REQ-051-014 |
- | The system MUST provide a visual interface for configuring agent settings including model selection, tool enablement, and concurrency limits. | none |
REQ-051-015 |
- | The system MUST allow instant model switching for agents without requiring page reload, with changes persisted immediately. | none |
REQ-051-016 |
- | The system MUST provide a visual interface for creating, editing, and deleting governance rules with condition builders. | none |
REQ-051-017 |
- | The system MUST maintain persistent WebSocket connections with automatic reconnection using exponential backoff. | none |
REQ-051-018 |
- | The system MUST cache UI assets via service worker and queue changes for sync when connection is restored. | none |
REQ-051-019 |
- | The system MUST support OAuth2 authentication with session management and automatic session expiration. | none |
REQ-051-020 |
- | The system MUST enforce role-based permissions with Admin, User, and Viewer roles. | none |
REQ-051-021 |
- | The system MUST validate CSRF tokens on all state-changing operations. | none |
REQ-051-022 |
- | The system MUST support creating, reading, updating, and deleting projects via REST API. | none |
REQ-051-023 |
- | The system MUST support creating, reading, updating, and deleting tasks via REST API. | none |
REQ-051-024 |
- | The system MUST support filtering projects and tasks by status, agent, priority, and custom criteria. | none |
REQ-051-025 |
- | The system MUST log all user actions for audit purposes with timestamps and user identification. | none |
REQ-051-026 |
- | The system MUST enforce rate limiting on authentication attempts, API calls, and WebSocket messages. | none |
REQ-051-027 |
- | The system MUST allow users to manage multiple projects simultaneously with project switching. | none |
REQ-051-028 |
- | The system MUST support defining and visualizing task dependencies with blocking indicators. | none |
REQ-051-029 |
- | The system MUST display real-time agent status including active task, idle state, and error conditions. | none |
REQ-051-030 |
- | On WebSocket disconnection (ERR-001) the system SHALL auto-reconnect with exponential backoff, to a maximum of 5 attempts. | none |
REQ-051-031 |
- | On authentication failure (ERR-002) the system SHALL redirect to the login page with a return URL. | none |
REQ-051-032 |
- | On API timeout (ERR-003) the system SHALL show a timeout message and SHALL auto-retry up to 3 times. | none |
REQ-051-033 |
- | When the network is offline (ERR-004) the system SHALL show an offline indicator and SHALL enable the change queue. | none |
REQ-051-034 |
- | On permission denied (ERR-005) the system SHALL show an access-denied message and SHALL log the attempt. | none |
REQ-051-035 |
- | On session expiry (ERR-006) the system SHALL clear the session and redirect to login. | none |
REQ-051-036 |
- | On an invalid CSRF token (ERR-007) the system SHALL reject the request and return 403. | none |
REQ-051-037 |
- | When a rate limit is exceeded (ERR-008) the system SHALL return 429 and show the retry-after header. | none |
REQ-051-038 |
- | When a project is not found (ERR-009) the system SHALL return 404 and show the project list. | none |
REQ-051-039 |
- | When a task is not found (ERR-010) the system SHALL return 404 and show the task list. | none |
REQ-051-040 |
- | When an agent is not found (ERR-011) the system SHALL return 404 and show the agent configuration. | none |
REQ-051-041 |
- | On invalid project data (ERR-012) the system SHALL return 400 with the validation errors. | none |
REQ-051-042 |
- | On invalid task data (ERR-013) the system SHALL return 400 with the validation errors. | none |
REQ-051-043 |
- | On a circular task dependency (ERR-014) the system SHALL return 400 and highlight the conflicting tasks. | none |
REQ-051-044 |
- | On a governance rule violation (ERR-015) the system SHALL return 451 and show the rule details. | none |
REQ-051-045 |
- | On database connection failure (ERR-016) the system SHALL return 503 and enable the retry queue. | none |
REQ-051-046 |
- | On a WebSocket protocol error (ERR-017) the system SHALL close the connection, log the error, and attempt reconnection. | none |
REQ-051-047 |
- | On an invalid OAuth callback (ERR-018) the system SHALL redirect to login with an error message. | none |
REQ-051-048 |
- | On a concurrent modification conflict (ERR-019) the system SHALL return 409 and show the conflict-resolution UI. | none |
REQ-051-049 |
- | On an unsupported media type (ERR-020) the system SHALL return 415 and show the supported types. | none |
REQ-051-101 |
- | The UI SHALL meet the performance budgets: page load (first contentful paint) < 500ms, API response time (p95) < 200ms, WebSocket event latency < 100ms, HTMX partial render < 50ms, and drag-and-drop response < 16ms (60fps). | none |
REQ-051-102 |
- | The system SHALL sustain the scalability capacities: 100 concurrent users, 50 projects per user, 1,000 tasks per project, 500 WebSocket connections, and 6,000 API requests per minute. | none |
REQ-051-103 |
- | The system SHALL meet a 99.9% uptime target, SHALL confine planned maintenance to the Sunday 02:00-04:00 UTC window, and SHALL degrade gracefully to read-only mode during maintenance. | none |
REQ-051-104 |
- | The UI SHALL comply with WCAG 2.1 Level AA, SHALL support keyboard navigation, SHALL be screen-reader compatible, SHALL provide a high-contrast mode, and SHALL show focus indicators on all interactive elements. | none |
REQ-051-105 |
- | The UI SHALL support Chrome 90+, Firefox 88+, Safari 14+, Edge 90+, Mobile Safari iOS 14+, and Chrome for Android 90+. | none |
REQ-051-106 |
- | The system SHALL depend on fastapi >= 0.100 (web framework), websockets >= 11.0 (real-time updates), redis >= 5.0 (session store), neo4j >= 5.0 (data persistence), htmx >= 1.9 (reactive HTML), and tailwindcss >= 3.0 (styling). | none |
REQ-051-050 |
- | Authentication SHALL use OAuth 2.0, SHALL manage sessions with secure cookies, SHALL expire sessions automatically, and SHALL support MFA via TOTP. | none |
REQ-051-051 |
- | Authorization SHALL enforce PAM++ policy, role-based access control, project-scoped permissions, and the Admin/User/Viewer role set. | none |
REQ-051-052 |
- | The system SHALL sanitize all user input, SHALL send Content Security Policy headers, SHALL use HTTP-only cookies, and SHALL send the secure headers X-Content-Type-Options and X-Frame-Options. |
none |
REQ-051-053 |
- | The system SHALL rate-limit login attempts to 5 per minute, API calls to 100 per minute, and WebSocket messages to 60 per minute. | none |
REQ-051-054 |
- | All UI actions SHALL be subject to PAM++ checks, governance errors SHALL return status 451, admin-only routes SHALL be protected, and user actions SHALL be logged for audit. | none |
REQ-051-055 |
- | Data retention SHALL be 30 days for user sessions, 90 days for audit logs, 30 days for activity logs, and until deletion for project data. | none |
REQ-051-056 |
- | VizInt SHALL follow a layered architecture with clear separation of concerns across four layers: a Presentation layer of HTMX templates with TailwindCSS styling, an API layer of FastAPI REST endpoints with request/response models, a Service layer holding the business logic for project, task and agent management, and a Data layer of a Neo4j graph database for persistence with Redis for sessions. | none |
REQ-051-057 |
- | Server state SHALL be held in Neo4j for persistent data and in Redis for sessions and cache; client state SHALL be held in HTMX DOM state and in localStorage for the offline queue; shared state SHALL be synchronized across clients over WebSocket. | none |
REQ-051-058 |
- | The system SHALL integrate with the Orchestrata kernel over /api/orchestrata/* (HTTP/REST) for agent command execution, /ws/orchestrata (WebSocket) for real-time agent events, and /api/cxp/* (CXP) for cross-process communication. |
none |
REQ-051-059 |
- | The system SHALL access Neo4j with Cypher: project CRUD and task CRUD on user action, relationship queries on page load, and full-text search on search. | none |
REQ-051-060 |
- | The system SHALL hold in Redis: user sessions with a 30-day TTL for authentication state, CSRF tokens with a 1-hour TTL, WebSocket heartbeats with a 1-minute TTL for connection health, rate-limit counters with a 1-minute TTL for API throttling, and the offline change queue retained until sync. | none |
REQ-051-061 |
- | The system SHALL support user authentication through the GitHub and Google OAuth providers, each configured with a client ID and secret. | none |
REQ-051-062 |
- | The dashboard SHALL display all projects with status (SC-001), validated by visual inspection. | none |
REQ-051-063 |
- | Tasks SHALL be draggable between Kanban columns (SC-002), validated by manual testing. | none |
REQ-051-064 |
- | Agent configuration changes SHALL persist immediately (SC-003), validated by API verification. | none |
REQ-051-065 |
- | WebSocket SHALL deliver updates within 100ms (SC-004), validated by performance test. | none |
REQ-051-066 |
- | Governance rules SHALL block prohibited actions (SC-005), validated by rule enforcement test. | none |
REQ-051-067 |
- | Offline changes SHALL sync when the connection is restored (SC-006), validated by offline testing. | none |
REQ-051-107 |
- | Test coverage SHALL exceed 80% (QC-001). | none |
REQ-051-108 |
- | API availability SHALL be 99.9% (QC-002). | none |
REQ-051-109 |
- | Page load time SHALL be under 500ms (QC-003). | none |
REQ-051-110 |
- | The number of critical vulnerabilities SHALL be 0 (QC-004). | none |
REQ-051-111 |
- | Accessibility SHALL comply with WCAG 2.1 AA (QC-005). | none |
REQ-051-112 |
- | Production deployment SHALL succeed (DC-001), validated by the deployment pipeline. | none |
REQ-051-113 |
- | The health check endpoint SHALL return 200 (DC-002), validated by monitoring. | none |
REQ-051-114 |
- | The release SHALL introduce no breaking changes to existing APIs (DC-003), validated by contract tests. | none |
REQ-051-115 |
- | The rollback procedure SHALL be documented (DC-004), validated by runbook review. | none |
REQ-051-116 |
- | Integration tests SHALL cover database integration, WebSocket connections, the authentication flow, project CRUD operations, and task management. | none |
REQ-051-117 |
- | End-to-end tests SHALL cover complete user workflows, cross-browser compatibility, mobile responsiveness, and offline mode functionality. | none |
REQ-051-118 |
- | Test coverage SHALL exceed 80% for unit tests, SHALL exceed 90% for integration tests, and SHALL be 100% for API coverage. | none |
REQ-051-119 |
- | The system SHALL report metrics for user sessions, API response times, error rates, WebSocket connections, and database queries. | none |
REQ-051-120 |
- | The system SHALL alert on a high error rate (>5%), slow responses (>1s), authentication failures, and database connection issues. | none |
REQ-051-068 |
- | The system SHALL expose the project endpoints GET /api/projects (list), POST /api/projects (create, accepting name, template and volk_configs), GET /api/projects/{project_id} (detail), PUT /api/projects/{project_id} (update) and DELETE /api/projects/{project_id} (delete). |
none |
REQ-051-069 |
- | The system SHALL expose the task endpoints GET /api/projects/{project_id}/tasks (list, filterable by the status and assigned_volk query parameters), POST /api/projects/{project_id}/tasks (create), PUT /api/projects/{project_id}/tasks/{task_id} (update) and PATCH /api/projects/{project_id}/tasks/{task_id}/status (drag-and-drop status update). |
none |
REQ-051-070 |
- | The system SHALL expose the agent-configuration endpoints GET /api/projects/{project_id}/config/agents and PUT /api/projects/{project_id}/config/agents/{agent_alias}, the latter accepting model, enabled, max_concurrent, timeout and tools. |
none |
REQ-051-071 |
- | The system SHALL expose the governance-rule endpoints GET /api/projects/{project_id}/rules (list), POST /api/projects/{project_id}/rules (create, accepting name, scope, condition, action and priority), PUT /api/projects/{project_id}/rules/{rule_id} (update) and DELETE /api/projects/{project_id}/rules/{rule_id} (delete). |
none |
REQ-051-072 |
- | The system SHALL accept WebSocket connections at WS /ws/{project_id} and SHALL send server-to-client messages carrying a type and a data payload, including task_updated, agent_status and checkpoint_created. |
none |
REQ-051-073 |
- | The WebSocket event vocabulary SHALL be task_updated, task_created, task_deleted, agent_status, agent_progress, checkpoint_created, checkpoint_restored, rule_updated, rule_violation and project_updated. |
none |
Code that traces this spec
No src/ symbol cites a requirement of this spec.
Other tracked files
specs/051-vizint-ui/archive/compliance-audit.md
Full spec text
Verbatim from specs/051-vizint-ui/spec.md; headings are pushed down two levels.
⚠️ DEPRECATED: This specification has been superseded by SPEC-016: VizInt Command Center. All VizInt requirements, architecture, and implementation guidance now live in SPEC-016. This document is retained for historical context only.
SPEC-051: VizInt UI - Visual Interface Dashboard
Metadata
- Spec ID: 051-vizint-ui
- Title: VizInt UI - Visual Interface Dashboard
- Author: Mohamed
- Status: Deprecated — superseded by SPEC-016
- Created: 2026-04-08
- Last Updated: 2026-04-08
- Priority: P0
- Version: 1.0.0
API Contracts
REST API Endpoints
# Example endpoint definition
GET /api/v1/resource/{id}
Response (200):
type: object
required:
- id
- name
properties:
id: { type: string }
name: { type: string }
Response (404):
$ref: '#/components/schemas/ErrorResponse'
Error Response Schema
components:
schemas:
ErrorResponse:
type: object
required:
- error
- message
- timestamp
properties:
error: { type: string }
message: { type: string }
timestamp: { type: string, format: date-time }
request_id: { type: string }
trace_id: { type: string }
details: { type: array, items: { type: object } }
REQ-051-001: Every error response SHALL conform to the ErrorResponse schema: it SHALL carry the required fields error, message and timestamp (date-time), and it admits the optional fields request_id, trace_id and details.
API Versioning
REQ-051-002: All APIs SHALL use path-based versioning (/api/v1/). A breaking change SHALL require an increment to v2.
Visual Architecture
Class Diagram
Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 22:).
classDiagram-direction LR
class CheetahClawsTUI {
+__init__()
#_load_commands(): dict[str, Any]
+async create_checkpoint(name: str): dict[str, Any]
+async rewind(steps: int = 1): dict[str, Any]
+async query_memory(query: str, depth: int = 1): dict[str, Any]
+async edit_file(file_path: str, old_string: str, new_string: str): dict[str, Any]
+async search_files(pattern: str, path: str = '.'): list[str]
+async execute_command(command: str, args: list[str] | None = None): dict[str, Any]
}
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]]
}
Revision History
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0.0 | 2026-04-08 | Mohamed | Initial specification |
User Scenarios
US-001: Project Manager Viewing Dashboard
As a project manager, I want to see all projects and their status so I can track progress across multiple projects.
Acceptance Criteria:
- Dashboard shows project cards with status
- Real-time updates when tasks change
- Drag-and-drop to reorder projects
- Filter by status, agent, priority
REQ-051-003: The dashboard SHALL show project cards with status, SHALL update in real time when tasks change, SHALL allow projects to be reordered by drag-and-drop, and SHALL support filtering by status, agent and priority.
US-002: Developer Configuring Agents
As a developer, I want to configure agent settings so I can optimize agent behavior for my project.
Acceptance Criteria:
- Agent configuration form with all settings
- Real-time model switching
- Tool enable/disable toggles
- Validation before save
REQ-051-004: The agent configuration interface SHALL present a form covering all agent settings, SHALL support real-time model switching, SHALL provide tool enable/disable toggles, and SHALL validate the configuration before save.
US-003: Visual Task Management
As a team lead, I want to manage tasks visually so I can organize work efficiently.
Acceptance Criteria:
- Kanban board view (backlog, in-progress, review, done)
- Drag-and-drop task movement
- Task detail modal on click
- Bulk operations on selected tasks
REQ-051-005: The task view SHALL provide a Kanban board with backlog, in-progress, review and done columns, SHALL support drag-and-drop task movement, SHALL open a task detail modal on click, and SHALL support bulk operations on selected tasks.
US-004: Offline Support
As a user, I want to access the UI offline so I can continue working without internet.
Acceptance Criteria:
- Service worker caches UI assets
- Offline indicator in UI
- Sync queue for changes when back online
- Show pending changes
REQ-051-006: A service worker SHALL cache the UI assets, the UI SHALL display an offline indicator, changes made offline SHALL be queued for sync when the connection returns, and the pending changes SHALL be shown to the user.
Data Models
Project
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "name", "status"],
"properties": {
"id": {
"type": "string",
"pattern": "^proj_[a-zA-Z0-9]+$"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"status": {
"type": "string",
"enum": ["active", "paused", "completed", "archived"]
},
"description": {
"type": "string"
},
"agents": {
"type": "array",
"items": {"type": "string"}
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}
REQ-051-007: A Project resource SHALL conform to the Project schema: id, name and status are required; id SHALL match ^proj_[a-zA-Z0-9]+$; name SHALL be 1 to 100 characters; status SHALL be one of active, paused, completed, archived; and description, agents, created_at and updated_at (date-time) are optional.
Task
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "title", "status", "priority"],
"properties": {
"id": {
"type": "string",
"pattern": "^T:[0-9]+$"
},
"title": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"description": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["pending", "in_progress", "in_review", "completed", "blocked"]
},
"priority": {
"type": "integer",
"minimum": 1,
"maximum": 5
},
"agent_id": {
"type": "string"
},
"project_id": {
"type": "string",
"pattern": "^proj_[a-zA-Z0-9]+$"
},
"dependencies": {
"type": "array",
"items": {"type": "string"}
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}
REQ-051-008: A Task resource SHALL conform to the Task schema: id, title, status and priority are required; id SHALL match ^T:[0-9]+$; title SHALL be 1 to 200 characters; status SHALL be one of pending, in_progress, in_review, completed, blocked; priority SHALL be an integer from 1 to 5; and description, agent_id, project_id (matching ^proj_[a-zA-Z0-9]+$), dependencies, created_at and updated_at are optional.
AgentConfig
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["id", "type", "model"],
"properties": {
"id": {
"type": "string",
"pattern": "^U:[A-Za-z]+$"
},
"type": {
"type": "string",
"enum": ["coding", "review", "research", "orchestration"]
},
"model": {
"type": "string"
},
"tools_enabled": {
"type": "array",
"items": {"type": "string"}
},
"max_concurrent_tasks": {
"type": "integer",
"minimum": 1
},
"timeout_seconds": {
"type": "integer",
"minimum": 60
}
}
}
REQ-051-009: An AgentConfig resource SHALL conform to the AgentConfig schema: id, type and model are required; id SHALL match ^U:[A-Za-z]+$; type SHALL be one of coding, review, research, orchestration; max_concurrent_tasks SHALL be an integer of at least 1; and timeout_seconds SHALL be an integer of at least 60.
Functional Requirements
FR-001: Project Dashboard Display
REQ-051-010: The system MUST display a dashboard showing all projects with their current status, task counts, and agent assignments.
FR-002: Real-time Project Updates
REQ-051-011: The system MUST provide real-time updates to the dashboard when project status changes, using WebSocket connections.
FR-003: Task Kanban Board
REQ-051-012: The system MUST display tasks in a Kanban board format with columns for backlog, in-progress, review, and completed states.
FR-004: Drag-and-Drop Task Management
REQ-051-013: The system MUST allow users to move tasks between columns using drag-and-drop, updating task status in real-time.
FR-005: Agent Configuration Interface
REQ-051-014: The system MUST provide a visual interface for configuring agent settings including model selection, tool enablement, and concurrency limits.
FR-006: Real-time Model Switching
REQ-051-015: The system MUST allow instant model switching for agents without requiring page reload, with changes persisted immediately.
FR-007: Governance Rule Editor
REQ-051-016: The system MUST provide a visual interface for creating, editing, and deleting governance rules with condition builders.
FR-008: WebSocket Connection Management
REQ-051-017: The system MUST maintain persistent WebSocket connections with automatic reconnection using exponential backoff.
FR-009: Offline Support
REQ-051-018: The system MUST cache UI assets via service worker and queue changes for sync when connection is restored.
FR-010: User Authentication
REQ-051-019: The system MUST support OAuth2 authentication with session management and automatic session expiration.
FR-011: Role-Based Access Control
REQ-051-020: The system MUST enforce role-based permissions with Admin, User, and Viewer roles.
FR-012: CSRF Protection
REQ-051-021: The system MUST validate CSRF tokens on all state-changing operations.
FR-013: Project CRUD Operations
REQ-051-022: The system MUST support creating, reading, updating, and deleting projects via REST API.
FR-014: Task CRUD Operations
REQ-051-023: The system MUST support creating, reading, updating, and deleting tasks via REST API.
FR-015: Filter and Search
REQ-051-024: The system MUST support filtering projects and tasks by status, agent, priority, and custom criteria.
FR-016: Audit Logging
REQ-051-025: The system MUST log all user actions for audit purposes with timestamps and user identification.
FR-017: Rate Limiting
REQ-051-026: The system MUST enforce rate limiting on authentication attempts, API calls, and WebSocket messages.
FR-018: Multi-Project Support
REQ-051-027: The system MUST allow users to manage multiple projects simultaneously with project switching.
FR-019: Task Dependencies
REQ-051-028: The system MUST support defining and visualizing task dependencies with blocking indicators.
FR-020: Agent Status Monitoring
REQ-051-029: The system MUST display real-time agent status including active task, idle state, and error conditions.
Authentication
OAuth2 Flow
@app.get("/auth/login")
async def login():
"""Redirect to OAuth provider."""
return RedirectResponse(
url=f"{OAUTH_URL}?client_id={CLIENT_ID}&response_type=code"
)
@app.get("/auth/callback")
async def callback(code: str):
"""Handle OAuth callback."""
token = await exchange_code(code)
# Create session
return RedirectResponse(url="/dashboard")
Session Management
async def get_current_user(request: Request):
"""Get current user from session."""
session_id = request.cookies.get("session_id")
if not session_id:
raise HTTPException(401, "Not authenticated")
user = await redis.get(f"session:{session_id}")
if not user:
raise HTTPException(401, "Session expired")
return json.loads(user)
WebSocket Reconnection
Connection Manager
class ConnectionManager:
def __init__(self):
self.active_connections: Dict[str, WebSocket] = {}
async def connect(self, websocket: WebSocket, client_id: str):
await websocket.accept()
self.active_connections[client_id] = websocket
def disconnect(self, client_id: str):
self.active_connections.pop(client_id, None)
async def broadcast(self, message: dict):
for connection in self.active_connections.values():
await connection.send_json(message)
Client Reconnection Logic
const ws = new WebSocket(WS_URL);
ws.onopen = () => {
console.log('Connected to WebSocket');
};
ws.onclose = () => {
// Attempt reconnection with exponential backoff
setTimeout(() => {
connectWebSocket();
}, 1000 * Math.pow(2, reconnectAttempts));
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
Error Conditions
| ID | Condition | Handling |
|---|---|---|
| ERR-001 | WebSocket disconnected | Auto-reconnect with exponential backoff (max 5 attempts) |
| ERR-002 | Authentication failed | Redirect to login page with return URL |
| ERR-003 | API timeout | Show timeout message, auto-retry up to 3 times |
| ERR-004 | Network offline | Show offline indicator, enable change queue |
| ERR-005 | Permission denied | Show access denied message, log attempt |
| ERR-006 | Session expired | Clear session, redirect to login |
| ERR-007 | Invalid CSRF token | Reject request, return 403 |
| ERR-008 | Rate limit exceeded | Return 429, show retry-after header |
| ERR-009 | Project not found | Return 404, show project list |
| ERR-010 | Task not found | Return 404, show task list |
| ERR-011 | Agent not found | Return 404, show agent configuration |
| ERR-012 | Invalid project data | Return 400 with validation errors |
| ERR-013 | Invalid task data | Return 400 with validation errors |
| ERR-014 | Circular task dependency | Return 400, highlight conflicting tasks |
| ERR-015 | Governance rule violation | Return 451, show rule details |
| ERR-016 | Database connection failed | Return 503, enable retry queue |
| ERR-017 | WebSocket protocol error | Close connection, log error, attempt reconnect |
| ERR-018 | Invalid OAuth callback | Redirect to login with error message |
| ERR-019 | Concurrent modification conflict | Return 409, show conflict resolution UI |
| ERR-020 | Unsupported media type | Return 415, show supported types |
REQ-051-030: On WebSocket disconnection (ERR-001) the system SHALL auto-reconnect with exponential backoff, to a maximum of 5 attempts.
REQ-051-031: On authentication failure (ERR-002) the system SHALL redirect to the login page with a return URL.
REQ-051-032: On API timeout (ERR-003) the system SHALL show a timeout message and SHALL auto-retry up to 3 times.
REQ-051-033: When the network is offline (ERR-004) the system SHALL show an offline indicator and SHALL enable the change queue.
REQ-051-034: On permission denied (ERR-005) the system SHALL show an access-denied message and SHALL log the attempt.
REQ-051-035: On session expiry (ERR-006) the system SHALL clear the session and redirect to login.
REQ-051-036: On an invalid CSRF token (ERR-007) the system SHALL reject the request and return 403.
REQ-051-037: When a rate limit is exceeded (ERR-008) the system SHALL return 429 and show the retry-after header.
REQ-051-038: When a project is not found (ERR-009) the system SHALL return 404 and show the project list.
REQ-051-039: When a task is not found (ERR-010) the system SHALL return 404 and show the task list.
REQ-051-040: When an agent is not found (ERR-011) the system SHALL return 404 and show the agent configuration.
REQ-051-041: On invalid project data (ERR-012) the system SHALL return 400 with the validation errors.
REQ-051-042: On invalid task data (ERR-013) the system SHALL return 400 with the validation errors.
REQ-051-043: On a circular task dependency (ERR-014) the system SHALL return 400 and highlight the conflicting tasks.
REQ-051-044: On a governance rule violation (ERR-015) the system SHALL return 451 and show the rule details.
REQ-051-045: On database connection failure (ERR-016) the system SHALL return 503 and enable the retry queue.
REQ-051-046: On a WebSocket protocol error (ERR-017) the system SHALL close the connection, log the error, and attempt reconnection.
REQ-051-047: On an invalid OAuth callback (ERR-018) the system SHALL redirect to login with an error message.
REQ-051-048: On a concurrent modification conflict (ERR-019) the system SHALL return 409 and show the conflict-resolution UI.
REQ-051-049: On an unsupported media type (ERR-020) the system SHALL return 415 and show the supported types.
Non-Functional Requirements
Performance
| Metric | Target |
|---|---|
| Page load (first contentful paint) | < 500ms |
| API response time (p95) | < 200ms |
| WebSocket event latency | < 100ms |
| HTMX partial render | < 50ms |
| Drag-and-drop response | < 16ms (60fps) |
REQ-051-101: The UI SHALL meet the performance budgets: page load (first contentful paint) < 500ms, API response time (p95) < 200ms, WebSocket event latency < 100ms, HTMX partial render < 50ms, and drag-and-drop response < 16ms (60fps).
Scalability
| Resource | Capacity |
|---|---|
| Concurrent users | 100 |
| Projects per user | 50 |
| Tasks per project | 1,000 |
| WebSocket connections | 500 |
| API requests per minute | 6,000 |
REQ-051-102: The system SHALL sustain the scalability capacities: 100 concurrent users, 50 projects per user, 1,000 tasks per project, 500 WebSocket connections, and 6,000 API requests per minute.
Availability
- System uptime target: 99.9%
- Planned maintenance window: Sunday 02:00-04:00 UTC
- Graceful degradation: Read-only mode during maintenance
REQ-051-103: The system SHALL meet a 99.9% uptime target, SHALL confine planned maintenance to the Sunday 02:00-04:00 UTC window, and SHALL degrade gracefully to read-only mode during maintenance.
Accessibility
- WCAG 2.1 Level AA compliance
- Keyboard navigation support
- Screen reader compatible
- High contrast mode available
- Focus indicators on all interactive elements
REQ-051-104: The UI SHALL comply with WCAG 2.1 Level AA, SHALL support keyboard navigation, SHALL be screen-reader compatible, SHALL provide a high-contrast mode, and SHALL show focus indicators on all interactive elements.
Browser Support
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
- Mobile Safari iOS 14+
- Chrome for Android 90+
REQ-051-105: The UI SHALL support Chrome 90+, Firefox 88+, Safari 14+, Edge 90+, Mobile Safari iOS 14+, and Chrome for Android 90+.
Dependencies
| Dependency | Version | Purpose |
|---|---|---|
| fastapi | >=0.100 | Web framework |
| websockets | >=11.0 | Real-time updates |
| redis | >=5.0 | Session store |
| neo4j | >=5.0 | Data persistence |
| htmx | >=1.9 | Reactive HTML |
| tailwindcss | >=3.0 | Styling |
REQ-051-106: The system SHALL depend on fastapi >= 0.100 (web framework), websockets >= 11.0 (real-time updates), redis >= 5.0 (session store), neo4j >= 5.0 (data persistence), htmx >= 1.9 (reactive HTML), and tailwindcss >= 3.0 (styling).
Security
Authentication
- OAuth 2.0 for user authentication
- Session management with secure cookies
- Automatic session expiration
- MFA support (TOTP)
REQ-051-050: Authentication SHALL use OAuth 2.0, SHALL manage sessions with secure cookies, SHALL expire sessions automatically, and SHALL support MFA via TOTP.
Authorization
- PAM++ policy enforcement
- Role-based access control
- Project-scoped permissions
- Admin/User/Viewer roles
REQ-051-051: Authorization SHALL enforce PAM++ policy, role-based access control, project-scoped permissions, and the Admin/User/Viewer role set.
CSRF Protection
@app.middleware("http")
async def csrf_protection(request: Request, call_next):
if request.method in ["POST", "PUT", "DELETE", "PATCH"]:
csrf_token = «redacted»
session_csrf = request.cookies.get("csrf_token")
if not csrf_token or csrf_token != session_csrf:
raise HTTPException(403, "CSRF token invalid")
response = await call_next(request)
return response
XSS Prevention
- All user input sanitized
- Content Security Policy headers
- HTTP-only cookies
- Secure headers (X-Content-Type-Options, X-Frame-Options)
REQ-051-052: The system SHALL sanitize all user input, SHALL send Content Security Policy headers, SHALL use HTTP-only cookies, and SHALL send the secure headers X-Content-Type-Options and X-Frame-Options.
Rate Limiting
- Login attempts: 5 per minute
- API calls: 100 per minute
- WebSocket messages: 60 per minute
REQ-051-053: The system SHALL rate-limit login attempts to 5 per minute, API calls to 100 per minute, and WebSocket messages to 60 per minute.
Governance (PAM++)
Policy Enforcement
- All UI actions subject to PAM++ checks
- Governance errors return 451 status
- Admin-only routes protected
- User actions logged for audit
REQ-051-054: All UI actions SHALL be subject to PAM++ checks, governance errors SHALL return status 451, admin-only routes SHALL be protected, and user actions SHALL be logged for audit.
Audit Logging
@app.middleware("http")
async def audit_log(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
await log_audit({
"user": request.user.id if request.user else "anonymous",
"action": f"{request.method} {request.url.path}",
"status": response.status_code,
"duration_ms": (time.time() - start_time) * 1000
})
return response
Data Retention
- User sessions: 30 days
- Audit logs: 90 days
- Project data: Until deleted
- Activity logs: 30 days
REQ-051-055: Data retention SHALL be 30 days for user sessions, 90 days for audit logs, 30 days for activity logs, and until deletion for project data.
Technical Design
Architecture Pattern
VizInt follows a layered architecture pattern with clear separation of concerns:
- Presentation Layer - HTMX templates with TailwindCSS styling
- API Layer - FastAPI REST endpoints with request/response models
- Service Layer - Business logic for project, task, and agent management
- Data Layer - Neo4j graph database for persistence and Redis for sessions
REQ-051-056: VizInt SHALL follow a layered architecture with clear separation of concerns across four layers: a Presentation layer of HTMX templates with TailwindCSS styling, an API layer of FastAPI REST endpoints with request/response models, a Service layer holding the business logic for project, task and agent management, and a Data layer of a Neo4j graph database for persistence with Redis for sessions.
Component Interactions
┌─────────────────────────────────────────────────────────────────┐
│ VizInt Web Server │
│ (FastAPI + HTMX + TailwindCSS) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Projects │ │ Tasks │ │ Config │ │
│ │ View │ │ View │ │ View │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └─────────────────┼─────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ API │ │
│ │ Service │ │
│ └──────┬──────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │Orchestrata │ │ Neo4j │ │ WebSocket │ │
│ │ Kernel │ │ KG │ │ Updates │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Data Flow
- User Request Flow: User browser → HTMX request → FastAPI endpoint → Service layer → Neo4j → Response → HTMX swap
- Real-time Updates: Orchestrata kernel → WebSocket broadcast → Client JavaScript → DOM update
- Authentication Flow: OAuth2 provider → Callback → Session creation → Redis storage → Cookie set
State Management
- Server State: Neo4j for persistent data, Redis for sessions and cache
- Client State: HTMX for DOM state, localStorage for offline queue
- Shared State: WebSocket for real-time synchronization across clients
REQ-051-057: Server state SHALL be held in Neo4j for persistent data and in Redis for sessions and cache; client state SHALL be held in HTMX DOM state and in localStorage for the offline queue; shared state SHALL be synchronized across clients over WebSocket.
Examples
Example 1: Creating a New Project
POST /api/projects HTTP/1.1
Host: vizint.orchestrata.local
Content-Type: application/json
Authorization: Bearer <token>
{
"name": "ecommerce-platform",
"template": "fullstack",
"volk_configs": {
"U:Cd": {
"enabled": true,
"model": "claude-3-5-sonnet",
"max_concurrent": 3
},
"U:Qa": {
"enabled": true,
"model": "gpt-4o",
"max_concurrent": 2
}
}
}
Response (201 Created):
{
"project_id": "proj_abc123",
"name": "ecommerce-platform",
"status": "active",
"path": "/home/user/projects/ecommerce-platform",
"task_count": 0,
"agent_count": 2,
"created_at": "2026-04-09T10:00:00Z",
"updated_at": "2026-04-09T10:00:00Z"
}
Example 2: Drag-and-Drop Task Update
PATCH /api/projects/proj_abc123/tasks/T:001/status HTTP/1.1
Host: vizint.orchestrata.local
Content-Type: application/json
Authorization: Bearer <token>
{
"status": "in_progress"
}
Response (200 OK):
{
"task_id": "T:001",
"status": "in_progress",
"updated_at": "2026-04-09T10:05:00Z"
}
WebSocket Broadcast:
{
"type": "task_updated",
"data": {
"task_id": "T:001",
"status": "in_progress",
"assigned_volk": "U:Cd",
"timestamp": "2026-04-09T10:05:00Z"
}
}
Example 3: Governance Rule Creation
POST /api/projects/proj_abc123/rules HTTP/1.1
Host: vizint.orchestrata.local
Content-Type: application/json
Authorization: Bearer <token>
{
"name": "require_code_review",
"scope": "project",
"condition": "action == 'merge' AND has_changes('.py')",
"action": "require_approval",
"priority": 50,
"description": "All Python changes require code review before merge"
}
Response (201 Created):
{
"rule_id": "rule_xyz789",
"name": "require_code_review",
"scope": "project",
"condition": "action == 'merge' AND has_changes('.py')",
"action": "require_approval",
"priority": 50,
"description": "All Python changes require code review before merge",
"created_at": "2026-04-09T10:10:00Z"
}
Integration Points
Orchestrata Kernel Integration
| Endpoint | Purpose | Protocol |
|---|---|---|
/api/orchestrata/* |
Agent command execution | HTTP/REST |
/ws/orchestrata |
Real-time agent events | WebSocket |
/api/cxp/* |
Cross-process communication | CXP |
REQ-051-058: The system SHALL integrate with the Orchestrata kernel over /api/orchestrata/* (HTTP/REST) for agent command execution, /ws/orchestrata (WebSocket) for real-time agent events, and /api/cxp/* (CXP) for cross-process communication.
Neo4j Database Integration
| Operation | Query Type | Frequency |
|---|---|---|
| Project CRUD | Cypher | On user action |
| Task CRUD | Cypher | On user action |
| Relationship queries | Cypher | On page load |
| Full-text search | Cypher | On search |
REQ-051-059: The system SHALL access Neo4j with Cypher: project CRUD and task CRUD on user action, relationship queries on page load, and full-text search on search.
Redis Integration
| Data Type | TTL | Purpose |
|---|---|---|
| User sessions | 30 days | Authentication state |
| CSRF tokens | 1 hour | CSRF protection |
| WebSocket heartbeats | 1 minute | Connection health |
| Rate limit counters | 1 minute | API throttling |
| Offline change queue | Until sync | Offline support |
REQ-051-060: The system SHALL hold in Redis: user sessions with a 30-day TTL for authentication state, CSRF tokens with a 1-hour TTL, WebSocket heartbeats with a 1-minute TTL for connection health, rate-limit counters with a 1-minute TTL for API throttling, and the offline change queue retained until sync.
External OAuth Providers
| Provider | Capability | Config |
|---|---|---|
| GitHub | User authentication | Client ID/Secret |
| User authentication | Client ID/Secret |
REQ-051-061: The system SHALL support user authentication through the GitHub and Google OAuth providers, each configured with a client ID and secret.
Success Criteria
Functional Criteria
| ID | Criterion | Validation Method |
|---|---|---|
| SC-001 | Dashboard displays all projects with status | Visual inspection |
| SC-002 | Tasks can be dragged between Kanban columns | Manual testing |
| SC-003 | Agent configuration changes persist immediately | API verification |
| SC-004 | WebSocket delivers updates within 100ms | Performance test |
| SC-005 | Governance rules block prohibited actions | Rule enforcement test |
| SC-006 | Offline changes sync when connection restored | Offline testing |
REQ-051-062: The dashboard SHALL display all projects with status (SC-001), validated by visual inspection.
REQ-051-063: Tasks SHALL be draggable between Kanban columns (SC-002), validated by manual testing.
REQ-051-064: Agent configuration changes SHALL persist immediately (SC-003), validated by API verification.
REQ-051-065: WebSocket SHALL deliver updates within 100ms (SC-004), validated by performance test.
REQ-051-066: Governance rules SHALL block prohibited actions (SC-005), validated by rule enforcement test.
REQ-051-067: Offline changes SHALL sync when the connection is restored (SC-006), validated by offline testing.
Quality Criteria
| ID | Criterion | Target |
|---|---|---|
| QC-001 | Test coverage | > 80% |
| QC-002 | API availability | 99.9% |
| QC-003 | Page load time | < 500ms |
| QC-004 | Critical vulnerabilities | 0 |
| QC-005 | Accessibility compliance | WCAG 2.1 AA |
REQ-051-107: Test coverage SHALL exceed 80% (QC-001).
REQ-051-108: API availability SHALL be 99.9% (QC-002).
REQ-051-109: Page load time SHALL be under 500ms (QC-003).
REQ-051-110: The number of critical vulnerabilities SHALL be 0 (QC-004).
REQ-051-111: Accessibility SHALL comply with WCAG 2.1 AA (QC-005).
Deployment Criteria
| ID | Criterion | Validation |
|---|---|---|
| DC-001 | Production deployment succeeds | Deployment pipeline |
| DC-002 | Health check endpoint returns 200 | Monitoring |
| DC-003 | No breaking changes to existing APIs | Contract tests |
| DC-004 | Rollback procedure documented | Runbook review |
REQ-051-112: Production deployment SHALL succeed (DC-001), validated by the deployment pipeline.
REQ-051-113: The health check endpoint SHALL return 200 (DC-002), validated by monitoring.
REQ-051-114: The release SHALL introduce no breaking changes to existing APIs (DC-003), validated by contract tests.
REQ-051-115: The rollback procedure SHALL be documented (DC-004), validated by runbook review.
Testing Requirements
Unit Tests
class TestProjectAPI:
async def test_create_project_success(self):
response = await client.post("/api/v1/projects", json={
"name": "Test Project",
"description": "Test"
})
assert response.status_code == 201
async def test_create_project_unauthorized(self):
response = await client.post("/api/v1/projects", json={
"name": "Test"
})
assert response.status_code == 401
Integration Tests
- Database integration
- WebSocket connections
- Authentication flow
- Project CRUD operations
- Task management
REQ-051-116: Integration tests SHALL cover database integration, WebSocket connections, the authentication flow, project CRUD operations, and task management.
E2E Tests
- Complete user workflows
- Cross-browser compatibility
- Mobile responsiveness
- Offline mode functionality
REQ-051-117: End-to-end tests SHALL cover complete user workflows, cross-browser compatibility, mobile responsiveness, and offline mode functionality.
Test Coverage
- Unit tests: >80%
- Integration tests: >90%
- API coverage: 100%
REQ-051-118: Test coverage SHALL exceed 80% for unit tests, SHALL exceed 90% for integration tests, and SHALL be 100% for API coverage.
Performance Targets
Response Times
- Page load: <500ms
- API calls: <200ms
- WebSocket events: <100ms
- Real-time updates: <50ms
Scalability
- Concurrent users: 100
- Projects per user: 50
- Tasks per project: 1000
- Real-time connections: 500
Monitoring
Metrics
- User sessions
- API response times
- Error rates
- WebSocket connections
- Database queries
REQ-051-119: The system SHALL report metrics for user sessions, API response times, error rates, WebSocket connections, and database queries.
Alerts
- High error rate (>5%)
- Slow responses (>1s)
- Authentication failures
- Database connection issues
REQ-051-120: The system SHALL alert on a high error rate (>5%), slow responses (>1s), authentication failures, and database connection issues.
Overview
What
VizInt (Visual Interface) is a modern web-based dashboard for the Ultimate Hybrid system, providing project management, task orchestration, agent configuration, and governance rule editing through a visual interface.
Why
- Provide accessible web UI for non-terminal users
- Enable visual project and task management
- Allow drag-and-drop task orchestration
- Configure agent settings visually
- Edit governance rules with point-and-click interface
How
- FastAPI backend serving HTMX + TailwindCSS frontend
- WebSocket for real-time updates
- Neo4j for data persistence
- Integration with Orchestrata kernel via CXP
Terminology
VizInt
Visual Interface - the web-based dashboard system described in this specification.
Ultimate Hybrid
The orchestrata system combining CheetahClaws TUI and VizInt UI for comprehensive agent management.
CheetahClaws
The TUI (Terminal User Interface) companion to VizInt for command-line agent interactions.
CXP
Communication Protocol - the inter-process communication mechanism between VizInt and the Orchestrata kernel.
HTMX
HTML Markup eXtensions - library for creating dynamic web interfaces using HTML attributes.
WebSocket
Bi-directional communication protocol for real-time updates between server and client.
PAM++
Policy and Authorization Management - the governance framework for enforcing rules and permissions.
Neo4j
Graph database used for storing projects, tasks, and agent relationships.
Agent
An autonomous software entity that performs tasks within the Ultimate Hybrid system.
Project
A container for tasks, agents, and configuration within the Ultimate Hybrid system.
Task
A unit of work assigned to an agent with defined parameters and dependencies.
Architecture
Tech Stack
┌─────────────────────────────────────────────────────────────────┐
│ VizInt Web Server │
│ (FastAPI + HTMX + TailwindCSS) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Projects │ │ Tasks │ │ Config │ │
│ │ View │ │ View │ │ View │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └─────────────────┼─────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ API │ │
│ │ Service │ │
│ └──────┬──────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │Orchestrata │ │ Neo4j │ │ WebSocket │ │
│ │ Kernel │ │ KG │ │ Updates │ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Project Structure
vizint/
├── app/
│ ├── main.py # FastAPI application
│ ├── routes/
│ │ ├── projects.py # Project endpoints
│ │ ├── tasks.py # Task endpoints
│ │ ├── config.py # Configuration endpoints
│ │ ├── rules.py # Governance rules endpoints
│ │ └── ws.py # WebSocket handler
│ ├── services/
│ │ ├── orchestrator.py # Orchestrata integration
│ │ ├── neo4j.py # Neo4j client
│ │ └── todoist.py # Todoist integration
│ ├── models/
│ │ ├── project.py # Project models
│ │ ├── task.py # Task models
│ │ └── config.py # Config models
│ └── templates/ # HTMX templates
│ ├── base.html
│ ├── projects.html
│ ├── tasks.html
│ ├── config.html
│ └── rules.html
├── static/
│ ├── css/
│ │ └── app.css # TailwindCSS
│ └── js/
│ └── app.js # HTMX + interactivity
└── pyproject.toml
API Endpoints
Projects
List Projects
GET /api/projects
Response:
{
"projects": [
{
"project_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "webapp-ecommerce",
"path": "/home/user/projects/ecommerce",
"status": "active",
"session_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
"task_count": 12,
"agent_count": 4,
"created_at": "2026-04-01T10:00:00Z",
"updated_at": "2026-04-08T14:30:00Z"
}
]
}
Create Project
POST /api/projects
Content-Type: application/json
{
"name": "webapp-ecommerce",
"template": "fullstack",
"volk_configs": {
"U:Cd": {"enabled": true, "model": "claude-3-5-sonnet"},
"U:Qa": {"enabled": true, "model": "gpt-4o"}
}
}
Get Project Details
GET /api/projects/{project_id}
Update Project
PUT /api/projects/{project_id}
Content-Type: application/json
{
"name": "webapp-ecommerce-v2",
"volk_configs": {...}
}
Delete Project
DELETE /api/projects/{project_id}
REQ-051-068: The system SHALL expose the project endpoints GET /api/projects (list), POST /api/projects (create, accepting name, template and volk_configs), GET /api/projects/{project_id} (detail), PUT /api/projects/{project_id} (update) and DELETE /api/projects/{project_id} (delete).
Tasks
List Tasks
GET /api/projects/{project_id}/tasks
Query Parameters:
status: Filter by status (pending, in_progress, completed)assigned_volk: Filter by assigned agent
Create Task
POST /api/projects/{project_id}/tasks
Content-Type: application/json
{
"title": "Implement user authentication",
"description": "Add OAuth2 and JWT support",
"assigned_volk": "U:Cd",
"priority": 1,
"due_date": "2026-04-15T00:00:00Z",
"depends_on": []
}
Update Task
PUT /api/projects/{project_id}/tasks/{task_id}
Content-Type: application/json
{
"status": "completed",
"assigned_volk": "U:Cd"
}
Update Task Status (Drag & Drop)
PATCH /api/projects/{project_id}/tasks/{task_id}/status
Content-Type: application/json
{
"status": "in_progress"
}
REQ-051-069: The system SHALL expose the task endpoints GET /api/projects/{project_id}/tasks (list, filterable by the status and assigned_volk query parameters), POST /api/projects/{project_id}/tasks (create), PUT /api/projects/{project_id}/tasks/{task_id} (update) and PATCH /api/projects/{project_id}/tasks/{task_id}/status (drag-and-drop status update).
Configuration
Get Agent Configuration
GET /api/projects/{project_id}/config/agents
Update Agent Configuration
PUT /api/projects/{project_id}/config/agents/{agent_alias}
Content-Type: application/json
{
"model": "gpt-4o",
"enabled": true,
"max_concurrent": 3,
"timeout": 300,
"tools": ["Read", "Write", "Edit", "Bash"]
}
REQ-051-070: The system SHALL expose the agent-configuration endpoints GET /api/projects/{project_id}/config/agents and PUT /api/projects/{project_id}/config/agents/{agent_alias}, the latter accepting model, enabled, max_concurrent, timeout and tools.
Governance Rules
List Rules
GET /api/projects/{project_id}/rules
Create Rule
POST /api/projects/{project_id}/rules
Content-Type: application/json
{
"name": "no_delete_prod",
"scope": "project",
"condition": "action == 'delete' AND path contains 'prod'",
"action": "deny",
"priority": 100
}
Update Rule
PUT /api/projects/{project_id}/rules/{rule_id}
Delete Rule
DELETE /api/projects/{project_id}/rules/{rule_id}
REQ-051-071: The system SHALL expose the governance-rule endpoints GET /api/projects/{project_id}/rules (list), POST /api/projects/{project_id}/rules (create, accepting name, scope, condition, action and priority), PUT /api/projects/{project_id}/rules/{rule_id} (update) and DELETE /api/projects/{project_id}/rules/{rule_id} (delete).
WebSocket
Connect
WS /ws/{project_id}
Messages (Server → Client):
{
"type": "task_updated",
"data": {
"task_id": "task-123",
"status": "in_progress",
"assigned_volk": "U:Cd",
"timestamp": "2026-04-08T14:30:00Z"
}
}
{
"type": "agent_status",
"data": {
"U:Cd": {"status": "active", "current_task": "task-123"},
"U:Qa": {"status": "idle", "current_task": null}
}
}
{
"type": "checkpoint_created",
"data": {
"checkpoint_id": "c5",
"description": "OAuth2 implementation",
"timestamp": "2026-04-08T14:30:00Z"
}
}
REQ-051-072: The system SHALL accept WebSocket connections at WS /ws/{project_id} and SHALL send server-to-client messages carrying a type and a data payload, including task_updated, agent_status and checkpoint_created.
Frontend Components
Base Layout
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VizInt - Ultimate Hybrid Dashboard</title>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="/static/css/app.css">
</head>
<body class="bg-gray-900 text-gray-100">
<div class="flex h-screen">
<!-- Sidebar -->
<aside class="w-64 bg-gray-800 border-r border-gray-700 flex flex-col">
<div class="p-4 border-b border-gray-700">
<h1 class="text-xl font-bold text-cyan-400">VizInt</h1>
<p class="text-xs text-gray-400">Ultimate Hybrid Dashboard</p>
</div>
<nav class="flex-1 p-4 space-y-2">
<a href="/projects"
class="flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-700"
hx-get="/partials/nav/projects" hx-target="#main-content">
<svg class="w-5 h-5">...</svg>
Projects
</a>
<a href="/tasks"
class="flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-700"
hx-get="/partials/nav/tasks" hx-target="#main-content">
<svg class="w-5 h-5">...</svg>
Tasks
</a>
<a href="/config"
class="flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-700"
hx-get="/partials/nav/config" hx-target="#main-content">
<svg class="w-5 h-5">...</svg>
Configuration
</a>
<a href="/rules"
class="flex items-center gap-3 px-4 py-2 rounded-lg hover:bg-gray-700"
hx-get="/partials/nav/rules" hx-target="#main-content">
<svg class="w-5 h-5">...</svg>
Rules
</a>
</nav>
<!-- Status Bar -->
<div class="p-4 border-t border-gray-700">
<div class="flex items-center gap-2 text-sm">
<span class="w-2 h-2 rounded-full bg-green-500"></span>
<span>System Online</span>
</div>
</div>
</aside>
<!-- Main Content -->
<main class="flex-1 flex flex-col overflow-hidden">
<!-- Header -->
<header class="h-16 bg-gray-800 border-b border-gray-700 flex items-center justify-between px-6">
<div class="flex items-center gap-4">
<h2 class="text-lg font-semibold" id="page-title">Projects</h2>
</div>
<div class="flex items-center gap-4">
<button class="px-4 py-2 bg-cyan-600 rounded-lg hover:bg-cyan-700">
+ New Project
</button>
</div>
</header>
<!-- Content Area -->
<div id="main-content" class="flex-1 overflow-auto p-6">
<!-- Dynamic Content Loaded Here -->
</div>
</main>
</div>
<!-- WebSocket Connection -->
<script src="/static/js/websocket.js"></script>
</body>
</html>
Projects View
<!-- projects.html -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Project Card -->
<div class="bg-gray-800 rounded-xl border border-gray-700 overflow-hidden hover:border-cyan-500 transition-colors cursor-pointer"
hx-get="/api/projects/{{ project.id }}"
hx-target="#project-detail">
<div class="p-4">
<div class="flex items-start justify-between">
<div>
<h3 class="text-lg font-semibold text-white">{{ project.name }}</h3>
<p class="text-sm text-gray-400">{{ project.path }}</p>
</div>
<span class="px-2 py-1 text-xs rounded-full
{% if project.status == 'active' %}bg-green-900 text-green-300
{% else %}bg-gray-700 text-gray-400{% endif %}">
{{ project.status }}
</span>
</div>
<div class="mt-4 flex items-center gap-4 text-sm text-gray-400">
<div class="flex items-center gap-1">
<svg class="w-4 h-4">...</svg>
{{ project.task_count }} tasks
</div>
<div class="flex items-center gap-1">
<svg class="w-4 h-4">...</svg>
{{ project.agent_count }} agents
</div>
</div>
<!-- Agent Status -->
<div class="mt-4 flex items-center gap-2">
{% for agent in project.agents %}
<div class="flex items-center gap-1 text-xs">
<span class="w-2 h-2 rounded-full
{% if agent.status == 'active' %}bg-green-500
{% elif agent.status == 'idle' %}bg-yellow-500
{% else %}bg-gray-500{% endif %}">
</span>
{{ agent.alias }}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
Tasks View (Kanban)
<!-- tasks.html -->
<div class="flex gap-6 h-full">
<!-- Pending Column -->
<div class="flex-1 bg-gray-800 rounded-xl p-4"
hx-controller="tasks"
hx-get="/api/projects/{{ project_id }}/tasks?status=pending"
hx-trigger="task_updated from:body">
<div class="flex items-center justify-between mb-4">
<h3 class="font-semibold text-gray-300">Pending</h3>
<span class="px-2 py-1 text-xs bg-gray-700 rounded-full">{{ pending_count }}</span>
</div>
<div class="space-y-3 min-h-[200px]"
hx-drop-zone="true"
hx-put="/api/projects/{{ project_id }}/tasks/drop?status=pending">
{% for task in pending_tasks %}
<div class="bg-gray-700 rounded-lg p-3 cursor-move"
draggable="true"
hx-put="/api/projects/{{ project_id }}/tasks/{{ task.id }}/status"
hx-vals='{"status": "pending"}'>
<div class="flex items-start justify-between">
<h4 class="font-medium text-white">{{ task.title }}</h4>
<span class="text-xs text-gray-400">P{{ task.priority }}</span>
</div>
<p class="mt-2 text-sm text-gray-400 line-clamp-2">
{{ task.description }}
</p>
<div class="mt-3 flex items-center justify-between">
<span class="text-xs text-gray-500">
{{ task.assigned_volk }}
</span>
{% if task.due_date %}
<span class="text-xs text-gray-500">
Due: {{ task.due_date }}
</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
<!-- In Progress Column -->
<div class="flex-1 bg-gray-800 rounded-xl p-4">
<div class="flex items-center justify-between mb-4">
<h3 class="font-semibold text-yellow-300">In Progress</h3>
<span class="px-2 py-1 text-xs bg-yellow-900 text-yellow-300 rounded-full">
{{ in_progress_count }}
</span>
</div>
<!-- Tasks with progress bars -->
</div>
<!-- Completed Column -->
<div class="flex-1 bg-gray-800 rounded-xl p-4">
<div class="flex items-center justify-between mb-4">
<h3 class="font-semibold text-green-300">Completed</h3>
<span class="px-2 py-1 text-xs bg-green-900 text-green-300 rounded-full">
{{ completed_count }}
</span>
</div>
</div>
</div>
Agent Configuration View
<!-- config.html -->
<div class="space-y-6">
{% for agent in agents %}
<div class="bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center justify-between mb-4">
<div class="flex items-center gap-3">
<span class="w-3 h-3 rounded-full
{% if agent.enabled %}bg-green-500{% else %}bg-gray-500{% endif %}">
</span>
<h3 class="text-lg font-semibold">{{ agent.alias }}</h3>
<span class="text-gray-400">{{ agent.role }}</span>
</div>
<label class="flex items-center gap-2">
<input type="checkbox"
{% if agent.enabled %}checked{% endif %}
class="form-checkbox h-5 w-5 text-cyan-600"
hx-put="/api/projects/{{ project_id }}/config/agents/{{ agent.alias }}/toggle">
<span class="text-sm text-gray-300">Enabled</span>
</label>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm text-gray-400 mb-2">Model</label>
<select class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"
hx-put="/api/projects/{{ project_id }}/config/agents/{{ agent.alias }}/model">
{% for model in available_models %}
<option value="{{ model.id }}"
{% if model.id == agent.model %}selected{% endif %}>
{{ model.name }} ({{ model.provider }})
</option>
{% endfor %}
</select>
</div>
<div>
<label class="block text-sm text-gray-400 mb-2">Max Concurrent</label>
<input type="number" value="{{ agent.max_concurrent }}"
class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"
hx-put="/api/projects/{{ project_id }}/config/agents/{{ agent.alias }}/max_concurrent">
</div>
<div>
<label class="block text-sm text-gray-400 mb-2">Timeout (seconds)</label>
<input type="number" value="{{ agent.timeout }}"
class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"
hx-put="/api/projects/{{ project_id }}/config/agents/{{ agent.alias }}/timeout">
</div>
<div>
<label class="block text-sm text-gray-400 mb-2">Cost Limit ($)</label>
<input type="number" step="0.01" value="{{ agent.cost_limit }}"
class="w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2"
hx-put="/api/projects/{{ project_id }}/config/agents/{{ agent.alias }}/cost_limit">
</div>
</div>
<div class="mt-4">
<label class="block text-sm text-gray-400 mb-2">Tools</label>
<div class="flex flex-wrap gap-2">
{% for tool in available_tools %}
<label class="flex items-center gap-2 px-3 py-1 bg-gray-700 rounded-lg cursor-pointer hover:bg-gray-600">
<input type="checkbox"
{% if tool in agent.tools %}checked{% endif %}
class="form-checkbox h-4 w-4 text-cyan-600"
hx-put="/api/projects/{{ project_id }}/config/agents/{{ agent.alias }}/tools/{{ tool }}">
<span class="text-sm">{{ tool }}</span>
</label>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>
Governance Rules View
<!-- rules.html -->
<div class="space-y-6">
<!-- Global Rules Section -->
<div class="bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">Global Rules</h3>
<button class="px-3 py-1 bg-cyan-600 rounded-lg hover:bg-cyan-700 text-sm"
hx-get="/partials/rules/create?scope=global"
hx-target="#rule-form">
+ Add Rule
</button>
</div>
<div class="space-y-3">
{% for rule in global_rules %}
<div class="flex items-center justify-between p-3 bg-gray-700 rounded-lg">
<div class="flex items-center gap-3">
<span class="px-2 py-1 text-xs font-medium rounded
{% if rule.action == 'deny' %}bg-red-900 text-red-300
{% elif rule.action == 'allow' %}bg-green-900 text-green-300
{% else %}bg-yellow-900 text-yellow-300{% endif %}">
{{ rule.action|upper }}
</span>
<span class="font-medium">{{ rule.name }}</span>
</div>
<div class="flex items-center gap-2 text-sm text-gray-400">
<span>Priority: {{ rule.priority }}</span>
<button class="p-1 hover:text-white"
hx-delete="/api/projects/{{ project_id }}/rules/{{ rule.id }}">
<svg class="w-4 h-4">...</svg>
</button>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- Project Rules Section -->
<div class="bg-gray-800 rounded-xl p-6 border border-gray-700">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">Project Rules</h3>
<button class="px-3 py-1 bg-cyan-600 rounded-lg hover:bg-cyan-700 text-sm"
hx-get="/partials/rules/create?scope=project"
hx-target="#rule-form">
+ Add Rule
</button>
</div>
<!-- Rule form container -->
<div id="rule-form" class="mb-4"></div>
<div class="space-y-3">
{% for rule in project_rules %}
<div class="p-3 bg-gray-700 rounded-lg">
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<span class="px-2 py-1 text-xs font-medium rounded
{% if rule.action == 'deny' %}bg-red-900 text-red-300
{% elif rule.action == 'allow' %}bg-green-900 text-green-300
{% else %}bg-yellow-900 text-yellow-300{% endif %}">
{{ rule.action|upper }}
</span>
<span class="font-medium">{{ rule.name }}</span>
</div>
<div class="flex items-center gap-2">
<button class="p-1 hover:text-white"
hx-get="/api/projects/{{ project_id }}/rules/{{ rule.id }}/edit"
hx-target="#rule-form">
<svg class="w-4 h-4">...</svg>
</button>
<button class="p-1 hover:text-white"
hx-delete="/api/projects/{{ project_id }}/rules/{{ rule.id }}">
<svg class="w-4 h-4">...</svg>
</button>
</div>
</div>
<p class="mt-2 text-sm text-gray-400">{{ rule.description }}</p>
<code class="mt-2 block text-xs bg-gray-800 p-2 rounded">
{{ rule.condition }}
</code>
</div>
{% endfor %}
</div>
</div>
</div>
WebSocket Events
Server-Side Implementation
from fastapi import WebSocket
from typing import Dict, Set
class WebSocketManager:
"""Manages WebSocket connections for real-time updates."""
def __init__(self):
self.active_connections: Dict[str, Set[WebSocket]] = {}
async def connect(self, project_id: str, websocket: WebSocket):
"""Connect a new WebSocket client."""
await websocket.accept()
if project_id not in self.active_connections:
self.active_connections[project_id] = set()
self.active_connections[project_id].add(websocket)
def disconnect(self, project_id: str, websocket: WebSocket):
"""Disconnect a WebSocket client."""
if project_id in self.active_connections:
self.active_connections[project_id].discard(websocket)
async def broadcast(self, project_id: str, message: dict):
"""Broadcast message to all clients for a project."""
if project_id in self.active_connections:
for connection in self.active_connections[project_id]:
try:
await connection.send_json(message)
except Exception:
# Remove dead connections
self.active_connections[project_id].discard(connection)
Event Types
class WebSocketEvents:
"""WebSocket event types and payloads."""
TASK_UPDATED = "task_updated"
TASK_CREATED = "task_created"
TASK_DELETED = "task_deleted"
AGENT_STATUS = "agent_status"
AGENT_PROGRESS = "agent_progress"
CHECKPOINT_CREATED = "checkpoint_created"
CHECKPOINT_RESTORED = "checkpoint_restored"
RULE_UPDATED = "rule_updated"
RULE_VIOLATION = "rule_violation"
PROJECT_UPDATED = "project_updated"
REQ-051-073: The WebSocket event vocabulary SHALL be task_updated, task_created, task_deleted, agent_status, agent_progress, checkpoint_created, checkpoint_restored, rule_updated, rule_violation and project_updated.
Styling
Custom CSS
/* app.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn-primary {
@apply px-4 py-2 bg-cyan-600 text-white rounded-lg hover:bg-cyan-700 transition-colors;
}
.btn-secondary {
@apply px-4 py-2 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors;
}
.card {
@apply bg-gray-800 rounded-xl border border-gray-700 overflow-hidden;
}
.input-field {
@apply w-full bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-white focus:outline-none focus:border-cyan-500;
}
.status-active {
@apply w-2 h-2 rounded-full bg-green-500;
}
.status-idle {
@apply w-2 h-2 rounded-full bg-yellow-500;
}
.status-offline {
@apply w-2 h-2 rounded-full bg-gray-500;
}
}
/* Smooth transitions */
* {
transition-property: background-color, border-color, color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #1f2937;
}
::-webkit-scrollbar-thumb {
background: #4b5563;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
JavaScript
WebSocket Client
// websocket.js
class VizIntWebSocket {
constructor(projectId) {
this.projectId = projectId;
this.ws = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
}
connect() {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
this.ws = new WebSocket(`${protocol}//${window.location.host}/ws/${this.projectId}`);
this.ws.onopen = () => {
console.log('WebSocket connected');
this.reconnectAttempts = 0;
this.setupHeartbeat();
};
this.ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.handleMessage(message);
};
this.ws.onclose = () => {
console.log('WebSocket disconnected');
this.attemptReconnect();
};
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
}
handleMessage(message) {
switch (message.type) {
case 'task_updated':
this.updateTaskCard(message.data);
break;
case 'agent_status':
this.updateAgentStatus(message.data);
break;
case 'checkpoint_created':
this.showNotification('Checkpoint created', 'success');
break;
case 'rule_violation':
this.showNotification(`Rule violation: ${message.data.rule}`, 'error');
break;
}
}
updateTaskCard(data) {
const card = document.querySelector(`[data-task-id="${data.task_id}"]`);
if (card) {
card.setAttribute('hx-vals', JSON.stringify({ status: data.status }));
htmx.process(card);
}
}
updateAgentStatus(agents) {
for (const [alias, status] of Object.entries(agents)) {
const indicator = document.querySelector(`[data-agent="${alias}"]`);
if (indicator) {
indicator.className = `w-3 h-3 rounded-full ${
status.status === 'active' ? 'bg-green-500' :
status.status === 'idle' ? 'bg-yellow-500' : 'bg-gray-500'
}`;
}
}
}
showNotification(message, type) {
// Show toast notification
const toast = document.createElement('div');
toast.className = `fixed bottom-4 right-4 px-4 py-2 rounded-lg ${
type === 'success' ? 'bg-green-600' : 'bg-red-600'
} text-white`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
}
attemptReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
setTimeout(() => this.connect(), 1000 * this.reconnectAttempts);
}
}
setupHeartbeat() {
setInterval(() => {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify({ type: 'ping' }));
}
}, 30000);
}
}
// Initialize WebSocket when page loads
document.addEventListener('DOMContentLoaded', () => {
const projectId = new URLSearchParams(window.location.search).get('project');
if (projectId) {
const ws = new VizIntWebSocket(projectId);
ws.connect();
}
});