Forge
markdowndeeb25a2
1<!-- English translation of adr/0117-remote-operator-surface-multidevice.md. Canonical Russian: ../../adr/0117-remote-operator-surface-multidevice.md -->
2
3# ADR 0117: Remote operator surface - multi-device operator (remote control, not mobile IDE)
4
5**Status:** Proposed
6**Date:** 2026-05-16
7**Updated:** 2026-05-16 - remote surface client: **PWA** (canonical choice).
8
9## Related ADRs
10
11| ADR | Role |
12|-----|------|
13| [0017](0017-multi-window-workspace-and-agent-surfaces.md) | Multi-window on one station (**not** remote) |
14| [0108](0108-web-ai-portal-host-object-tools-bridge.md) | Web in MFD → `IdeCommands` (orthogonal) |
15| [0035](0035-mfd-embedded-webview-external-llm-and-mcp-boundary.md) | Web Trust Boundary ↔ MCP |
16| [0016](0016-agent-client-protocol-external-agent.md) | External ACP Agent |
17| [0031](0031-agent-chat-clarification-batches-and-threading.md) | Clarifications Intercom vs PFD |
18| [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md) | `command_id`, confirmations |
19| [0008](0008-mcp-contracts-and-testable-infrastructure.md) | `IdeCommands`, MCP |
20| [0043](0043-mcp-transport-recovery-human-agent-parity.md) | Transport restoration |
21| [0099](0099-ide-databus-typed-events-and-projections.md) | IDE Events → Projections |
22| [0045](0045-agent-chat-persistence-event-log-and-projections.md) | Chat/event history |
23
24## Summary
25
26- **Remote operator:** PWA remote control from a phone/other PC, Operator Gateway.
27- Not mobile IDE; complements multi-window ([0017](0017-multi-window-workspace-and-agent-surfaces.md)).
28- Communication with the web-portal bridge ([0108](0108-web-ai-portal-host-object-tools-bridge.md)).
29
30**Outside the repo:** vision **agent-forge** (worst case scenario, API + browser) - personal canon `agent-notes`.
31
32---
33
34## 1. Context
35
36**Powers:**
37
38- 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.
39- **[ADR 0017](0017-multi-window-workspace-and-agent-surfaces.md)** solves **multi-monitor on one station** (`MainWindow`, `MfdHostWindow`, `presentation` presets). This is **not** a “left the office - continued from the phone” session.
40- **[ADR 0108](0108-web-ai-portal-host-object-tools-bridge.md)** 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.
41- 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”.
42
43**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.
44
45---
46
47## 2. Decision (intention)
48
49### 2.1. Three circuits (separation of responsibilities)
50
51| Contour | Where | Destination |
52|--------|-----|-----------|
53| **Heavy (cockpit)** | CascadeIDE on workstation | editor, Roslyn, build, debugging, full HUD, MCP in progress |
54| **Lightweight (remote operator surface)** | **PWA** on another device (phone, tablet, second PC) | session status, Intercom (limited), approve/reject, pause/stop, “agent is waiting” notifications |
55| **Machine** | git, MCP remote, CI, Issues | closing a task without UI; agent and automation |
56
57**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).
58
59### 2.2. Remote operator surface (ROS) - scope v1
60
61**Included (target phase 1-2):**
62
63- 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).
64- Operator actions with **explicit confirmation** on the desktop in case of risk: response to chat (follow-up), approve/reject for “human only” zones ([0030](0030-command-ids-hotkeys-and-ui-registry-layers.md), pre-flight — [0042](0042-pre-flight-planned-changes-and-review-before-apply.md) when it appears).
65- **Push / pull notifications:** “agent is blocked on a question” (integration with an external channel - Telegram, email - **outside** the ADR core, via an adapter).
66- **Pairing** of a remote client with an IDE instance (one-time code, TTL, recall).
67
68**Not included in v1:**
69- Full-fledged code editor in the browser.
70- Randomly call all `IdeCommands` from the phone without allowlist.
71- Public cloud relay without E2E / without being tied to a pair of devices.
72- **Native** companion applications (iOS/Android/desktop) - postponed; if necessary later as a wrapper over the same API gateway.
73
74### 2.2.1. Client: PWA (canon)
75
76**Solution:** remote operator surface is implemented as a **Progressive Web App**, not as separate native applications and not as “just a tab without install”.
77
78**Why PWA:**
79
80| Criterion | PWA |
81|----------|-----|
82| One artifact | phone, tablet, second PC - one UI (HTML/CSS/TS), no store releases |
83| Friction / worst way | “opened in browser → Add to Home Screen” without installing CIDE |
84| Transport | the same **Operator Gateway** (SSE/WebSocket + REST); PWA - client only |
85| Notifications (Phase 3) | **Web Push** + service worker with explicit consent; fallback - pull/SSE |
86| Offline | service worker: UI shell cache + latest snapshot; **commands** when offline - queue or failure (see §7) |
87| Security | console origin = origin gateway (loopback or VPN); **do not** mix with [0108](0108-web-ai-portal-host-object-tools-bridge.md) |
88
89**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.
90
91**Minimum UX v1:** one “session” page (status + feed + response field); mobile-first layout; without complicated cockpit navigation.
92
93### 2.3. Transport and border (Operator Gateway)
94
95Between **CascadeIDE (host)** and **remote client** there is a logical **Operator Gateway** (process or built-in module):
96
971. **Outgoing Events** - subset of [0099](0099-ide-databus-typed-events-and-projections.md) / projections ([0045](0045-agent-chat-persistence-event-log-and-projections.md)): serialized DTO, no secrets and no full paths to `.env` / `ai-keys.toml`.
982. **Incoming commands** - narrow allowlist (`operator.reply`, `operator.approve`, `operator.reject`, `operator.pause_agent`, ...), mapping to existing IDE loops (Intercom, PFD confirmations), **not** direct arbitrary `ide_execute_command` from the Internet.
993. **Transport:** preferably **WebSocket or SSE + REST** on `localhost` with **TLS** and reverse proxy only when explicitly configured; default - **loopback** + pairing token.
1004. **Recovery parity** - in spirit [0043](0043-mcp-transport-recovery-human-agent-parity.md): when the remote client breaks, it shows “session unavailable”, does not simulate success.
101
102**Connection with [0108](0108-web-ai-portal-host-object-tools-bridge.md):** Web AI Portal - **foreign origin** in WebView2; ROS-PWA - **our own** origin gateway, separate allowlist. Do not mix portal and remote control.
103
104### 2.4. Difference from multi-window [0017](0017-multi-window-workspace-and-agent-surfaces.md)
105
106| | ADR 0017 | ADR 0117 |
107|---|----------|----------|
108| Devices | one PC, N monitors | N devices, 1 “heavy” station |
109| UI | Avalonia `TopLevel` | **PWA** (canon) |
110| Synchronization | shared process, shared `DataContext` | network/loopback gateway |
111| Criterion | cockpit layout | surveillance + solutions outside the cockpit |
112
113Both can work **simultaneously** (second monitor + phone as a remote control).
114
115### 2.5. Friction criterion (negative scenario)
116
117We consider ROS successful for scenario **S**:
118
1191. The operator has moved away from the workstation; The remote control (or PWA) is open on the phone.
1202. The agent in the IDE has requested clarification or confirmation.
1213. The operator **sees** the request within a reasonable TTL and can **answer** or **reject** without installing full CIDE on the phone.
1224. Agent **continues** on desktop; in the audit log there is a combination of `operator_device_id` + action.
123
124If only “open laptop with IDE” is available for S, ROS **hasn’t** removed the friction for this class of tasks.
125
126---
127
128## 3. Phases (road map)
129
130| Phase | Contents | Readiness criterion |
131|------|-----------|---------------------|
132| **0** | This ADR; list of DTOs and allowlists in a drawing | Borders agreed with 0017/0108/0031 |
133| **1** | Read-only: gateway + **PWA** (manifest, service worker shell); snapshot + SSE | PWA on loopback: status and “waiting for operator” |
134| **2** | Write + pairing; installable PWA on phone on LAN | Scenario S passes |
135| **3** | Web Push / adapters; optional TLS + VPN to gateway | Operator outside LAN with secure channel |
136**MVP-zero (outside CIDE code):** async via Issues / org Discussions / Telegram-relay MCP - **doesn't** replace ROS, acceptable as a temporary workaround.
137
138---
139
140## 4. Security and trust
141
142- **Secrets** are not transferred to the remote client; `ai-keys.toml` and MCP tokens remain on the IDE station.
143- **Pairing:** short-lived code; list of recalled devices; by default gateway listens to **127.0.0.1**.
144- **Allowlist of commands** on gateway - separate from [0108](0108-web-ai-portal-host-object-tools-bridge.md) and from the full MCP.
145- **Audit:** each remote action is logged with `principal=human`, `channel=remote_operator`, `device_id`.
146- **Do not** expose the gateway to the Internet without an explicit org policy (VPN, mTLS).
147
148---
149
150## 5. Alternatives (rejected or postponed)
151
152| Alternative | Why not the target path |
153|--------------|-----------------------|
154| **Full web IDE** | Roslyn/debugging parity; huge friction; duplicates cockpit |
155| **RDP/VNC on desktop only** | Works, but not mobile-friendly; does not reduce friction scenario S |
156| **Public MCP endpoint** without layers | Risk of workspace leakage; see backlog remote MCP in agent-notes |
157| **Single chatbot without IDE connection** | There is no session truth; hallucination “I did” |
158| **Native companion (v1)** | Two support circuits; PWA closes scenario S; native - if proven necessary |
159
160---
161
162## 6. Consequences
163
164- A new **feature slice** will appear (for example `Features/OperatorGateway/`): host service, DTO, allowlist, **PWA statics** (`manifest.webmanifest`, service worker, UI).
165- Requires **contract tests** snapshot for wire-DTO ([0008](0008-mcp-contracts-and-testable-infrastructure.md), [0052](0052-agent-contract-cli-and-snapshot-tests.md)).
166- **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”.
167- Operator documentation: separate page in handbook/kb-public **after** phase 1 (not in this ADR).
168
169---
170
171## 7. Open questions
172
1731. **Built-in gateway** vs separate process `cascade-operator-gateway` (easier to update, harder to deploy)?
1742. **One workspace - several remote clients** (family of devices) or one active remote control?
1753. **Communication with ACP [0016](0016-agent-client-protocol-external-agent.md):** Does the remote surface control only the built-in IDE agent or also the external ACP?
1764. **Offline:** command queue on the client vs hard failure?
1775. Intersection with **[0034](0034-pilot-incapacitation-emergency-mode-and-presence-sensing.md)** (emergency / presence) - is it a general notification channel or a separate one?
1786. **Web Push:** VAPID and delivery via gateway vs only external adapter (Telegram) in phase 2?
179
180---
181
182## 8. Implementation status
183
184| Region | State |
185|---------|-----------|
186| ADR/borders | this document |
187| Operator Gateway in code | no |
188| PWA (manifest + SW + UI) | no |
189| Pairing | no |
190| DataBus/Intercom integration | no |
191
192When the code appears, update §8 and the ADR status to **Accepted · Implemented** (by [status-lifecycle.md](status-lifecycle.md)).
View only · write via MCP/CIDE