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:
FleetHubpushesRunUpdated(status dispatched->…->completed/failed, carriesNeedsHumanReview),WorkerHeartbeat,GovernorTier,QuotaUpdated. Frontendfleet-live.service.tsalready subscribes to all 4.POST /agent-runspushes an INSTANTRunUpdated{status:"dispatched"}at accept time. - Targets are COMPUTERNAMEs from
FleetTargets(ANDREWBEDROOMTV, ANDYGREATROOMPC, DESKTOP-D249KD4, DESKTOP-SCDT9HI), NOT nicknames.
Build¶
- NSwag: regenerate the TS client so it has the
LaunchAgentRunwrite method (GET-only today). - 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).
- Live run list fed by
RunUpdated— status transitions in place. - Cancel a run (needs a backend cancel path — see Backend gaps).
- 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}/cancelthat 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).