Skip to content

Session B brief — Cockpit command & session UI (FLT-16)

Branch wt/WT-0026/FLT-16-command-ui off master 0ebe335. Worktree isolation: build/test here only.

Goal

The cockpit can currently only WATCH the fleet. Make it ISSUE commands and MANAGE sessions — the whole point of the harness (launch agent runs, watch them live, cancel, see needs-human).

What's ALREADY LANDED on master (build on it, don't rebuild)

  • POST /api/agent-runs (bearer-authed): validates + signs a run_agent job + FILE-QUEUE enqueues to the target PC's inbox. Body = {target, run:{agent, task, repo, ticket, branch?, mode?, timeoutSec?}}. Returns 202 {jobId, target, agent, ticket, acceptedAt}. Proven live. Transport is FILE QUEUE, not HTTP-to-peer (council REJECT'd the HTTP design — SSRF/bearer theft; see AgentRunDispatcher.cs).
  • SignalR return path: FleetHub pushes RunUpdated (status dispatched->…->completed/failed, carries NeedsHumanReview), WorkerHeartbeat, GovernorTier, QuotaUpdated. Frontend fleet-live.service.ts already subscribes to all 4. POST /agent-runs pushes an INSTANT RunUpdated{status:"dispatched"} at accept time.
  • Targets are COMPUTERNAMEs from FleetTargets (ANDREWBEDROOMTV, ANDYGREATROOMPC, DESKTOP-D249KD4, DESKTOP-SCDT9HI), NOT nicknames.

Build

  1. NSwag: regenerate the TS client so it has the LaunchAgentRun write method (GET-only today).
  2. Command UI: a "launch run" form (agent select claude|codex|gemini|grok, repo, ticket, task, target PC), POST it, show the accepted run immediately (the instant RunUpdated).
  3. Live run list fed by RunUpdated — status transitions in place.
  4. Cancel a run (needs a backend cancel path — see Backend gaps).
  5. Kerr gate (MANDATORY): the needs-human state (rate_limited / approval_required / NeedsHumanReview) must NEVER be hidden behind a tab or collapsed pane. It is the one thing the operator must not miss. If you add tabs, needs-human surfaces above them.

Backend gaps you may need to close (in this repo)

  • Cancel: no cancel endpoint yet. Add POST /api/agent-runs/{jobId}/cancel that enqueues a cancel/kill job to the target (fleet-dispatch has process-tree kill in AgentRun). Bearer-authed.
  • Session management: "sessions" = tracking in-flight + recent runs per PC. GET /api/runs exists; a per-target grouping / active-vs-history view may need a small read addition.

THE AUTH CONSTRAINT — read [[fmc-cockpit-signing-oracle]] memory FIRST

The write bearer == SHA256(fleet key). It MUST NOT ship to the browser (devtools/localStorage/XSS = full fleet RCE). The Angular app cannot hold the raw bearer. Options: a local broker the cockpit talks to, or a short-lived per-session token minted server-side. Design this before wiring the POST from Angular. Do NOT put the fleet key in frontend config.

Guardrails

C#-first backend, Angular frontend. /council-code-review before every commit+push (security: this adds a command-issuing UI). Verify by artifact (live run over the hub, not just tests). 100% mocked tests + the frontend resilience pattern. Do NOT deploy VSIXs (that's done separately).