Skip to content

[agent-cli] runtime:reload and smoke reload only this worktree's app while the scope skips one (llp/0005 §Target owner) - #207

Draft
vonovak wants to merge 1 commit into
vonovak/fix-cloud-scope-own-targetfrom
vonovak/fix-reload-skipped-apps
Draft

vonovak wants to merge 1 commit into
vonovak/fix-cloud-scope-own-targetfrom
vonovak/fix-reload-skipped-apps

Conversation

@vonovak

@vonovak vonovak commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

runtime:reload and smoke's reload reloaded other apps (dogfood N2-06, N2-17). The dev server sends a reload broadcast to every app on its port, so a reload in one worktree also reloaded an app the scope skipped.

Fix

When the scope skips an app, the reload sends Page.reload over the debugger to this worktree's targets only, not a broadcast. A new verifiedBy, debugger-context-replaced, proves it: a marker global set before the reload is gone after it. Evidence and the relaunch count only this worktree's targets. If no proof comes, auto relaunches this worktree's app, as before.

The marker proof has not run on a real React Native runtime, only in unit tests and the e2e stub. The live-cloud CI does not take this path.

🤖 Generated with Claude Code

@vonovak
vonovak marked this pull request as ready for review October 24, 2026 03:41
@vonovak
vonovak requested a review from Kudo October 24, 2026 03:41
@vonovak
vonovak marked this pull request as draft October 24, 2026 05:08
vonovak added a commit that referenced this pull request Oct 24, 2026
…with or without a platform flag (llp/0005 §Pointing an app at this dev server)

Problem (N3-25): right after `dev --ios --eas`, a `navigate` with no
platform flag waited 120 s and exited 22. The run decided "an app is
attached" from the platform flag, before the device was known. With no
flag it counted the debugger targets of every platform, so a local
simulator's app on the same Metro counted as attached, and the launcher
open for the session did not happen. A no-flag navigate to a local
Android emulator with only an iOS app attached made the same mistake.
`navigate --ios` that fell back to an EAS Simulator iOS session without
`--eas` had the reverse fault: the flag scope cannot place the session's
app, so the run reopened an attached app through the launcher.

Change: `openRouteAsync` builds one attach waiter from the scope of the
device it resolved, and asks it whether an app is attached before it
decides on the launcher open. The same waiter serves the launcher wait
and the route-link wait, and reads the device facts once, at its first
probe. The route resolver no longer reports an attached flag. llp/0005
states the rule in the section on pointing an app at this dev server.

This commit sits on the batch-2 stack (#202-#207, RunScope in
src/runtime/runScope.ts); its base is vonovak/fix-reload-skipped-apps.

Red before: navigateAsync on a development build that is not loaded >
opens the launcher URL first, when no platform is named and only an iOS
app is attached; navigateAsync on an EAS Simulator session > opens, with
no flag, an Android session, only an iOS app attached; navigateAsync on
an EAS Simulator session > opens, with --ios without --eas, an iOS
session, its app attached

Guard: navigateAsync on an EAS Simulator session > opens, with no flag,
an Android session, its app attached; navigateAsync on an EAS Simulator
session > opens, with no flag, an iOS session, its app attached

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vonovak
vonovak added this pull request to stack #210 October 26, 2026 09:54
@vonovak
vonovak force-pushed the vonovak/fix-reload-skipped-apps branch from d1b95e1 to 9b2210d Compare October 26, 2026 17:44
vonovak added a commit that referenced this pull request Oct 26, 2026
…with or without a platform flag (llp/0005 §Pointing an app at this dev server)

Problem (N3-25): right after `dev --ios --eas`, a `navigate` with no
platform flag waited 120 s and exited 22. The run decided "an app is
attached" from the platform flag, before the device was known. With no
flag it counted the debugger targets of every platform, so a local
simulator's app on the same Metro counted as attached, and the launcher
open for the session did not happen. A no-flag navigate to a local
Android emulator with only an iOS app attached made the same mistake.
`navigate --ios` that fell back to an EAS Simulator iOS session without
`--eas` had the reverse fault: the flag scope cannot place the session's
app, so the run reopened an attached app through the launcher.

Change: `openRouteAsync` builds one attach waiter from the scope of the
device it resolved, and asks it whether an app is attached before it
decides on the launcher open. The same waiter serves the launcher wait
and the route-link wait, and reads the device facts once, at its first
probe. The route resolver no longer reports an attached flag. llp/0005
states the rule in the section on pointing an app at this dev server.

This commit sits on the batch-2 stack (#202-#207, RunScope in
src/runtime/runScope.ts); its base is vonovak/fix-reload-skipped-apps.

Red before: navigateAsync on a development build that is not loaded >
opens the launcher URL first, when no platform is named and only an iOS
app is attached; navigateAsync on an EAS Simulator session > opens, with
no flag, an Android session, only an iOS app attached; navigateAsync on
an EAS Simulator session > opens, with --ios without --eas, an iOS
session, its app attached

Guard: navigateAsync on an EAS Simulator session > opens, with no flag,
an Android session, its app attached; navigateAsync on an EAS Simulator
session > opens, with no flag, an iOS session, its app attached

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…while the scope skips one (llp/0005 §Target owner)

Problem: the dev server relays a reload broadcast to every app on its port.
- N2-06 (night 1): a runtime:reload in one worktree reloaded another
  worktree's app.
- N2-17 (night 2): on a worktree bound to an EAS Simulator session, the
  scope line said it skipped the app on the local simulator, and the
  broadcast then reloaded that app.
- The review of the old layers (thermo 02) found four more bugs: a fresh
  debugger target of a skipped app proved this worktree's reload; the
  bundle rule guarded the wrong axis (an iOS bundle of another worktree's
  iOS app proved the own iOS app); the relaunch could take a skipped
  app's app id; and the e2e stub re-id'd every target on Page.reload,
  which the real runtime does not do.

Change:
- New src/runtime/reload/rungOne.ts. A pure policy decides rung 1 from
  the placed targets: `page-reload` exactly when the scope skips an app;
  a served bundle proves only for a platform no skipped app is on; a
  target is skipped by its device name, so a new page of a skipped
  device is skipped too. One runner returns a typed outcome: proved,
  delivered, not-delivered, or unprovable. The broadcast code moved
  there from reloadAsync.ts unchanged.
- New src/runtime/contextReplaced.ts: set a marker global on the own
  target with Runtime.evaluate, take the action, and read the marker on
  the same target id until an evaluate answers without it. The reads
  share one debugger connection, opened again only when it drops. A
  failed read and a read that still finds the marker are "not yet". A
  target that
  cannot keep the marker gets no Page.reload (unprovable), and `auto`
  relaunches at once. New verifiedBy label `debugger-context-replaced`;
  a run it proves skips the evidence wait, and bundlesAfterReload.reason
  says the new context proved the reload.
- ReloadAttempt is a union with `{ method: 'page-reload'; answeredBy }`.
  The top-level `method` stays `dev-server` on this path.
- Evidence counts only own targets: known ids, the fresh-target wait and
  `appsConnected` leave out skipped apps. The relaunch takes the app id
  from the own targets (local and cloud).
- The human report prints one line per skipped placement group, and
  its "via" phrase names Page.reload when a `page-reload` attempt ran.
- smoke's reloadApp calls the same rung 1 and maps its outcome.
- e2e stub: Page.reload answers {}, keeps every page id, and clears the
  marker of the reloaded app only. It counts broadcasts and Page.reloads.
- llp/0005 §How it reloads, §What proves a reload, §Target owner,
  §Testing.

Not observed: the marker proof has not run against a real React Native
runtime. The unit tests and the e2e stub model it. If a real runtime
does not clear the marker, rung 1 reports `delivered` and `auto`
relaunches the own app, which is observed behavior.

Not done: `--method runtime` keeps its fresh-debugger-target proof. That
rung has an attributable proof already, so the marker helper is not used
there.

Red before (on the parent):
- rungOne-test and contextReplaced-test: the modules did not exist.
- reloadAsync-test "does not count a new page of the skipped app as this
  worktree's reload": reloaded true, appsReconnected 1.
- reloadAsync-test "relaunches this worktree's app, not the skipped app
  listed first": simctl terminate IOS-1 com.legend.app.
- smokeDeps-test "reloads only this worktree's app, and proves it by its
  new JavaScript context": ok false, verifiedBy null.
- e2e runtime-preflight-test "runtime:reload sends no broadcast and
  reloads only the session app": 1 broadcast.

Guard: reloadAsync-test (all broadcast cases, "climbs to the relaunch
when the broadcast was delivered and proved nothing", "does not check the
bundle of another worktree's app, and reports that app"), bundleSignal-test,
waitReady-test, and the e2e files runtime-reload-test,
runtime-preflight-test and smoke-test pass before and after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vonovak
vonovak force-pushed the vonovak/fix-reload-skipped-apps branch from 9b2210d to c9ea36d Compare October 26, 2026 18:24
vonovak added a commit that referenced this pull request Oct 26, 2026
…with or without a platform flag (llp/0005 §Pointing an app at this dev server)

Problem (N3-25): right after `dev --ios --eas`, a `navigate` with no
platform flag waited 120 s and exited 22. The run decided "an app is
attached" from the platform flag, before the device was known. With no
flag it counted the debugger targets of every platform, so a local
simulator's app on the same Metro counted as attached, and the launcher
open for the session did not happen. A no-flag navigate to a local
Android emulator with only an iOS app attached made the same mistake.
`navigate --ios` that fell back to an EAS Simulator iOS session without
`--eas` had the reverse fault: the flag scope cannot place the session's
app, so the run reopened an attached app through the launcher.

Change: `openRouteAsync` builds one attach waiter from the scope of the
device it resolved, and asks it whether an app is attached before it
decides on the launcher open. The same waiter serves the launcher wait
and the route-link wait, and reads the device facts once, at its first
probe. The route resolver no longer reports an attached flag. llp/0005
states the rule in the section on pointing an app at this dev server.

This commit sits on the batch-2 stack (#202-#207, RunScope in
src/runtime/runScope.ts); its base is vonovak/fix-reload-skipped-apps.

Red before: navigateAsync on a development build that is not loaded >
opens the launcher URL first, when no platform is named and only an iOS
app is attached; navigateAsync on an EAS Simulator session > opens, with
no flag, an Android session, only an iOS app attached; navigateAsync on
an EAS Simulator session > opens, with --ios without --eas, an iOS
session, its app attached

Guard: navigateAsync on an EAS Simulator session > opens, with no flag,
an Android session, its app attached; navigateAsync on an EAS Simulator
session > opens, with no flag, an iOS session, its app attached

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant