Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions internal/tui/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,10 @@ func (m *Model) handleEvent(ev client.Event) (tea.Model, tea.Cmd) {
case "memory_event":
m.addTransientNote("memory · " + strings.TrimSpace(ev.SubType+" "+ev.Target) + eventTail(ev))
case "agent_signal":
if ev.SubType == "trim" {
// Context trimming is engine housekeeping — nothing the user
// can act on, so it never reaches the notice strip.
if ev.SubType == "trim" || ev.SubType == "tool_running" {
// Engine housekeeping: context trimming and tool-running
// heartbeats duplicate what the transcript already shows
// (the in-flight step spinner) — never reach the strip.
break
}
m.addTransientNote("signal · " + strings.TrimSpace(ev.SubType+" "+ev.Detail) + eventTail(ev))
Expand Down
12 changes: 10 additions & 2 deletions internal/tui/notices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ func assertAlertDwell(t *testing.T, m *Model, cmdArmed bool, substr string) {
}

// TestTrimSignalSilenced pins the actionable-only contract for agent_signal:
// the "trim" subtype is engine housekeeping (context-window trimming) —
// nothing the user can act on — so it must never surface as a notice.
// the "trim" and "tool_running" subtypes are engine housekeeping (context-
// window trimming, tool-execution heartbeats) — nothing the user can act
// on — so they must never surface as notices.
// Every other subtype keeps flowing into the strip.
func TestTrimSignalSilenced(t *testing.T) {
m := newTestModel()
Expand All @@ -71,6 +72,13 @@ func TestTrimSignalSilenced(t *testing.T) {
}
}

m.handleEvent(client.Event{Type: "agent_signal", SubType: "tool_running", Detail: "shell"})
for _, n := range m.notices {
if strings.Contains(n, "signal · tool_running") {
t.Fatalf("tool_running signal surfaced as a notice: %v", m.notices)
}
}

// Silence is per-subtype, not per event class.
m.handleEvent(client.Event{Type: "agent_signal", SubType: "fallback", Detail: "glm-x"})
if note, _ := lastNoteMatching(m, "signal · fallback"); note == "" {
Expand Down