Orchestrata Ultimate › Plans › spec-audit › G-gateway-ui
Cluster G — Gateway, UI, TUI & plugins (spec audit + plan)
Source: plans/spec-audit/G-gateway-ui.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-04 · 137 lines.
Prose pending.
Plan text
Cluster G — Gateway, UI, TUI & plugins (spec audit + plan)
Investigation agent G. READ-ONLY audit of src/orchestrata_ultimate/gateway/,
orchestrator/, integrations/cheetahclaws/, plugin/, kernel/ CLIs, and the
vizint-ui/ web app. Evidence by code only (spec - [ ] markers ignored per _METHOD.md).
Builds on docs/spec-gap-register.md (which audited 014, 015, 016).
Specs: 014, 015, 016, 022, 050, 051.
SPEC-014 WebSocket Gateway — PARTIAL (core DONE; auth divergence + HTTP-observability gap)
- Specifies: Real-time control plane — WS server, JSON-RPC 2.0 dispatch, pluggable auth, pub/sub topics, ring-buffer replay, heartbeat, PAM++ authorization, HTTP health/metrics, audit.
- Verified:
- ✅ WS server + lifecycle —
WebSocketGatewaygateway/server.py:182(constructed bygateway/cli.pyserve; live per memory sessions 165/193). - ✅ JSON-RPC dispatch + full method surface —
RPCHandler.dispatchgateway/rpc.py:213; registrygateway/rpc.py:275-373implements every FR-015–FR-020 method (cxp.*,volk.*,session.*,governance.*,knowledge.*,gateway.*) plus extras (state.*,memory.*,projects.*,orchestrator.intent,tui.*,fireflies.*,tests.run). - ✅ Ring buffer + replay (FR-012/US-008) —
RedisRingBuffer+GatewayHandler.handle_replaygateway/handlers/gateway.py:205. - ✅ Heartbeat (FR-014) —
ConnectionManager.update_heartbeatgateway/session.py:124. - ✅ Audit trail (FR-024) —
AuditWriterlogged on every dispatchgateway/rpc.py:238. - ✅ Serve CLI (US-010) —
gateway/cli.py:44(orchestrata-gateway serve|version). - ⚠️ Auth is a single JWT
TokenAuthenticatorgateway/auth.py:16, not the spec's pluggableIAuthStrategyshippingStaticTokenAuth/HMACAuth/PrologPolicyAuth(FR-005–008). Grep forIAuthStrategy|StaticTokenAuth|HMACAuth|PrologPolicyAuth→ 0 hits. (Confirms register's divergence row.) - ⚠️ No
IGatewayServerABC /ComponentType.GATEWAYDI registration (FR-001) — grepIGatewayServer→ 0 hits; the class isWebSocketGateway, constructed directly. Structural, not functional. - ❌ No HTTP
/health/ready/metricsand no Prometheus metrics (FR-021/022, US-009). Grep for/health|/ready|/metrics|prometheus|start_http_serverundergateway/→ 0 hits.gateway/config.pyhas nometrics_port/health_enabled/metrics_enabledfields. (VizIntWebUIgateway/server.py:675is just an empty WS alias, serves no HTTP.)
- ✅ WS server + lifecycle —
- Remaining work / plan:
- Scope: add an HTTP surface alongside the WS server —
/health(200/503),/ready(Redis/Neo4j/Prolog/kernel probes),/metrics(Prometheus). Addmetrics_port/health_enabledtoGatewayConfig. (Auth-strategy abstraction: recommend update the spec to record the JWT divergence rather than build 3 strategies, unless HMAC/Prolog auth is actually required — surface as a decision.) - Target files:
gateway/server.py(bind an aiohttp/asgi HTTP listener),gateway/config.py(new fields), newgateway/http_health.py; spec update tospecs/014-websocket-gateway/spec.mdfor the auth divergence. - Approach: reuse the existing health-probe pattern already used for the gateway↔engine fallback; export counters the handlers already track (connected_clients, rpc latency, auth success/failure).
- Dependencies: SPEC-032 concierge/pipeline (kernel readiness the
/readyprobe reports), Redis/Neo4j/Prolog infra,governance(Prolog auth if the strategy work is chosen). Loose coupling to SPEC-011 provider events (already forwarded). - Effort: M (HTTP health/metrics). Risk: low. Auth-strategy build (if chosen) is M/L, med risk (security surface).
- Scope: add an HTTP surface alongside the WS server —
- Evidence log:
grep -rnE '/health|/ready|/metrics|prometheus|aiohttp' src/…/gateway/→ 0;grep metrics_port|health_enabled gateway/config.py→ 0;grep IAuthStrategy|StaticTokenAuth|HMACAuth→ 0;rpc.pyregistry read;symbols WebSocketGateway.
SPEC-015 Plugin SDK — PARTIAL / ORPHANED (full SDK built, disconnected from the running system)
- Specifies: Runtime extension framework —
IPluginManager(DIComponentType.PLUGIN_MANAGER), discovery, validation, load/lifecycle, SDK registration (volk/tool/provider/channel/rules/kg), capability enforcement, PAM++ governance, resource limits,orchestrata pluginsCLI,plugins.listRPC, audit. - Verified:
- ✅ SDK + manager fully implemented —
PluginManagerplugin/manager.py:48;IPluginManagerABCplugin/interfaces.py:350+(discover/list/enable/disable/install/uninstall); module-levelinstall_plugin/uninstall_plugin/enable_plugin/disable_pluginplugin/discovery.py:61/179/219/267;PluginContext, loader, registry, manifest, capability governance, PAM++ predicates all present underplugin/. - ❌ The subsystem is orphaned.
refs PluginManager→ 1 def + 2 imports/uses, all insideplugin/(plugin/sdk.py). GrepPluginManager\(|discover_plugins|load_plugin|list_pluginsoutsideplugin/→ 0 hits. It is never instantiated at kernel bootstrap. - ❌ Not DI-registered (FR-001). Grep
PLUGIN_MANAGERacross src → 0 hits;ComponentType.PLUGIN_MANAGERdoes not exist. - ❌ No CLI surface (FR-014/015/016). No
add_parser("plugins"); the SPEC-000 Click CLI (kernel/cli_main.py:302cligroup) exposes onlystart/version/health. Noorchestrataconsole-script entry inpyproject.tomleither. - ❌ No
plugins.listgateway RPC (US-007 last criterion). Absent fromgateway/rpc.pyregistry.
- ✅ SDK + manager fully implemented —
- Remaining work / plan:
- Scope: (1) construct + start
PluginManagerin the monolithic boot (_boot_monolithic) and register it in the DI container under a newComponentType.PLUGIN_MANAGER; (2) hang apluginssubcommand group (list/info/install/uninstall/enable/disable) on the SPEC-000 Click CLI, delegating to the ready-madeplugin/discovery.pyfunctions +manager.list_plugins(); (3) add aPluginsHandlerwithplugins.list/plugins.install/… to the gateway RPC registry. - Target files:
kernel/cli_main.py(new@cli.group() plugins),core/*(addComponentType.PLUGIN_MANAGER+ DI register in boot), newgateway/handlers/plugins.py+ wire ingateway/rpc.py. - Approach: additive — the manager/discovery/registry code is complete and tested-shaped; this is wiring + thin CLI/RPC adapters, not new logic.
- Dependencies: SPEC-000 (CLI) — needs the
orchestrataClick entry to be a real console-script + a place to add subcommands; SPEC-014 (gateway) for theplugins.*RPC; kernel/DI forComponentType. - Effort: M. Risk: med — starting the plugin manager at boot means real plugin loading/governance runs in the live process (error-isolation matters).
- Scope: (1) construct + start
- Evidence log:
refs PluginManager;grep PluginManager\(|discover_plugins|PLUGIN_MANAGERoutside plugin/ → 0;symbols install_plugin|enable_plugin→ discovery.py;cli_main.pycliClick group read; pyproject[project.scripts]read (noorchestrata).
SPEC-016 VizInt Command Center — DONE (confirm register)
- Specifies: Browser command center over the SPEC-014 gateway (JSON-RPC/WS), 10 P1 orchestration gadgets + backend Session/Projects handlers.
- Verified:
- ✅ All 10 P1 gadgets present —
vizint-ui/gadgets/: project-explorer, session-manager, cxp-feed, volk-status, claude-chat, task-board, qa-dashboard, audit-trail, kg-explorer, notification-center (+ extras: orchestrator, debug-panel, calendar, todoist). - ✅ Portal + bridge framework present —
vizint-ui/lib/{portal,bus,registry,chrome,shared}.js,vizint-ui/bridge/{websocket-bridge,gadget-bridge,state-sync,notification-manager}.js. - ✅ FR-027 SessionHandler —
gateway/handlers/session.pywired (session.active/list/get/open/close/events/facts.subscribeinrpc.py:300-306). - ✅ FR-028 ProjectsHandler —
gateway/handlers/projects.pywired (projects.list/get/tasks/taskCreate/taskUpdaterpc.py:317-321). - ✅ Pipeline→UI wiring done —
orchestrator.intent+state.*RPC live (memory: session 193 SPEC-016 wiring; gRPC health-probe fallback + broadcast delivery). - ⚠️ Spec-accuracy nit (not a gap): spec claims 31 gadgets; repo ships 14 (10 P1 + 4). The 21 "personal" gadgets (flashcards/prayer/iqama/etc.) are upstream-portal inventory, not vendored here — the inventory in the spec is aspirational. No functional impact on the orchestration surface.
- ✅ All 10 P1 gadgets present —
- Remaining work / plan: none required for classification DONE. Optional: correct the gadget-inventory count in the spec. Individual per-US
- [ ]sub-items in the spec (inline task edit, CSV export, cypher autocomplete, etc.) are frontend polish, JS-only, out of the Python audit scope. - Evidence log:
ls vizint-ui/gadgets(14);ls vizint-ui/{lib,bridge};rpc.pyregistry rows for session/projects; register row (SPEC-016 clean).
SPEC-022 Terminal User Interface — GAP (Design Phase; essentially unimplemented)
- Specifies: A Textual three-panel app (
tui_app.py+panels/+widgets/+tui.tcss) launched viaorchestrata tui, replacing thepipeline_cli.pyREPL; real-time thread/chat/status panels, command palette, approval workflow. - Verified:
- ❌ No Textual anywhere.
grep -rl 'import textual|from textual|Textual' src/→ 0 files;textualis not inpyproject.tomldeps (onlyrich,click). - ❌ No
orchestrata tuicommand and notui_app.py/panels//widgets//tui.tcss. The only "tui" token is the gateway RPC prefix ingateway/handlers/ultimatetui.py:38(SPEC-050 browser bridge, unrelated to a terminal UI). - ⚠️ The REPL the spec intends to replace still exists —
kernel/pipeline_cli.py(basicinput()/print()loop overPipelineRunner). Spec status is literally "Design Phase", so this is planned scope, not a regression.
- ❌ No Textual anywhere.
- Remaining work / plan:
- Scope: build the Textual app per the spec —
tui_app.py(3-panel grid: ThreadList | Chat | Status + input + header/footer),panels/{thread_list,chat,status}.py,widgets/{input_area,command_palette}.py,tui.tcss; register anorchestrata tuisubcommand; drive it via theTUIKernelInterface(submit_intent/respond/approve/reject/get_status/subscribe) againstPipelineRunner/PipelineKernel. Addtextual>=0.90to deps. - Target files: new
src/orchestrata_ultimate/tui/package;kernel/cli_main.py(@cli.command() tui);pyproject.toml(textual dep + declare it). - Approach: greenfield but well-scoped; reuse existing
pipeline_clicommand semantics (intent/respond/approve/status) as the kernel adapter; the gatewaytui.*/orchestrator.intentRPC path is an alternative backend if a WS-based TUI is preferred over direct kernel calls. - Dependencies: SPEC-000 (CLI) for the
orchestrata tuisubcommand + console entry; kernelPipelineRunner/PipelineKernel(approve/reject surface — overlaps the SPEC-023 goal/approval area); new Textual dependency (must be declared —check-depsgate). - Effort: L (>2d, full app). Risk: med — approval workflow couples to governance (Article I) and the human-in-the-loop semantics.
- Scope: build the Textual app per the spec —
- Evidence log:
grep -rl textual src/→ 0;grep 'add_parser(.tui|orchestrata tui'→ onlyultimatetui.py:38RPC prefix;grep textual pyproject.toml→ 0;pipeline_cli.pyhead read.
SPEC-050 CheetahClaws Integration — PARTIAL (multi-agent edit wired; checkpoint/40+-commands/live-diff/path-traversal missing)
Register/orchestrator marked "clean", but SPEC-050 was not in the register's audited set (002…032). Code shows real remaining work.
- Specifies: CheetahClaws Rich TUI + 40+ slash commands routed through the kernel, multi-agent (Cd/Qa/Ar/Ux) coordinated edits, PAM++ governance, checkpoint create/restore, multi-provider model switching, live diff, audit.
- Verified:
- ✅ FR-001 multi-agent edit —
MultiAgentCoordinator.dispatch_reviewintegrations/cheetahclaws/__init__.py:119(parallel Cd/Qa/Ar[/Ux], BLOCK rejects);UltimateTUI.handle_edit:281. - ✅ FR-002 governance pre-edit —
GovernanceBridge.can_edit:221(10 MB cap, null-byte binary detect, secret-name + blocked-path patterns). - ✅ Live surface wired —
UltimateTUIHandlerexposestui.edit/intent/agents/models/model_switch/readgateway/handlers/ultimatetui.py, registered inrpc.py:325-344and consumed by the VizInt orchestrator gadget. - ✅ Intent pipeline (FR-009 partial) —
handle_intent:353→PipelineRunner.run. - ❌ FR-003/FR-004 checkpoint create/restore + US-002 NOT wired to the CC surface — no
/checkpoint//rewind; grepCheckpointManagerunderintegrations/+gateway/→ 0 hits. (A realCheckpointManagerexists atsession/checkpoint.py:21andkernel/pipeline_checkpoint.py, but it is a separate session subsystem, not exposed as a CC command.) - ❌ FR-005 path-traversal (
../) not enforced —GovernanceBridge.can_editchecks size/binary/secrets/blocked-list but never rejects... TheEditRequestJSON-schema declares the pattern; the code does not. - ⚠️ FR-008 multi-provider model switch is profile-based (
tui.model_switch→select_profile), not the spec's per-agent/model switch U:Cd gpt-4owith cost/fallback. Divergence — consistent with the SPEC-028 "profiles-only, no env overrides" design (register). - ❌ FR-009 "40+ commands": only ~6
tui.*RPC methods exist (edit/intent/agents/models/model_switch/read); the 40-command catalog is not routed. - ❌ FR-012 live diff rendering — absent.
- 🐞 Dead code + latent bug (surface, don't fix):
UltimateTUI.route_commandcheetahclaws/__init__.py:379has 0 refs (refs route_command→ 1 def / 0 uses) and would raiseAttributeErrorif ever called — it doesasyncio.iscoroutinefunction(handler.__wrapped__)on plain lambdas that have no__wrapped__. Candidate for deletion, or fix if the 40-command router is revived.
- ✅ FR-001 multi-agent edit —
- Remaining work / plan:
- Scope: (1) add
tui.checkpoint/tui.rewind/tui.listRPC + CC handlers delegating to the existingsession/checkpoint.pyCheckpointManager(or the pipeline checkpoint) — capturing files+session+KG per FR-003; (2) enforce..rejection inGovernanceBridge.can_edit(FR-005); (3) decide the 40-command scope (route what's real, drop the aspirational catalog + delete/fix deadroute_command); (4) optionally live-diff (FR-012). Reconcile FR-008 model spec to the profile model or build per-agent switch. - Target files:
integrations/cheetahclaws/__init__.py(path check, checkpoint methods, remove/repairroute_command),gateway/handlers/ultimatetui.py+gateway/rpc.py(newtui.checkpoint/rewindmethods), spec update for FR-008/FR-009 scope. - Approach: wiring over the existing
CheckpointManager+ a 4-line path guard is small; the 40-command catalog + live diff is a scope decision, not required for the core edit flow. - Dependencies: session subsystem (
CheckpointManager, SPEC-024/session), SPEC-014 gateway RPC, SPEC-016 VizInt orchestrator gadget (consumer), SPEC-028 LLM profile design (for FR-008 reconciliation), pipeline (PipelineRunner). - Effort: M (checkpoint wiring + path guard + dead-code cleanup). Risk: low–med (checkpoint restore touches files/session/KG atomically).
- Scope: (1) add
- Evidence log: read
integrations/cheetahclaws/__init__.py+gateway/handlers/ultimatetui.py;refs route_command→ 0 uses;symbols Checkpoint(session/checkpoint.py:21, kernel/pipeline_checkpoint.py);grep CheckpointManager integrations/ gateway/→ 0.
SPEC-051 VizInt UI — DIVERGENCE (deprecated; superseded by SPEC-016 — no action)
- Specifies: A FastAPI + HTMX + TailwindCSS web dashboard (
VizIntWebUI, REST/api/projects, Jinja templates, OAuth2, CSRF). The spec.md header (line 1) itself declares it DEPRECATED — superseded by SPEC-016. - Verified:
- ✅ Deprecation is authoritative —
specs/051-vizint-ui/spec.md:1"⚠️ DEPRECATED … superseded by SPEC-016", Status = "Deprecated". - ✅ The FastAPI/HTMX app was never built — no
htmx/tailwindFastAPI app, no/api/projectsREST routes, noapp/routes/*, no Jinjatemplates/. GrepVizIntWebUI|htmx|/api/projectsin src → the onlyVizIntWebUIis an empty WS aliasgateway/server.py:675(class VizIntWebUI(WebSocketGateway): pass), not the HTMX server the spec describes. - ✅ The real UI is the SPEC-016 zero-build ES-module
vizint-ui/talking to the SPEC-014 WS gateway (JSON-RPC), an intentionally different architecture than SPEC-051's REST/HTMX.
- ✅ Deprecation is authoritative —
- Remaining work / plan: none. Action = keep the spec retired (already marked). Do not build the SPEC-051 FastAPI/HTMX stack — it was consciously replaced.
- Evidence log: spec header read;
grep VizIntWebUI|htmx|/api/projects src/→ only the empty alias atserver.py:675.
Cluster summary table
| Spec | Class | Effort | Hard deps |
|---|---|---|---|
| SPEC-014 WebSocket Gateway | PARTIAL (HTTP health/metrics gap; JWT-auth divergence) | M (health/metrics); auth-strategy M/L if built | SPEC-032 (kernel readiness), Redis/Neo4j/Prolog, SPEC-011 events |
| SPEC-015 Plugin SDK | PARTIAL / ORPHANED (built, not wired: DI + CLI + RPC) | M | SPEC-000 (CLI), SPEC-014 (RPC), kernel/DI |
| SPEC-016 VizInt Command Center | DONE (confirm) | — | SPEC-014 gateway, pipeline (done, session 193) |
| SPEC-022 TUI | GAP (Design Phase, unimplemented) | L | SPEC-000 (CLI), kernel PipelineRunner, SPEC-023 (approval), Textual dep |
| SPEC-050 CheetahClaws | PARTIAL (checkpoint/40-cmds/live-diff/path-traversal missing; dead route_command) |
M | session CheckpointManager, SPEC-014, SPEC-016, SPEC-028 (models) |
| SPEC-051 VizInt UI | DIVERGENCE (deprecated → SPEC-016) | — | none |
Cross-cluster dependencies noticed
- SPEC-015 plugin CLI ↔ SPEC-000 CLI, and SPEC-022
orchestrata tui↔ SPEC-000 CLI: both need a realorchestrataconsole entry + subcommand hooks on the Click groupkernel/cli_main.py:302(cli). Todaypyproject.toml [project.scripts]has noorchestrataentry, and the group exposes onlystart/version/health. Sequencing: land the SPEC-000 console entry + subcommand pattern first; then 015 and 022 hang off it. - SPEC-014 gateway ↔ SPEC-032 concierge/pipeline: the gateway
/readyprobe (015 remaining work) must report kernel/pipeline readiness — the same live volk↔pipeline path resolved in sessions 165/193. - SPEC-015 plugins ↔ SPEC-014 gateway:
plugins.listRPC (US-007) is a gateway handler addition. - SPEC-016 & SPEC-050 ↔ pipeline: the VizInt orchestrator gadget and the CC
tui.*bridge both consumeorchestrator.intent/PipelineRunner— any pipeline contract change ripples to both UIs. - SPEC-050 ↔ session subsystem: checkpoint wiring reuses
session/checkpoint.py CheckpointManager(session cluster) rather than building new. - SPEC-050 FR-008 ↔ SPEC-028: model switching is profile-based per the SPEC-028 "profiles-only" decision — reconcile the SPEC-050 per-agent-model text there, don't add env/per-agent overrides.