Replaces the single-slot status-line flash with a top-right toast stack rendered over the focused pane.
flashError, flashTransient, and MCP request_human_attention now push onto the same stack (cap 5, oldest drops on overflow).
Ctrl-N dismisses the most recent toast. Empty stack lets Ctrl-N pass through to the focused PTY so readline / nano / emacs / opencode keep their bindings.
New "Clear notifications" palette command empties the stack.
Visual
Sample toast rendered by the new toast_dismiss harness scenario:
STEADY READY
╭────────────────────────────────────────────────╮
│ ! steady — needs eyes on the deploy │
╰────────────────────────────────────────────────╯
Test plan
go test ./...
go test -race ./internal/app/ ./internal/harness/
New unit tests in internal/app/toast_test.go cover push/cap/FIFO/dismissTop/clear/snapshot-copy
Existing error_flash_preserves_focused_pane.json still passes (toast surface preserves focused pane content)
Notes
Ctrl-N was chosen over Ctrl-X because opencode and other terminal apps bind Ctrl-X heavily; falling-through when the stack is empty keeps it cooperative.
Toasts are deliberately not auto-dismissed — user explicitly requested manual control.
## Summary
- Replaces the single-slot status-line flash with a top-right toast stack rendered over the focused pane.
- `flashError`, `flashTransient`, and MCP `request_human_attention` now push onto the same stack (cap 5, oldest drops on overflow).
- `Ctrl-N` dismisses the most recent toast. Empty stack lets `Ctrl-N` pass through to the focused PTY so readline / nano / emacs / opencode keep their bindings.
- New "Clear notifications" palette command empties the stack.
## Visual
Sample toast rendered by the new `toast_dismiss` harness scenario:
```
STEADY READY
╭────────────────────────────────────────────────╮
│ ! steady — needs eyes on the deploy │
╰────────────────────────────────────────────────╯
```
## Test plan
- [x] `go test ./...`
- [x] `go test -race ./internal/app/ ./internal/harness/`
- [x] New unit tests in `internal/app/toast_test.go` cover push/cap/FIFO/dismissTop/clear/snapshot-copy
- [x] New harness scenario `internal/harness/scenarios/toast_dismiss.json` exercises attention toast → Ctrl-N → dismissed
- [x] Existing `error_flash_preserves_focused_pane.json` still passes (toast surface preserves focused pane content)
## Notes
- `Ctrl-N` was chosen over `Ctrl-X` because opencode and other terminal apps bind Ctrl-X heavily; falling-through when the stack is empty keeps it cooperative.
- Toasts are deliberately *not* auto-dismissed — user explicitly requested manual control.
Replaces the single-slot status-line flash with a top-right toast
stack over the focused pane. flashError, flashTransient, and
notifyAttention all push onto the same stack (cap 5, FIFO drop).
Ctrl-N dismisses the most recent toast; empty stack falls through to
the focused PTY so readline / nano / emacs / opencode bindings keep
working. A new "Clear notifications" palette item empties the stack.
harry
merged commit e4ab8c2136 into main2026-05-15 20:28:10 +01:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
flashError,flashTransient, and MCPrequest_human_attentionnow push onto the same stack (cap 5, oldest drops on overflow).Ctrl-Ndismisses the most recent toast. Empty stack letsCtrl-Npass through to the focused PTY so readline / nano / emacs / opencode keep their bindings.Visual
Sample toast rendered by the new
toast_dismissharness scenario:Test plan
go test ./...go test -race ./internal/app/ ./internal/harness/internal/app/toast_test.gocover push/cap/FIFO/dismissTop/clear/snapshot-copyinternal/harness/scenarios/toast_dismiss.jsonexercises attention toast → Ctrl-N → dismissederror_flash_preserves_focused_pane.jsonstill passes (toast surface preserves focused pane content)Notes
Ctrl-Nwas chosen overCtrl-Xbecause opencode and other terminal apps bind Ctrl-X heavily; falling-through when the stack is empty keeps it cooperative.