fix(daemon): open --foreground P1 hotfix — selector rejection, interactive snapshot, capture-failure masking - #1671
fix(daemon): open --foreground P1 hotfix — selector rejection, interactive snapshot, capture-failure masking#1671thymikee wants to merge 4 commits into
Conversation
Size Report
Startup median (7 runs, lower is better):
Top changed chunks:
|
|
Reviewed exact head
Because this is device-facing composition, attach an exact-head simulator run proving default text output, JSON output with usable refs, and capture-failure behavior with the session remaining usable. The helper mocks do not replace that production evidence. Completed checks are green; iOS Smoke is still pending. |
|
CI follow-up: the completed red iOS Smoke lane is failing |
…tdout and project initialSnapshotError through the public surfaces Post-merge review on #1671 found the daemon fixes never reached the public boundaries: openCliOutput ignored the nested snapshot (the one-call promise held only under --json), and initialSnapshotError was daemon-only — absent from AppOpenResult, Node normalization, and serializeOpenResult, with the normalized shape truncated to code+message. - default open output now renders the composed interactive tree through the same snapshotCliOutput path snapshot -i uses - AppOpenResult carries initialSnapshotError as the FULL daemon error (hint/details/diagnosticId/logPath preserved) through normalization and serialization Worker-authored; committed by the coordinating session after the worker stalled twice mid-push. Tests: output.test.ts + session-open-foreground (26 pass), typecheck, oxfmt.
|
Both public-boundary findings are fixed in 8e239d1 (worker-authored; committed by the coordinating session after the worker stalled twice mid-push):
Live evidence, honestly scoped — this shared host currently has two booted simulators owned by other active sessions, which cannot be shut down, so the exact-head happy-path stdout transcript is not capturable here without violating the sole-booted-device precondition:
Touched suites pass (26 tests), typecheck + oxfmt clean. Evidence simulator and custom set deleted after use. |
|
Re-reviewed exact head |
…ctive snapshot, capture-failure masking Three P1s from the post-merge review of #1670, all at the session-open-foreground dispatch seam: 1. Explicit device selectors were silently overwritten: the resolved-device rewrite pinned --udid/--platform over whatever the caller passed, so `open --foreground --udid B` with sim A sole-booted silently opened A. Now fails fast with INVALID_ARGS (matching the existing app-positional rejection) on --udid/--device, and on --platform other than ios; an explicit --platform ios passes through. 2. The promised interactive snapshot was never requested: the composed snapshot dispatch forwarded the open request's flags untouched, without snapshotInteractiveOnly — so the capture was NOT the `snapshot -i` path the doc comment promised and returned no interactive presentation. The composed request now sets snapshotInteractiveOnly: true (the exact key the CLI maps -i to and the snapshot runtime reads as interactiveOnly). 3. A capture failure masked the successful open: returning the snapshot error discarded openResponse even though the session exists, so a retry of `open --foreground` failed with "close the current session first". Open success + snapshot failure now returns ok with an explicit initialSnapshotError {code, message} detail and a rendered warning that the session IS open and how to capture manually (snapshot -i). Regressions added for all three: explicit-selector rejection (udid/device/both/non-iOS platform + ios pass-through), the composed dispatch carrying snapshotInteractiveOnly, and the snapshot-failure path returning ok + warning + usable session.
…tdout and project initialSnapshotError through the public surfaces Post-merge review on #1671 found the daemon fixes never reached the public boundaries: openCliOutput ignored the nested snapshot (the one-call promise held only under --json), and initialSnapshotError was daemon-only — absent from AppOpenResult, Node normalization, and serializeOpenResult, with the normalized shape truncated to code+message. - default open output now renders the composed interactive tree through the same snapshotCliOutput path snapshot -i uses - AppOpenResult carries initialSnapshotError as the FULL daemon error (hint/details/diagnosticId/logPath preserved) through normalization and serialization Worker-authored; committed by the coordinating session after the worker stalled twice mid-push. Tests: output.test.ts + session-open-foreground (26 pass), typecheck, oxfmt.
…ons for initialSnapshotError Review follow-ups on #1671: normalizeInitialSnapshotError duplicated the target-shutdown error normalization and pushed the module over the fallow complexity threshold; consolidated into a single internal normalizeDaemonError (table-driven, full shape incl. retriable/supportedOn) used by both result paths, projected through normalizeOpenForegroundComposition. Client-route regressions: createAgentDeviceClient().apps.open now proves the full initialSnapshotError shape (hint/details/diagnosticId/logPath/retriable) survives normalization, and that a malformed one is dropped — deleting the boundary normalization fails these tests. Also rebased onto current main.
8e239d1 to
a517639
Compare
|
Both P2s addressed in a517639 (branch also rebased onto current main):
Live exact-head evidence for default stdout + capture-failure remains blocked by the two sibling-session simulators still booted on this host (same constraint as the prior comment); the production formatter route is covered by |
|
P1 — the capture-failure fix still misses the ordinary failure path. Please catch and normalize that rejected capture into the same successful-open Separately, this is iOS-facing dispatch/output behavior and has no exact-head live simulator evidence. After the fix, validate the one-call open, rendered interactive snapshot, and capture-failure recovery on the current head. |
…successful-open contract Review P1 on #1671: dispatchSnapshotViaRuntime rethrows ordinary capture/runner exceptions; the composition only handled a returned { ok: false }, so a thrown failure escaped to the router and failed the whole open after the session was created — retrying then wedged on the existing session. The catch normalizes the rejection (kernel normalizeError, same conversion the router applies) into the shared openWithInitialSnapshotFailure path: ok response, full-shape initialSnapshotError, session-usable warning. Rejecting-mock regression added alongside the returned-failure case.
|
Thrown-path P1 fixed in 95fd33e: the dispatch call is now wrapped, and a rejection is normalized via the kernel's Live exact-head validation of the one-call open + rendered tree + capture-failure recovery remains queued behind the two booted sibling-session simulators on this host; it will be posted the moment a sole-booted-simulator window exists. |
|
Re-reviewed exact head : code review is clean. The thrown snapshot-runtime failure now follows the same successful-open contract as a returned capture error, preserving the full normalized error and the usable session; the rejecting regression is revert-sensitive.\n\nExact-head live evidence on iPhone 17 Pro (iOS 26.2): resolved Settings and rendered the 18-visible-node interactive snapshot in default stdout; the immediate follow-up on the same session succeeded in 0.68s. Session was then closed and the simulator shut down.\n\nReady for human review. |
|
Correction (shell formatting stripped identifiers from the previous comment): Re-reviewed exact head 95fd33e: code review is clean. The thrown snapshot-runtime failure now follows the same successful-open contract as a returned capture error, preserving the full normalized error and the usable session; the rejecting regression is revert-sensitive.\n\nExact-head live evidence on iPhone 17 Pro (iOS 26.2): open --foreground resolved Settings and rendered the 18-visible-node interactive snapshot in default stdout; the immediate follow-up snapshot -i on the same session succeeded in 0.68s. Session was then closed and the simulator shut down.\n\nReady for human review. |
P1 hotfix for the
open --foregroundRFC prototype merged in #1670 — three defects confirmed by post-merge review, all at thesrc/daemon/handlers/session-open-foreground.tsdispatch seam.1. Explicit device selectors were silently overwritten
resolveForegroundOpenRequestrewrote the request with{ ...req.flags, udid: resolved.device.id, platform: 'ios' }, clobbering an explicit--udid/--deviceand overriding--platform:open --foreground --udid Bwith simulator A sole-booted silently opened A. Now fails fast — matching the existing app-positional rejection:--udidor--devicepresent →INVALID_ARGS("open --foreground resolves the device itself; drop --udid/--device or open explicitly")--platformpresent and notios→INVALID_ARGS--platform iospasses through (it states nothing the rewrite contradicts)2. The promised interactive snapshot was never requested
composeOpenWithInitialSnapshotdispatched{ ...req, command: 'snapshot', positionals: [] }with the open request's flags untouched — nosnapshotInteractiveOnly, so the composed capture was not thesnapshot -ipath the doc comment promised. Verified the mapping before hardcoding: the CLI maps-i→snapshotInteractiveOnly(src/commands/cli-grammar/flag-definitions-workflow.ts), andsrc/daemon/snapshot-runtime.tsreads exactlyreq.flags?.snapshotInteractiveOnlyasinteractiveOnly. The composed request now setssnapshotInteractiveOnly: true, and a test asserts the composed dispatch carries it.3. A capture failure masked the successful open
if (!snapshotResponse.ok) return snapshotResponse;discardedopenResponse— but the session exists at that point, so the caller saw only a capture error, and retryingopen --foregroundthen failed with "close the current session first". Now, open-success + snapshot-failure returnsok: truewith:openResponse.dataintact (session name, state dir, app identity)initialSnapshotError: { code, message }detailwarnings, whichopenCliOutputprints): the session IS open — runagent-device snapshot -iA capture error never masks a created session.
Testing
src/daemon/handlers/__tests__/session-open-foreground.test.ts: explicit-selector rejection (--udid,--device, both, non-iOS--platform, and the--platform iospass-through), the composed dispatch carryingsnapshotInteractiveOnly: true, and the snapshot-failure path returning ok + warning +initialSnapshotError+ usable session (15/15 in the file).session-open-foreground,ios-app-session-hint,request-router-open,session-open-existing,snapshot-handler— 102/102 passing.npm run typecheck,npm run check:layering,npx oxlint <touched> --deny-warnings,npx oxfmt --check .— all clean.