Skip to content

Commit d6fab0d

Browse files
committed
docs(rollout): record attended compatibility, run against a live unattended session
Run as coexistence rather than the minimum: an unattended session kept hosting a controlled tab while the operator attached an attended session to their own. "Reports only that tab" means nothing unless there is another controlled tab in the profile to not report. The protocol-2 criterion has a neat direct test worth reusing. Sending a write with NO understudy-command-contract header turns SAFE_WRITE_REQUIRED_TENANTS into a live probe of what the EXTENSION negotiated — supplying the header would satisfy the v2 branch whatever the extension is, so omitting it is the only caller-side way to tell. The write was accepted, so the extension is v2. Also records that Detach tab leaves the session reading "connected" while every command answers "no active CDP session". detached is set only when the socket closes; detaching the debugger tells the backend nothing, and the enum has no state for socket-up-nothing-attached. Logged as an observation, not a defect — it is an explicit per-command error, not a false success — for the owner to rule on.
1 parent 17421a3 commit d6fab0d

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

‎docs/unattended-production-rollout.md‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -919,7 +919,32 @@ Two operational notes:
919919
- **`wrangler secret put` is not immediately visible.** A freshly added digest answered `401` for roughly eight seconds before answering `400`. Checking straight after the put yields a false negative; poll until it flips.
920920
- **Keep the canonical credential file canonical.** `~/.understudy-canary/device-credential.json` now holds the live v2 credential; the superseded one is `device-credential-v1-REVOKED.json`. Leaving a dead credential under the name every runbook step references is a trap for the next re-enrolment, which — see the enrolment-loss entry above — may be needed without warning.
921921

922-
Still outstanding, each needing an operator at the browser or elapsed time: hard and idle expiry, attended compatibility. Two visual confirmations also remain — that cleanup closed exactly one tab, and that no stray popup window survived.
922+
#### Attended compatibility PASSED, run concurrently with unattended (2026-07-29)
923+
924+
Run as a **coexistence** test rather than the minimum the scenario describes: an unattended session was left hosting a controlled tab while the operator attached an attended session to a tab of their own. "Reports only that tab" is only meaningful when there is another controlled tab in the same profile for it to fail to report.
925+
926+
| Criterion | Evidence |
927+
|---|---|
928+
| Attaches to the user's own tab | Attended session bound tab `2134210639` (`https://www.google.com/`), operator-opened |
929+
| Reports only that tab | `get_tabs` returned exactly it; the unattended tab `2134210638` was invisible to it |
930+
| **Negotiates protocol 2 after attachment** | A **write sent with no `understudy-command-contract` header** was accepted. With `SAFE_WRITE_REQUIRED_TENANTS` naming this tenant, a protocol-1 extension would have drawn `426` on that exact request. It did not, so the extension negotiated v2 itself rather than the caller's header carrying it |
931+
| Snapshot and an approved action | a11y snapshot returned 25 nodes on the correct `tabId`; `key` write `ok: true` |
932+
| Coexistence | Throughout, the unattended session still reported only tab `2134210638` and device usage held at `1/2` |
933+
| Detach leaves the tab open | Operator-confirmed: the tab survived `Detach tab` |
934+
935+
The protocol-2 check is worth reusing. Sending a write **without** the contract header turns `SAFE_WRITE_REQUIRED_TENANTS` into a live probe of what the *extension* negotiated — the only way to test it from the caller side, since supplying the header would satisfy the v2 branch regardless of the extension.
936+
937+
**Observation — `Detach tab` does not change the reported status.** After detaching, the session still reads `status: "connected"` with `browser` present, while every command answers:
938+
939+
```json
940+
{"type":"action_result","ok":false,"error":"no active CDP session"}
941+
```
942+
943+
`detached` is set only when the WebSocket itself closes, or on an epoch change, device revocation, or terminal close. Detaching the debugger keeps the socket open and reports nothing to the backend, and the attended status enum — `pending | connected | detached` — has no state for "socket up, nothing attached".
944+
945+
Not a silent failure: the consumer gets an explicit per-command error rather than a false success, and Metamind's flow surfaces it. But a consumer that gates on status alone would see `connected` and be wrong. Recorded as an observation, not a defect — the status plausibly tracks the socket by design — and left for the owner to decide.
946+
947+
Still outstanding: hard and idle expiry, which are best evidenced by the Phase 3b soak rather than waited on. Two visual confirmations also remain — that cleanup closed exactly one tab, and that no stray popup window survived.
923948

924949
### Run the read-only soak
925950

0 commit comments

Comments
 (0)