ADR 0117: Remote operator surface - multi-device operator (remote control, not mobile IDE)¶
Status: Proposed
Date: 2026-05-16
Updated: 2026-05-16 - remote surface client: PWA (canonical choice).
Related ADRs¶
| ADR | Role |
|---|---|
| 0017 | Multi-window on one station (not remote) |
| 0108 | Web in MFD → IdeCommands (orthogonal) |
| 0035 | Web Trust Boundary ↔ MCP |
| 0016 | External ACP Agent |
| 0031 | Clarifications Intercom vs PFD |
| 0030 | command_id, confirmations |
| 0008 | IdeCommands, MCP |
| 0043 | Transport restoration |
| 0099 | IDE Events → Projections |
| 0045 | Chat/event history |
Summary¶
- Remote operator: PWA remote control from a phone/other PC, Operator Gateway.
- Not mobile IDE; complements multi-window (0017).
- Communication with the web-portal bridge (0108).
Outside the repo: vision agent-forge (worst case scenario, API + browser) - personal canon agent-notes.
1. Context¶
Powers:
- The operator (person) works not only at one desktop: a second PC, tablet, phone - for monitoring, replying to the agent, confirmations, changing the WORK/HUMAN mode, without transferring the full IDE.
- ADR 0017 solves multi-monitor on one station (
MainWindow,MfdHostWindow,presentationpresets). This is not a “left the office - continued from the phone” session. - ADR 0108 gives built-in web in MFD with a bridge to IDE for external web model. This is not an operator console from another device and is not a replacement for native Intercom.
- Line Friction / environment-first: convenience is measured by worst path (weak network, browser only, first time). If it is impossible to see the status and make a decision there, and heavy task closure is possible only behind the desktop, this is acceptable only if the desktop is clearly in the loop; otherwise the operator on the second device is “second class”.
Problem: without an explicit architecture it is easy to fall into (a) mobile IDE - unrealistic Roslyn/debugging parity; (b) naked chat without connection to the IDE session; (c) unsecure open port without pairing.
2. Decision (intention)¶
2.1. Three circuits (separation of responsibilities)¶
| Contour | Where | Destination |
|---|---|---|
| Heavy (cockpit) | CascadeIDE on workstation | editor, Roslyn, build, debugging, full HUD, MCP in progress |
| Lightweight (remote operator surface) | PWA on another device (phone, tablet, second PC) | session status, Intercom (limited), approve/reject, pause/stop, “agent is waiting” notifications |
| Machine | git, MCP remote, CI, Issues | closing a task without UI; agent and automation |
Principle: remote surface does not duplicate the cockpit. He observes and decides; execution of heavy tasks - on a station with IDE or through existing MCP / IdeCommands (with a policy on the gateway).
2.2. Remote operator surface (ROS) - scope v1¶
Included (target phase 1-2):
- Subscription to snapshot of session: workspace id, active Intercom topic/thread (briefly), “waiting for person” flag, last N agent messages, IDE health / failed step (without leaking the full workspace tree).
- Operator actions with explicit confirmation on the desktop in case of risk: response to chat (follow-up), approve/reject for “human only” zones (0030, pre-flight — 0042 when it appears).
- Push / pull notifications: “agent is blocked on a question” (integration with an external channel - Telegram, email - outside the ADR core, via an adapter).
- Pairing of a remote client with an IDE instance (one-time code, TTL, recall).
Not included in v1:
- Full-fledged code editor in the browser.
- Randomly call all IdeCommands from the phone without allowlist.
- Public cloud relay without E2E / without being tied to a pair of devices.
- Native companion applications (iOS/Android/desktop) - postponed; if necessary later as a wrapper over the same API gateway.
2.2.1. Client: PWA (canon)¶
Solution: remote operator surface is implemented as a Progressive Web App, not as separate native applications and not as “just a tab without install”.
Why PWA:
| Criterion | PWA |
|---|---|
| One artifact | phone, tablet, second PC - one UI (HTML/CSS/TS), no store releases |
| Friction / worst way | “opened in browser → Add to Home Screen” without installing CIDE |
| Transport | the same Operator Gateway (SSE/WebSocket + REST); PWA - client only |
| Notifications (Phase 3) | Web Push + service worker with explicit consent; fallback - pull/SSE |
| Offline | service worker: UI shell cache + latest snapshot; commands when offline - queue or failure (see §7) |
| Security | console origin = origin gateway (loopback or VPN); do not mix with 0108 |
Delivery: static PWA is distributed from the same host as the Operator Gateway (for example Features/OperatorGateway/www/ or embedded wwwroot), so as not to produce CORS and a second port unnecessarily. After pairing, the user saves the “Cascade Operator” shortcut.
Minimum UX v1: one “session” page (status + feed + response field); mobile-first layout; without complicated cockpit navigation.
2.3. Transport and border (Operator Gateway)¶
Between CascadeIDE (host) and remote client there is a logical Operator Gateway (process or built-in module):
- Outgoing Events - subset of 0099 / projections (0045): serialized DTO, no secrets and no full paths to
.env/ai-keys.toml. - Incoming commands - narrow allowlist (
operator.reply,operator.approve,operator.reject,operator.pause_agent, ...), mapping to existing IDE loops (Intercom, PFD confirmations), not direct arbitraryide_execute_commandfrom the Internet. - Transport: preferably WebSocket or SSE + REST on
localhostwith TLS and reverse proxy only when explicitly configured; default - loopback + pairing token. - Recovery parity - in spirit 0043: when the remote client breaks, it shows “session unavailable”, does not simulate success.
Connection with 0108: Web AI Portal - foreign origin in WebView2; ROS-PWA - our own origin gateway, separate allowlist. Do not mix portal and remote control.
2.4. Difference from multi-window 0017¶
| ADR 0017 | ADR 0117 | |
|---|---|---|
| Devices | one PC, N monitors | N devices, 1 “heavy” station |
| UI | Avalonia TopLevel |
PWA (canon) |
| Synchronization | shared process, shared DataContext |
network/loopback gateway |
| Criterion | cockpit layout | surveillance + solutions outside the cockpit |
Both can work simultaneously (second monitor + phone as a remote control).
2.5. Friction criterion (negative scenario)¶
We consider ROS successful for scenario S:
- The operator has moved away from the workstation; The remote control (or PWA) is open on the phone.
- The agent in the IDE has requested clarification or confirmation.
- The operator sees the request within a reasonable TTL and can answer or reject without installing full CIDE on the phone.
- Agent continues on desktop; in the audit log there is a combination of
operator_device_id+ action.
If only “open laptop with IDE” is available for S, ROS hasn’t removed the friction for this class of tasks.
3. Phases (road map)¶
| Phase | Contents | Readiness criterion |
|---|---|---|
| 0 | This ADR; list of DTOs and allowlists in a drawing | Borders agreed with 0017/0108/0031 |
| 1 | Read-only: gateway + PWA (manifest, service worker shell); snapshot + SSE | PWA on loopback: status and “waiting for operator” |
| 2 | Write + pairing; installable PWA on phone on LAN | Scenario S passes |
| 3 | Web Push / adapters; optional TLS + VPN to gateway | Operator outside LAN with secure channel |
| MVP-zero (outside CIDE code): async via Issues / org Discussions / Telegram-relay MCP - doesn't replace ROS, acceptable as a temporary workaround. |
4. Security and trust¶
- Secrets are not transferred to the remote client;
ai-keys.tomland MCP tokens remain on the IDE station. - Pairing: short-lived code; list of recalled devices; by default gateway listens to 127.0.0.1.
- Allowlist of commands on gateway - separate from 0108 and from the full MCP.
- Audit: each remote action is logged with
principal=human,channel=remote_operator,device_id. - Do not expose the gateway to the Internet without an explicit org policy (VPN, mTLS).
5. Alternatives (rejected or postponed)¶
| Alternative | Why not the target path |
|---|---|
| Full web IDE | Roslyn/debugging parity; huge friction; duplicates cockpit |
| RDP/VNC on desktop only | Works, but not mobile-friendly; does not reduce friction scenario S |
| Public MCP endpoint without layers | Risk of workspace leakage; see backlog remote MCP in agent-notes |
| Single chatbot without IDE connection | There is no session truth; hallucination “I did” |
| Native companion (v1) | Two support circuits; PWA closes scenario S; native - if proven necessary |
6. Consequences¶
- A new feature slice will appear (for example
Features/OperatorGateway/): host service, DTO, allowlist, PWA statics (manifest.webmanifest, service worker, UI). - Requires contract tests snapshot for wire-DTO (0008, 0052).
- Intercom / 0031 / 0042: approve remote must converge with the same state machines as PFD/MFD on the desktop - not a second parallel “source of truth”.
- Operator documentation: separate page in handbook/kb-public after phase 1 (not in this ADR).
7. Open questions¶
- Built-in gateway vs separate process
cascade-operator-gateway(easier to update, harder to deploy)? - One workspace - several remote clients (family of devices) or one active remote control?
- Communication with ACP 0016: Does the remote surface control only the built-in IDE agent or also the external ACP?
- Offline: command queue on the client vs hard failure?
- Intersection with 0034 (emergency / presence) - is it a general notification channel or a separate one?
- Web Push: VAPID and delivery via gateway vs only external adapter (Telegram) in phase 2?
8. Implementation status¶
| Region | State |
|---|---|
| ADR/borders | this document |
| Operator Gateway in code | no |
| PWA (manifest + SW + UI) | no |
| Pairing | no |
| DataBus/Intercom integration | no |
When the code appears, update §8 and the ADR status to Accepted · Implemented (by status-lifecycle.md).