Skip to content

fix: pairing handshake so the page and relay cannot miss each other - #51

Merged
attson merged 1 commit into
mainfrom
fix/pairing-handshake
Aug 17, 2026
Merged

fix: pairing handshake so the page and relay cannot miss each other#51
attson merged 1 commit into
mainfrom
fix/pairing-handshake

Conversation

@attson

@attson attson commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Summary

Found while verifying v0.0.57 against a real browser: the pairing page sat on 「正在联系扩展…」 forever and no session could ever connect.

Root cause is a timing race, provable from the build artifacts. The pairing page's inline <script> runs while the document is parsing and posted its payload exactly once. The content script hosting the relay is declared run_at: document_idle — it installs after that. The page announced itself to nobody, and the message was gone.

The relay now announces itself the moment it installs, and the page answers. The page also keeps announcing for 20 s in case either signal is missed, and finally says plainly that it could not reach the extension instead of spinning forever. Either ordering now works — including reloading the extension while the pairing page is already open.

Why the unit tests missed it: they installed the relay first and then posted, because the test controls the ordering. The one ordering that happens in a real browser was the one never exercised. Both halves of the handshake now have tests.

The 404s visible in the same console (react-root, approval, rpc, preload-helper) are the in-page chat widget lazy-loading its React chunks and are unrelated to pairing — pairing-relay.ts-*.js loaded fine.

Test plan

  • pnpm typecheck clean; pnpm test 1128 passing; pnpm build clean
  • Relay announces readiness on install (new test, failed before the fix)
  • Page answers the announcement, retries, gives up with a message, and stops once a result arrives (new tests)
  • Real browser, session A: pairing page → click Allow → connected in 14 s, 43 real tabs
  • Real browser, trust persistence: restart A → connected in 2 s with no click
  • Real browser, second session: different cwd (/tmp), different port, connected in 1.5 s with no click
  • Real browser, tab ownership: A binds a tab → A sees mine=true busy=false, B sees the same tab as busy=true busy_label=~/code/caiji2

The pairing page's inline script runs while the document is parsing; the
content script hosting the relay runs at document_idle. The page posted
once, before the relay existed, so the message went nowhere and the page
sat on '正在联系扩展…' forever.

The relay now announces itself on install and the page answers, plus the
page keeps announcing for 20s in case either signal is missed, and says
so plainly if nothing ever responds.

Unit tests missed this because they controlled the ordering themselves —
the relay was always installed first.
@attson
attson merged commit 77d4e71 into main Aug 17, 2026
2 checks passed
@attson
attson deleted the fix/pairing-handshake branch August 17, 2026 17:39
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