fix(extension): cross-origin nav must update daemon's lastActiveTab — §2C(iv)#6
Open
LeonTing1010 wants to merge 1 commit intomainfrom
Open
fix(extension): cross-origin nav must update daemon's lastActiveTab — §2C(iv)#6LeonTing1010 wants to merge 1 commit intomainfrom
LeonTing1010 wants to merge 1 commit intomainfrom
Conversation
… §2C(iv)
Post-merge dogfood (2026-05-09) caught a regression: §2C(iii) opens a
new bg tab for cross-origin nav, but chrome.tabs.create({active:false})
does NOT trigger chrome.tabs.onActivated, so the existing
active_tab_changed listener (line ~1430) never fires. Daemon's
lastActiveTab cache stays pointing at the OLD active tab → subsequent
ops in the same plan (eval/extract/click) silently route to the wrong
page.
Symptom: a cursor.directory plan returned bodyText/title/url from the
PREVIOUSLY-active Ahrefs tab (silent data corruption — reverse of the
problem §2C(iii) was meant to fix). The cross-origin guard worked
(new tab opened) but the post-nav routing silently broke.
Fix: in the §2C(ii)/(iii) chrome.tabs.create branch, manually emit
active_tab_changed via ws.send when fromDaemon=true. Daemon updates
its lastActiveTab cache; subsequent ops route to the new tab via the
existing fallback logic.
Static guard (Rule iv): self-heal.test.mjs source-text checks:
iv/1: chrome.tabs.create branch sends active_tab_changed
iv/2: emit is gated on fromDaemon (popup path unaffected)
CDD Phase 7 post-mortem:
Why didn't existing tests catch this? Source-text tests verified the
STATIC SHAPE (new tab created on cross-origin) but couldn't verify
the DYNAMIC TAB ROUTING across daemon-driven multi-op plans. Real
dogfood exposed the gap between "new tab opened" and "subsequent
ops route to it". Rule (iv) closes the static guard at the same
layer (source-text proxy for the runtime behavior).
Real-world verification: after this lands + reload extension, re-run
the same cross-origin batch (cursor after Ahrefs) — eval should
return cursor.directory content, not Ahrefs content.
Companion to PR #5 §2C(i)+(ii)+(iii). All four §2C subsections are
substrate-side fixes for the same dogfood session — one contiguous
self-heal patch.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CDD Phase 7 post-merge fix. §2C(iii) shipped in PR #5 opens a new bg tab for cross-origin nav, but
chrome.tabs.create({active:false})doesn't triggerchrome.tabs.onActivated, so the daemon'slastActiveTabcache stays stale. Subsequent ops in the same plan silently route to the OLD active tab.Symptom
Real dogfood 2026-05-09 (after merging PR #5):
The page object correctly shows the new cursor tab, but the eval result was injected into the OLD Ahrefs tab.
Root cause
active_tab_changedis sent viachrome.tabs.onActivatedlistener (line ~1430). Whenchrome.tabs.create({active:false})is used, the new tab is NOT activated, so onActivated doesn't fire, and daemon'slastActiveTabstays at the previous tab.The existing
lastActiveTabfallback at line ~1364 then routes the next op to the OLD tab.Fix
In the §2C(ii)/(iii)
chrome.tabs.createbranch, manually emitactive_tab_changedto ws whenfromDaemon=true. Daemon's cache catches up; subsequent ops route correctly.Static guards (Rule iv in
self-heal.test.mjs)chrome.tabs.createbranch sendsactive_tab_changedfromDaemon(popup path unaffected)CDD verification
Phase 7 learning
Source-text tests verified the STATIC shape (new tab created on cross-origin) but couldn't verify the DYNAMIC tab routing across daemon-driven multi-op plans. Real dogfood exposed the gap between "new tab opened" and "subsequent ops route to it". Rule (iv) closes the static guard at the same layer (source-text proxy for the runtime behavior). Per CDD v3 §7: the new RED test was added BEFORE the implementation fix, then the audit note explains why the original §2C(iii) tests passed despite this gap.
Real-world verification
After merge + reload extension:
🤖 Generated with Claude Code