fix(daemon): key the implicit session by workspace and platform - #2587
Conversation
|
Size Report
Startup median (7 runs, lower is better):
|
|
Two routing blockers at 9ba53df. In session-routing.ts:213, the default-address return bypasses the ambiguity check. Open iOS without --platform, then Android with --platform android: a bare press or close now silently selects iOS instead of AMBIGUOUS_MATCH. Check all implicit candidates before preferring the default leaf, and cover default + android through the attaching-command path. In session-routing.ts:157, candidate matching uses req.flags even when the platform came from meta.lockPlatform. With an existing iOS session and an Android lock, empty flags make iOS appear to agree. The later lock policy leaves the platform unset because a session is already bound, so the command runs on iOS. Include the effective platform in candidate matching and cover an existing opposite-platform session, not only an empty store. Checks are green and there are no merge conflicts. The reported live runs do not cover these two combinations; both need regression proof before this is ready. |
An implicit session was addressed by `cwd:<workspace>:default`, one slot per checkout, so a repo driving both platforms could not open the second one: after `open --platform ios`, `open --platform android` and `boot --platform android` from the same directory failed with INVALID_ARGS against a session they never asked for. The workaround named a session by hand on every command of both legs. `--platform` now selects the implicit session, so `cwd:<workspace>:ios` and `cwd:<workspace>:android` coexist. A platform-naming request joins a session it genuinely agrees with, so a session opened without `--platform` stays reachable and keeps its own artifact directory; a same-platform device or target mismatch still gets the existing refusal instead of forking a twin. A request naming no platform joins the workspace's only implicit session and refuses with AMBIGUOUS_MATCH when several exist, while `sessionKind: 'inventory'` commands keep routing so `session list` can resolve the ambiguity. Two adjacent repairs were load-bearing: a settling interaction published the live session under `SessionState.name` rather than the address the store owns, which `session list` already reported as a phantom second row; and `--session-lock`'s platform reaches `flags` only after the key is chosen, so routing now reads `meta.lockPlatform` too.
Review found two routes #2580's routing still chose a platform by accident. The platform-less branch returned the `default` leaf before consulting the workspace, so opening iOS without `--platform` and then Android with it left a bare `press` or `close` on the iOS device instead of refusing with AMBIGUOUS_MATCH. The `default` leaf is now one candidate among the workspace's sessions rather than a short-circuit, and it is still where a lone session lands. Candidate matching read `req.flags` only, so a request whose platform came from `--session-lock` claimed no platform and the workspace's opposite-platform session appeared to agree with it. The lock policy then leaves the platform unset because a session is already bound, so nothing downstream corrected the choice. Candidate matching now sees the effective platform.
9ba53df to
9ffcb69
Compare
|
Both fixed at session-routing.ts default-leaf bypass — session-routing.ts lockPlatform matching — candidate matching now reads the effective platform, not just Both also proven live on the built CLI:
|
|
Both routing fixes look correct at 9ffcb69. A bare command now refuses with The failing Smoke Tests job looks unrelated. The iOS Settings replay stopped at its |
…tle-on-exit-2522 * origin/main: perf(scroll-until): answer every candidate from one visibility index (#2596) refactor(daemon): resolve device interactors through a composed capability (#2593) refactor(daemon): stop the client value-importing daemon internals (#2559) (#2594) refactor(shell-quote): one implementation, reached through the runner host port (#2595) docs(agents): delete the file-size tiers nobody enforces (#2597) fix(daemon): key the implicit session by workspace and platform (#2587) refactor(cli-schema): orient the schema layer above commands (#2543 step 3) (#2590)
Summary
An implicit session was addressed by
cwd:<workspace>:default— one slot per checkout — so a repo driving both platforms could not open the second: afteropen --platform ios,boot --platform androidfrom the same directory failed withINVALID_ARGSagainst a session it never asked for.--platformnow selects the implicit session, so one workspace holds both:A platform-naming request joins a session it genuinely agrees with, so a session opened without
--platformstays reachable and keeps its artifact directory; a same-platform device or target mismatch keeps the existing refusal instead of forking a twin. Ambiguity is refused, never resolved by open order. Also fixes a settling interaction republishing the session underSessionState.name, whichsession listalready showed as a phantom row.12 files, all session-routing plus docs. References #2580, which was self-closed as premature but still reproduces on 0.21.1.
Validation
Rebased on
origin/mainat1b6515b. Head9ffcb69:pnpm check:affected --run,check:fallow --base origin/main,tsc --noEmitandoxlintpass;src/daemonis 2757 tests.Live, built CLI, fresh checkout per case:
--platform, thenopen --platform android:session listshows:defaultand:android, barecloserefuses withAMBIGUOUS_MATCHnaming both, andclose --platform ios/--platform androideach close their own.AGENT_DEVICE_PLATFORM=android AGENT_DEVICE_SESSION_LOCK=rejectagainst an existing iOS session routesboot/opentocwd:<hash>:androidand the lockedsnapshotreturns an Android tree instead of running on iOS.open --platform android→snapshot→press @e2 --settleheldsession listto one address; reverting only the interaction fix reproduced the phantomdefaultrow.Follow-up, not in scope:
--sessionaccepts address-shaped values likecwd:<hash>:ios, which can squat an implicit key (pre-existing).