|
10 | 10 | reconcile-loop half of ADR-4 is a sibling that can build on this. |
11 | 11 | - **Builds on:** [ADR-1](./agent-lifecycle.md) (6-state vocabulary), |
12 | 12 | [ADR-2](./deployment-control-plane.md) (read/write model + MCP surface). |
| 13 | +- **Consolidates:** the earlier *push-notifications* draft — its skin↔core |
| 14 | + subscription phasing, the poll-as-reconciliation-backstop invariant, and the |
| 15 | + user-facing-notification consumer fold into §2.4 here (single event canon). |
13 | 16 |
|
14 | 17 | > In the context of front-ends and agents needing to **know when an Instance |
15 | 18 | > changes** (a task dies, a service goes impaired, a probe fails), facing the |
@@ -112,6 +115,30 @@ sources ──AgentEvent──▶ EventHub ──▶ pull: deploy_events(list) |
112 | 115 | - The **webhook** sink is the *only* path that reaches an operator while **no |
113 | 116 | MCP client is connected** (see §5). |
114 | 117 |
|
| 118 | +### 2.4 Delivery, phasing & the reconciliation backstop |
| 119 | +(Folds the *push-notifications* draft into this ADR.) |
| 120 | + |
| 121 | +- **Skin ↔ core, Phase 1 (client wiring).** Today the desktop `McpClient` reader |
| 122 | + correlates replies **by `id` only**; unsolicited `notifications/resources/updated` |
| 123 | + land inertly in the MCP pane. Phase 1 makes the reader **act on id-less |
| 124 | + notifications** — forward `resources/updated` to the frontend as an event — and |
| 125 | + **removes the skin's 5 s `deploy_list` poll**. The roster becomes an MCP |
| 126 | + resource (`oab://deployments/{cluster}`, ADR-2 shape) the skin |
| 127 | + `resources/subscribe`s. |
| 128 | +- **Poll is the reconciliation backstop, not the primary path.** Push delivery is |
| 129 | + **best-effort**; a low-frequency full resync (on subscribe/reconnect + every N |
| 130 | + minutes) repairs missed or out-of-order events so state never silently drifts. |
| 131 | + In Phase 1 the core MAY still poll AWS internally; once `EcsEventSource::subscribe` |
| 132 | + (§3) lands, steady-state ECS polling drops to ~zero and the resync stays only as |
| 133 | + the backstop. |
| 134 | +- **User-facing notifications are a downstream consumer**, not a bespoke channel: |
| 135 | + OS/desktop alerts ("tell me when orca goes `Unhealthy`") subscribe to the same |
| 136 | + `EventHub` stream that drives the roster; the §2.3 webhook sink covers the |
| 137 | + no-client-connected case. **Caveat (from §1):** on ECS the `RUNNING`→unhealthy |
| 138 | + flip is *not* event-emitted, so that specific alert rides the reconcile/probe |
| 139 | + path, not the stream — the abstraction must not promise every transition is |
| 140 | + push-observable on every platform. |
| 141 | + |
115 | 142 | ## 3. Scope (now) |
116 | 143 |
|
117 | 144 | - **ECS adapter first** (per ADR-2 §10 "ECS driver first"): wire |
|
0 commit comments