Repository navigation
Conversation
…ilms the device Records the decisions behind #593, from what PoC #576 found: the stream route and envelope, close-is-stop, captures bounded by their lease, one optional driver capability for iOS and Android, the gateway relay with a head-only deadline, no business events, and vendored code under vendor/.
…ver capability as built The relay's 330 s deadline covers the channel and the response head; an idle timer of 330 s bounds every relayed body. The Android client reaches scrcpy through adb's smart-socket protocol, so no adb forward exists. The lease-end hook waits for captures to close before reclaim. Driver.screenCapture is declared in src/core/screen.ts; the iOS capture program's path can be overridden by drivers.ios.screenCaptureCommand.
The module is wired by the composition root, not ADR 0030's host. iOS's capture tool is built by pnpm build on the host; the scrcpy jar is copied after its digest check. Android sends an alive frame on a still screen, drops nothing and needs no reclaim sweep. The tag table gains seed and alive; the gateway's header bounds, 502 and relay-failure answers match checkedMeta and refusal.ts. No dispose hook; the log records opened and refused.
V3RON
marked this pull request as ready for review
October 15, 2026 11:29
Merged
8 of 11 tasks
…, protocol bump A driver's open takes a stop signal and the lease end waits for an open in progress. Android's alive frames start after the first key frame. The gateway maps relay failures to 503 and defines its 502. bitrateKbps starts at 100; available carries no reason; the config contract bumps the protocol. Captures per lease are unbounded in v1.
…leased capture the lease end still waits for
… and states the daemon stop once
…ast ADR 0013's 10 s
# Conflicts: # docs/internal/adr/README.md
V3RON
added a commit
that referenced
this pull request
Oct 15, 2026
…whoever is looking at it (#576) Closes #593 A leased iOS simulator's or Android emulator's screen, live in the console and at `GET /v1/stream/leases/{leaseId}`, on a worker and through a gateway. Design: ADR 0031 (#594). One PR, one review. - **Stream module** (`src/stream/`): no platform names; opens a screen through the driver's `screenCapture`, registers before it starts, re-reads the lease after the first frame, stops every capture when its lease ends. - **iOS**: serve-sim's capture, vendored and patched to Simlock's device set; `pnpm build` builds it on macOS. - **Android**: our own TypeScript client in the Android driver for the vendored, SHA-pinned scrcpy 5.0.1 server; adb smart socket, no `adb forward`; an `alive` frame keeps a still screen open. - **Gateway**: the relay's 330 s deadline now bounds only the head; a body is bounded by 330 s of silence on the Clock port (amends ADR 0028 §4). A worker gone or serving no stream answers 503. - **Module**: an optional module on ADR 0030's contract, under `capabilities.stream`; the worker context gains a registry read and the drivers' screens. No protocol change. ### Status Implement: done Review: 2 rounds done; the move onto ADR 0030 is not reviewed yet Hardware: live check passed on both platforms; slow lane not green yet Gate: not run Next: review round 3 on the move to the module contract, slow lane, the gateway check on real devices, then merge after #594 ### Done when - [x] Show screen on a leased iOS simulator, single worker: live in the console, iPhone 17 / iOS 27, 330×720 h264 - [x] The same on an Android emulator: Pixel 9, 320×720, first frame 4.1 s - [ ] The same through a gateway, both platforms (unit: `src/stream/gateway-link.test.ts`, `src/stream/create.test.ts`; not run live) - [x] Each Examples row answers its status and code, worker and gateway (`src/stream/*.test.ts`) - [x] Closing the request ends the capture: no capture process; on Android no server and no jar (checked live with `pgrep -x` and `adb shell`) - [ ] Releasing a watched lease ends the stream and leaves nothing, including mid-open: the open is stopped and reclaim waits for it (unit: `worker-link.test.ts`, `captures.test.ts`, `session.test.ts`; slow lane pending) - [x] A still Android screen stays open past 30 s, and one that never paints does not (`session.test.ts`; slow lane holds 45 s and requires `alive`, pending) - [x] `capabilities.stream.enabled: false`: no route, capability `off`; on: `available` (`e2e/console/screen.spec.ts`, 5/5 Chromium) - [x] `pnpm build` checks the scrcpy SHA-256 (a mismatch fails it) and builds the iOS program on macOS (`src/build-capture.test.ts`) - [x] Vendored code carries license texts and a `NOTICE.md` (`src/source-hygiene.test.ts`) - [ ] `scripts/slow-e2e.sh e2e/slow-ios-stream.test.ts e2e/slow-android-stream.test.ts` passes (first run failed at lease with the disk nearly full) ## Assumptions - Assumption: physical phones are refused `STREAM_NOT_SUPPORTED` on both platforms in v1. - Assumption: no business events; each stream opened or refused is logged. - Assumption: viewers per lease are not capped in v1; one capture each (#602 shares one capture). ## Review Spec review: 7 blocking, 3 fixed, 3 notes. Code review: 15 blocking, 15 fixed, 3 notes. Claims review: 8 blocking, 8 fixed, 9 notes. Rounds: 2. Tokens: 0.11M. Fixed in round 1 (`12943e48`): the console gave up on a stream's headers after 10 s, before a worker's own refusal; it now waits 90 s (ADR 0031 records the exception to ADR 0013). The rest were tests that could not fail and wording. Round 2 (`3d387864`): tests for the 30 s defaults and wording; Stop now also cancels a starting stream. Rejected: - spec: the slow-lane tests have not passed — proven by the hardware stage, not by review - spec: the gateway check on real devices is not done — a maintainer check on hardware - spec: (round 2) the slow-lane Android test has not passed — same as above - spec: (round 2) the gateway check on real devices — same as above *Written by an agent.* --------- Co-authored-by: Apex <noreply@callstack.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ADR 0031 for #593 (live screen streams of leased devices), accepted and matching #576. It amends ADR 0028 §4's relay deadline.
It decides:
streamis an optional module, wired bydaemon/main.ts(ADR 0030 is not merged). One name everywhere.GET /v1/stream/leases/{leaseId}is the only start, closing it the only stop. Body: the length-tag envelope, meta first, tags insrc/core/screen.ts.Driver.screenCapture. iOS runs the vendored serve-sim-derived tool thatpnpm buildbuilds on the host. Android runs our client against the vendored scrcpy 5.0.1 jar over adb smart sockets, withaliveframes on a still screen. Physical devices refused.stream, ownership proved twice, bytes unparsed, worker answers checked, relay failures answered 503. Every relay: 330 s deadline to the head, then a 330 s idle timer.vendor/.Stays open below #576 until it merges.
Status
Assumptions
None.
Written by an agent.