Summary
On SPA sites that push multiple history entries with an identical URL (state tracked in JS, not the URL), go_back / go_forward falsely report failure: "no {direction} entry in this tab's history (the page did not change)." even though history.go() genuinely moved the tab.
Root cause
src/chrome/src/agent/agent.js:18636-18680 (and the Firefox mirror):
```js
history.go(d); // via chrome.scripting.executeScript
await new Promise(r => setTimeout(r, 1500));
...
if (this._normalizeUrl(afterUrl) === this._normalizeUrl(probe.before)) {
return { success: false, dispatched: true,
error: `${name}: no ${dirWord} entry in this tab's history (the page did not change).` };
}
```
_normalizeUrl keeps query and hash, so two entries with the same URL + hash (very common in pushState apps) are judged as "no movement". The fixed 1.5s wait also races slow pages and produces the same false failure.
Impact
The model either retries go_back in a loop or falls back to navigate, losing the history position it meant to restore. This is a silent wrong-failure: the navigation actually succeeded.
Suggested direction (needs design input)
When URL readback is unchanged, verify movement via a document/route signal (readyState transition, navigation event, or the content-script document token) before declaring failure; at minimum wait for a second readback after the tab reports loading. The right signal and the wait budget are a design decision — hence this issue rather than an immediate PR.
Summary
On SPA sites that push multiple history entries with an identical URL (state tracked in JS, not the URL),
go_back/go_forwardfalsely report failure: "no {direction} entry in this tab's history (the page did not change)." even thoughhistory.go()genuinely moved the tab.Root cause
src/chrome/src/agent/agent.js:18636-18680(and the Firefox mirror):```js
history.go(d); // via chrome.scripting.executeScript
await new Promise(r => setTimeout(r, 1500));
...
if (this._normalizeUrl(afterUrl) === this._normalizeUrl(probe.before)) {
return { success: false, dispatched: true,
error: `${name}: no ${dirWord} entry in this tab's history (the page did not change).` };
}
```
_normalizeUrlkeeps query and hash, so two entries with the same URL + hash (very common in pushState apps) are judged as "no movement". The fixed 1.5s wait also races slow pages and produces the same false failure.Impact
The model either retries
go_backin a loop or falls back tonavigate, losing the history position it meant to restore. This is a silent wrong-failure: the navigation actually succeeded.Suggested direction (needs design input)
When URL readback is unchanged, verify movement via a document/route signal (readyState transition, navigation event, or the content-script document token) before declaring failure; at minimum wait for a second readback after the tab reports
loading. The right signal and the wait budget are a design decision — hence this issue rather than an immediate PR.