detached 04dc983

test(daemon): repair vacuous session-isolation assertion; drop dead seq bump

TestNotifyRoutesToSessionClientOnly compared against a client from a
second, unrelated Daemon fixture, so the isolation check passed
regardless of whether session-scoped routing actually fanned out.
Build the second session/client on the same daemon (matching
TestNotifyGlobalFansOutToAttachedClients) so the assertion exercises
real routing.

Also drop the dead noticeSeq bump and seq stamp in showToast's
prepend branch: retainToastTimerLocked immediately re-bumps and
re-stamps seq before the timer arms, making the first assignment
misleading dead code.
commit
04dc9834000f628b527cceed1c88ccb2a22e5e20
author
brice · · 2026-07-20 12:35 UTC
parent
57a5dbb
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +11 -5
M internal/usecase/daemon/notify.go +1 -2
@@ -229,8 +229,7 @@ func (d *Daemon) showToast(ac *attachedClient, n domain.Notification) {
229229 return
230230 }
231231
232- rt.noticeSeq++
233- toast := noticeToast{n: n, seq: rt.noticeSeq}
232+ toast := noticeToast{n: n}
234233 rt.noticeToasts = append([]noticeToast{toast}, rt.noticeToasts...)
235234 if len(rt.noticeToasts) > maxVisibleToasts {
236235 for i := maxVisibleToasts; i < len(rt.noticeToasts); i++ {
@@ -229,8 +229,7 @@ func (d *Daemon) showToast(ac *attachedClient, n domain.Notification) {
229 return229 return
230 }230 }
231 231
232- rt.noticeSeq++232+ toast := noticeToast{n: n}
233- toast := noticeToast{n: n, seq: rt.noticeSeq}
234 rt.noticeToasts = append([]noticeToast{toast}, rt.noticeToasts...)233 rt.noticeToasts = append([]noticeToast{toast}, rt.noticeToasts...)
235 if len(rt.noticeToasts) > maxVisibleToasts {234 if len(rt.noticeToasts) > maxVisibleToasts {
236 for i := maxVisibleToasts; i < len(rt.noticeToasts); i++ {235 for i := maxVisibleToasts; i < len(rt.noticeToasts); i++ {
M internal/usecase/daemon/notify_test.go +10 -3
@@ -367,14 +367,21 @@ func TestReportErrorNonBenignIsNeverDropped(t *testing.T) {
367367
368368 func TestNotifyRoutesToSessionClientOnly(t *testing.T) {
369369 d, sess, ac, _ := newNoticeFixture(t, newNoticeClock())
370- _, _, otherAC, _ := newNoticeFixture(t, newNoticeClock())
370+
371+ other := &attachedClient{output: newOutputStateStream(), size: domain.Size{Cols: 80, Rows: 24}}
372+ other.initOverlays()
373+ sess2 := &session{id: "manual-2", name: "other", ctx: sess.ctx, cancel: func() {}, client: other}
374+ other.setSession(sess2)
375+ d.mu.Lock()
376+ d.sessions[sess2.id] = sess2
377+ d.mu.Unlock()
371378
372379 d.notify(sess, domain.NoticeInfo, domain.NoticeClipboard, "copied", nil)
373380
374381 toasts := awaitToastCount(t, ac, 1)
375382 require.Equal(t, sess.id, toasts[0].SessionID)
376- otherToasts, _ := visibleToasts(otherAC)
377- require.Empty(t, otherToasts, "another daemon's client must be untouched")
383+ otherToasts, _ := visibleToasts(other)
384+ require.Empty(t, otherToasts, "another session's client must be untouched by session-scoped notices")
378385 }
379386
380387 func TestNotifySessionWithoutClientRecordsHistoryOnly(t *testing.T) {
@@ -367,14 +367,21 @@ func TestReportErrorNonBenignIsNeverDropped(t *testing.T) {
367 367
368 func TestNotifyRoutesToSessionClientOnly(t *testing.T) {368 func TestNotifyRoutesToSessionClientOnly(t *testing.T) {
369 d, sess, ac, _ := newNoticeFixture(t, newNoticeClock())369 d, sess, ac, _ := newNoticeFixture(t, newNoticeClock())
370- _, _, otherAC, _ := newNoticeFixture(t, newNoticeClock())370+
371+ other := &attachedClient{output: newOutputStateStream(), size: domain.Size{Cols: 80, Rows: 24}}
372+ other.initOverlays()
373+ sess2 := &session{id: "manual-2", name: "other", ctx: sess.ctx, cancel: func() {}, client: other}
374+ other.setSession(sess2)
375+ d.mu.Lock()
376+ d.sessions[sess2.id] = sess2
377+ d.mu.Unlock()
371 378
372 d.notify(sess, domain.NoticeInfo, domain.NoticeClipboard, "copied", nil)379 d.notify(sess, domain.NoticeInfo, domain.NoticeClipboard, "copied", nil)
373 380
374 toasts := awaitToastCount(t, ac, 1)381 toasts := awaitToastCount(t, ac, 1)
375 require.Equal(t, sess.id, toasts[0].SessionID)382 require.Equal(t, sess.id, toasts[0].SessionID)
376- otherToasts, _ := visibleToasts(otherAC)383+ otherToasts, _ := visibleToasts(other)
377- require.Empty(t, otherToasts, "another daemon's client must be untouched")384+ require.Empty(t, otherToasts, "another session's client must be untouched by session-scoped notices")
378 }385 }
379 386
380 func TestNotifySessionWithoutClientRecordsHistoryOnly(t *testing.T) {387 func TestNotifySessionWithoutClientRecordsHistoryOnly(t *testing.T) {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close