Gate found the unconditional post-load _acknowledgeSessionVisit() cleared a
hidden-tab completion's unread marker: a completion landing while
_ensureMessagesLoaded() is in flight AND the tab then goes hidden is correctly
marked unread, but the final re-ack wiped it. Gate the re-ack on
_isSessionActivelyViewedForList(sid) so only an actively-viewed session clears.
Regression test added. Co-authored-by: neaucode-bot.
Two CI-red issues, both fixed:
1. Lint (F401): the new tests/test_session_unread_dot_on_visit.py imported
`re` but never used it. Dropped the import.
2. Test hang/timeout: loadSession() now routes its viewed-count/unread clear
through the new _acknowledgeSessionVisit() helper, but the PRE-EXISTING
tests/test_cross_session_message_load_isolation.py harness (which extracts
loadSession and stubs its deps) didn't define it — so the extracted
loadSession broke and the node driver hung to the 60s pytest-timeout.
Stubbed _acknowledgeSessionVisit + _sessionVisitHasUnreadState to no-ops
there, mirroring the pre-existing _setSessionViewedCount /
_clearSessionCompletionUnread stubs they replaced. That harness covers
cross-session load ordering + stale-reject, not unread-dot state, so a
no-op stub preserves its intent; the real helper is exercised by the PR's
own test_session_unread_dot_on_visit.py.
Verified: ruff forward gate clean; the timeout test passes in ~1s; the PR's
unread-dot suite 7/7.
Salvaged from #4946 by @neaucode-bot. Rebuilt fresh on master (repro-confirmed),
without regressing hidden-tab completion state or lineage-parent unread dots.
Co-authored-by: neaucode-bot <neaucode-bot@users.noreply.github.com>