A lookup that fails during an otherwise successful refresh is read as an answer. PRs leave the list or join it, and they re-notify when the lookup recovers. The refresh still reports ok, and the menu shows no warning.
Evidence (extension/helper/attention.js on main, bb9f722)
- :341-343:
ok(listAll(... listPulls ...)) ?? []. A repo whose list fails (502 after retries) has no open PRs for that refresh. The engine's empty-result guard (engine.js:370) only fires when no repos are listed, so one failing repo out of many always gets through. - :358:
ok(lastComment(...)). IflistCommentsfails, a PR where you commented last falls back to "the author acted last". It shows up as waiting on you and fires aReview:notification. - :224:
ok(listCollaboratorsBy). If it fails, every repo you only collaborate on drops out together. engine.js:391-393:_knownis replaced by the shrunken list. The next good refresh treats the returning PRs as new, and their merge and CI verdicts reset tochecking.
I reproduced it by running the real compute() and Engine against a fake client (/tmp/claude-audit2-scratch/drop.js):
1 normal shown ["1"] notified []
2 listPulls 502 shown [] notified [] phase ok, error none
3 recovered shown ["1"] notified ["1"]
4 listComments 502 shown ["1","2"] notified ["2"] (#2: you commented last)
5 recovered shown ["1"] notified []
The live fetch log shows bursts of UpstreamFailed 502s from api.tangled.org that outlast all 3 attempts (14 of them on 2026-11-05 between 22:03 and 22:05). It's only luck that those hit getRef, which keeps the last head, and not a list call.
Proposal. Treat a failed list or comment lookup as "unknown", not as "nothing". For that repo or PR, carry the previous refresh's items and tracking forward, leave them in _known, and set the snapshot's error (e.g. "couldn't list PRs on owner/repo; showing the last list") so the menu says so. A failed listComments keeps the PR's previous waiting/not-waiting answer, or leaves it out if it has none. The protocol and state stay as they are: this changes the input to _apply, not its shape.
Done when a test (engine or tests/driver/ with the mock server returning 502 for one repo's listPulls, and for one listComments) shows the list unchanged, no new notification on recovery, and the header warning while it fails.
Fix proposed in https://tangled.org/permadeath.com/gnome-shell-extension-tangled-reviewer/pulls/41: failed list and comment lookups keep their last answer, the header says what could not be read, and recovery fires no "new" notifications. Includes a driver test that has the mock server answer 502 for one listPulls and one listComments.