2026 03 04 Observatory Redesign

Documentation for Plans

Observatory Redesign — Unified Vitto Super-Agent Monitoring

Session: 176.3 Date: 2026-03-04 Status: Approved design, pending implementation

Vision

Vitto is the super-agent that orchestrates, monitors, and governs all AI activity. The Observatory is Vitto's eyes — the unified surface where humans see what Vitto sees. Every piece of monitoring data queryable by Vitto through MCP has a corresponding visualization in the Observatory.

Current State

Two separate observatory surfaces exist:

Both are functional with real backend integrations. The split happened historically: /observatory was built when monitoring was a platform concern; /vitto/observatory was built when Vitto became a standalone product. Now that Vitto IS the platform's AI layer, they should be one surface.

Architecture Decision

Vitto's Observatory becomes THE canonical observatory.

Tab Structure

/vitto/observatory (OR /observatory)
├── Operations (all roles)
│   ├── agents      → AgentObservatoryComponent (enhanced)
│   ├── system      → ObservatoryDashboardComponent (enhanced)
│   └── sandbox     → SandboxTabComponent (fixed)
├── Governance (all roles)
│   ├── approvals   → ObservatoryApprovalsComponent (fixed)
│   ├── audit       → ObservatoryAuditComponent
│   └── trust       → TrustDashboardComponent
└── Intelligence (developer/admin only)
    ├── costs       → CostDashboardComponent
    ├── failures    → FailureChainsComponent (fixed)
    └── specialization → SpecializationMatrixComponent (fixed)

Backend Responsibilities (Unchanged)

Backend Port Observatory Role
backend-ai-api 3001 Data platform: health checks, LLM costs, sandbox mgmt, agent specialization, MCP data
backend-vitto-api 3003 Orchestrator: tasks, mind, trust, security audit, skills, task costs, smart routing

The frontend abstracts this split — observatory services talk to both backends and present a unified view.

Implementation Plan

Part 1: Unified Surface (Route Consolidation)

Goal: Both /observatory and /vitto/observatory render the same shell with all 9 tabs.

Changes:

  1. Enhance ObservatoryPanelComponent to accept all 9 child routes grouped into Operations / Governance / Intelligence
  2. Add agents, system, sandbox as new child routes under /vitto/observatory
  3. Update /observatory in apps/gograb-ai to render ObservatoryPanelComponent with the same child route config
  4. Update Chrome extension sidepanel iframe URL
  5. Role-based tab visibility: Intelligence group hidden for non-developer roles

Files:

Part 2: Bug Fixes (11 confirmed issues)

# Issue File Fix
1 Server infrastructure hardcoded in template sandbox-tab.component.html:80-105, observatory.controller.ts, .env.local Backend sandbox-providers returns serverInfo from env vars (SANDBOX_SERVER_LABEL, SANDBOX_SERVER_HARDWARE). Template reads from signal.
2 setInterval violates async rules observatory-approvals.component.ts:77 Replace with timer(0, 30_000).pipe(takeUntilDestroyed(this.destroyRef))
3 VittoMonitorService singleton race condition vitto-monitor.service.ts Reference-counting: _connectCount incremented on connect, decremented on disconnect. SSE only closes when count reaches 0.
4 Dead vittoApiUrl injection sandbox-tab.component.ts:26 Remove unused injection
5 getModelEntries() template method observatory-dashboard.component.ts:75 Convert to computed() signal
6 Legacy *ngIf/*ngFor syntax observatory-dashboard.component.html Convert to @if/@for control flow
7 (res as any) untyped responses All 6 vitto hub observatory tabs Create proper DTOs in vitto.types.ts, type the VittoApiService methods
8 Non-functional taskTypeFilter failure-chains.component.html Add <input> bound to taskTypeFilter signal with debounce
9 any[] typing specialization-matrix.component.ts:40 Type as SharedPattern[]
10 destroySession() no error handling sandbox-tab.component.ts Add error toast, loading state, optimistic removal + refresh on success
11 Non-joined HTTP calls specialization-matrix.component.ts Join with forkJoin for single loading cycle

Part 3: Wire Unwired Code

Goal: Every component built by a previous session gets wired to its intended home.

Component Intent Wire To
GoGrabObservatoryComponent (embeddable-bridge) Session 104.2: Embed observatory in any host app Import into gograb-space admin layout. Shows observatory for space admins without navigating away.
createObservatoryPlugin (vitto-chat) Session 149: Observatory tab in unified chat Add to createStandardPluginSet in plugin-presets.ts for T0+T1 tiers. Pass AgentObservatoryComponent.
VittoMonitorComponent unique features Session 103: Original monitor had model/provider in history + phase token counts Merge both into AgentObservatoryComponent template. Mark VittoMonitorComponent as @deprecated.
recentDecisions signal OrchestrationClientService: agent decisions feed New "Agent Decisions" card in AgentObservatoryComponent full mode
loadedContext signal OrchestrationClientService: context loading indicator New "Context Loaded" section in full mode
patternMatches signal OrchestrationClientService: pattern matching feed New "Pattern Matches" feed in full mode
learningStats signal OrchestrationClientService: learning system health New "Learning System" status card in full mode

Part 4: LLM Cost Persistence (MongoDB)

Goal: LLM costs survive server restarts. Historical trends available.

Backend changes (backend-ai-api):

New Mongoose schema:

@Schema({ collection: 'llm-usage', timestamps: true })
export class LlmUsageDocument {
  @Prop() model: string;
  @Prop() tokensIn: number;
  @Prop() tokensOut: number;
  @Prop() estimatedCostUsd: number;
  @Prop() userId: string;
  @Prop() sessionId?: string;
  @Prop() timestamp: Date;
}

TTL index: auto-expire after 90 days (configurable).

LlmCostTrackerService.recordUsage():

New endpoints:

Frontend changes:

Part 5: Unified Alert Pipeline

Goal: All alert sources flow through one service, persist to MongoDB, push to frontend in real-time.

Backend (backend-ai-api):

New AlertAggregatorService:

@Injectable()
export class AlertAggregatorService implements OnModuleInit {
  // Subscribes to:
  // - PipelineMetricsService events (pipeline.alert, pipeline.unhealthy, pipeline.degraded)
  // - ConditionMonitorService events (monitor.alert, monitor.recovered)
  // - ObservatoryService health results (backend down/degraded)
  // - Vitto proactive alerts (forwarded from vitto-api)

  // Persists to 'alerts' collection (deduplication by message hash + 1h window)
  // Emits to WebSocket for real-time frontend push
  // Exposes via REST for polling fallback
}

Mongoose schema:

@Schema({ collection: 'alerts', timestamps: true })
export class AlertDocument {
  @Prop() severity: 'critical' | 'warning' | 'info';
  @Prop() source: string; // 'pipeline' | 'condition-monitor' | 'health-check' | 'vitto-proactive'
  @Prop() check: string;  // e.g., 'api-health', 'build-health', 'dependency-audit'
  @Prop() message: string;
  @Prop() details?: string;
  @Prop() resolved: boolean;
  @Prop() resolvedAt?: Date;
  @Prop() firstSeenAt: Date;
  @Prop() lastSeenAt: Date;
  @Prop() occurrenceCount: number;
}

TTL index: auto-expire resolved alerts after 30 days.

New endpoint:

Frontend:

Part 6: MCP Convergence — Vitto Self-Monitoring

Goal: Every observatory visualization maps to an MCP tool. Vitto can self-diagnose.

New MCP actions (in MCP/mcp-gograb-ai/):

  1. stats({ action: "alerts" }) — returns active unresolved alerts

    • Calls GET /infrastructure/observatory/alerts?resolved=false
    • Vitto uses this to self-diagnose when backends are degraded
  2. stats({ action: "costs", days: 7 }) — returns cost breakdown by model/user

    • Calls GET /infrastructure/observatory/llm-history?days=7
    • Vitto can monitor spend and warn proactively
  3. intelligence({ action: "trust", actionType: "deploy::execute" }) — returns trust score

    • Calls GET /engine/trust-scores on vitto-api
    • Vitto checks its own trust before attempting risky actions

Existing MCP tool ↔ Observatory mapping:

MCP Tool Observatory Tab Status
preflight (health check) System tab Exists
stats.enhanced (system stats) System tab Exists
intelligence.specializations Specialization tab Exists
intelligence.calibrate Trust tab Exists
intelligence.recall Failure Chains tab Partial match
agent.handoff_pending Approvals tab Exists
stats.alerts System tab (new Alerts section) New
stats.costs System tab (cost charts) New
intelligence.trust Trust tab New

Vitto self-monitoring flow:

Part 7: Wire Key Unused Backend Endpoints

Goal: 8 existing VittoApiService methods with high value get wired to observatory tabs.

# Method Wire To User Value
1 estimateCost(params) Costs tab — pre-flight cost prediction "This task will cost ~$X" before execution
2 getMcpUsageHistory() Costs > AI Infrastructure — usage trend Daily/weekly MCP usage chart
3 getRoutingDecisions() Costs > Routing — decision audit Why SmartRouter chose each provider
4 getComplianceReport(start, end) Audit tab — date-range report Structured compliance view
5 getAuditTrail(params) Audit tab — extended with pagination Replaces 50-entry limit with scrollable history
6 Mind health endpoints System tab — new "AI Health" section Memory health, consolidation, stale count
7 getThoughtTrace(taskId) Agent Monitor — expandable per task Vitto's reasoning chain visualization
8 getMemoryInsights(userId) Intelligence — insight card AI-generated summary of learned knowledge

Data Flow

                    ┌─────────────────────────────────────────┐
                    │          Observatory UI (Angular)        │
                    │                                         │
                    │  ┌─────────────┐  ┌──────────────────┐ │
                    │  │ VittoMonitor│  │ Orchestration     │ │
                    │  │ Service     │  │ ClientService     │ │
                    │  │ (SSE)       │  │ (WebSocket)       │ │
                    │  └──────┬──────┘  └────────┬─────────┘ │
                    │         │                   │           │
                    │  ┌──────┴───────────────────┴─────────┐ │
                    │  │ ObservatoryDataService (REST poll)  │ │
                    │  │ VittoApiService (REST on-demand)    │ │
                    │  └──────┬───────────────────┬─────────┘ │
                    └─────────┼───────────────────┼───────────┘
                              │                   │
                    ┌─────────▼─────────┐ ┌──────▼──────────┐
                    │ backend-ai-api    │ │ backend-vitto-api│
                    │ (port 3001)       │ │ (port 3003)      │
                    │                   │ │                   │
                    │ • Health checks   │ │ • Task engine     │
                    │ • LLM costs (DB)  │ │ • Mind/memories   │
                    │ • Sandbox mgmt    │ │ • Trust scores    │
                    │ • Alerts (DB)     │ │ • Security audit  │
                    │ • Agent specs     │ │ • Task costs      │
                    │ • MCP data        │ │ • Smart routing   │
                    │ • Computer use    │ │ • Skills/personas │
                    │ • Command center  │ │ • A2A protocol    │
                    └───────────────────┘ └──────────────────┘
                              │                   │
                    ┌─────────▼───────────────────▼───────────┐
                    │              MCP Server                  │
                    │ (same data, programmatic access)        │
                    │                                         │
                    │ stats.alerts → backend-ai-api           │
                    │ stats.costs → backend-ai-api            │
                    │ intelligence.trust → backend-vitto-api  │
                    │ preflight → both backends               │
                    └─────────────────────────────────────────┘

Dead Code Resolution

Item Original Intent Resolution
GoGrabObservatoryComponent Session 104.2: embed in host apps Wire to gograb-space layout
createObservatoryPlugin Session 149: chat tab integration Wire to createStandardPluginSet
VittoMonitorComponent Session 103: original monitor Merge unique features, deprecate
OrchestrationClientService 4 signals WS event receivers for decisions/context/patterns/learning Wire to AgentObservatoryComponent full mode

Overlap Resolution

Overlap Location A Location B Resolution
Backend health cards System tab (ObservatoryDashboardComponent) Costs > AI Infrastructure Remove generic health from Costs; keep MCP-specific data (decisions, patterns, circuit breaker). System tab owns health.
Checkpoint approvals Agent Monitor inline Approvals tab dedicated Keep both — different user journeys (real-time ops vs governance review). Same SSE data source, no wasted work.

Files Touched (Estimated)

Modified: ~25 files New: ~5 files (alert service, alert schema, LLM usage schema, new MCP actions, shared DTOs) Deprecated: 1 file (VittoMonitorComponent marked @deprecated)

Success Criteria

  1. Single observatory surface accessible from both /observatory and /vitto/observatory
  2. All 9 tabs render real data from their respective backends
  3. Zero (res as any) patterns — all responses typed
  4. LLM costs persisted to MongoDB with 30-day trend chart
  5. Alerts aggregated, persisted, and visible in System tab
  6. 3 new MCP actions for Vitto self-monitoring
  7. All 4 OrchestrationClientService signals rendered in Agent Monitor (full mode)
  8. All previously unwired components connected to their intended homes
  9. All 11 confirmed bugs fixed
  10. 8 high-value unused backend endpoints wired to observatory tabs