* fix(runtime-environments): don't crash when a server removed via the CLI still responds
orca environment rm edits the environment store behind the running app, so the
next ok response on a live socket called markEnvironmentUsed, which threw
'Unknown environment' out of an unguarded socket callback. Main-process callers
now use markEnvironmentUsedIfPresent, which skips a missing environment and
keeps every other store error; the status owner pauses shared control instead
of re-establishing it for a removed server.
* fix(runtime-environments): guard usage bookkeeping at the main-process boundary
Keep one strict store contract and move the leniency to the caller that cannot
report a failure to anyone.
- Revert markEnvironmentUsedIfPresent: drawing the line around one error string
left corrupt, unreadable and oversized store files still fatal on the same
unguarded socket callback.
- Add recordRuntimeEnvironmentUsage, a named main-process boundary that says
lastUsedAt is advisory and swallows every store failure. Route only the three
sites with no observer through it (subscription onResponse in transport- and
support-routing, and the status owner's verified hook, where a throw skips
settleWaiters and hangs refresh callers). Awaited request paths stay strict.
- Guard onResponse/onBinary in the subscription frame router the way the sibling
request router already guards validateStatus, so no consumer throw can reach
the ws 'message' emitter and become main_uncaught_exception.
- Drop the status-owner `capable && present` gate: pauseStandingRetry no-ops
while subscriptions exist, and removal teardown belongs to #21048's watcher.
Co-authored-by: mmarabel <mmarabel@users.noreply.github.com>
* test(runtime-environments): cover the real socket path a consumer throw escapes
The existing tests invoke the captured onResponse directly, which never touches
the surface that actually kills the app. Drive a real WebSocket server through
subscribeRemoteRuntimeRequest so the throw travels ws 'message' -> handleFrame
-> consumer; without the frame-router guard vitest reports it as an unhandled
error, which is main_uncaught_exception in production.
---------
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: mmarabel <mmarabel@users.noreply.github.com>
A control-handshake test that expects a timeout was instead getting
'Unexpected server response: 401' about once in fourteen runs. A slow machine
cannot turn a timeout into a 401 -- that needs a real HTTP response, so the
connection was reaching a different server.
new WebSocketServer({ port: 0 }) binds the wildcard address while the client
dials 127.0.0.1. On macOS those differ, and with SO_REUSEADDR a foreign process
can hold the more specific 127.0.0.1:P and win the connection. Caught live: a
wildcard bind took port 52584, which a running Orca app already held on
loopback, and Orca answered the probe. A listener that checks a token answers
401.
Ten constructions across seven files now pass host: '127.0.0.1', so the
reservation covers the address the client dials and a duplicate bind is refused.
Adds a ratchet, because this is not authors forgetting a convention: all 30+
.listen(0, ...) sites already pass '127.0.0.1', while 7 of 7 ws constructions
did not. ws accepts { port } alone and binds the wildcard silently, so nothing
told them. The guard pins the wildcard count, and pins separately at zero the
option shapes it cannot read -- spreads and variable option objects fail rather
than being exempted, and a recognized-construction floor catches the matcher
going blind, which otherwise reads exactly like a clean tree.
mobile/scripts/mock-server.ts stays on the wildcard deliberately: a phone
reaches it over the LAN.