# TODO ## Per-id history removal The notification spec (quickshell repo, `docs/superpowers/specs/2026-09-15-notification-daemon-design.md`) says a history row is closable individually. The daemon has no per-id history delete: `notifyctl` ships `clear-history` (all) only, so the renderer's history page ships inert rows and a clear all. To close this: - `Store.RemoveHistory(id uint32)` in `internal/notify/store.go`, dropping one entry from the ring and publishing. - `control.RemoveHistory(id)` in `internal/notify/control.go`. - `notifyctl history-remove ` in `cmd/notifyctl/main.go`. - A `store_test.go` case that removes one entry and leaves the rest of the ring. - Renderer: `shared/Notify.qml` gains `historyRemove(id)` running `notifyctl history-remove`, and `desktop/NotificationRow.qml` calls it for a non-live (history) row instead of ignoring the click. Until then, the history page clears all or nothing. ## Image support follow-ups Spec: quickshell repo, `docs/superpowers/specs/2026-09-15-notification-images-design.md`. The feature ships (`image.go`, `icons.go`, `classify.go`, the `image` field and its cleanup, the `body-images` capability); these are polish or documented ceilings. - [ ] `IconMaxPixels` is 256 in `internal/notify/classify.go`. opencode's logo is 480x600, so it draws as a large preview rather than an app icon. Raise the bound to 640 if large logos should be icons, accepting that a small area screenshot under 640px would then also render small. - [ ] An image written between `Store.Add` and `Store.SetImage` is orphaned if the entry is dismissed, evicted or replaced in that window: `SetImage` no-ops and nothing removes the file. - [ ] `Store.Expire` unlinks the image but does not republish, so `queue.json` keeps a path to a removed file until the entry is dismissed. - [ ] `Service.removeImage` only checks that a path sits directly inside the image directory, so a client that sets `image-path` into that directory could have another notification's PNG unlinked. Same-user only, inside the daemon's own directory. - [ ] `Inherits` is read from the first XDG root that yields a value, not the root the icon resolved from; `iniValue` is section-agnostic and skips only `#` comments. - [ ] `homeDir` falls back to `os.TempDir()` when `HOME` is unset. - [ ] A present-but-undecodable `image-data` blocks the `image-path` fallback. The priority is correct; the failure is only logged. - [ ] No `recover` on the D-Bus call path: the image overflow was fixed, but any handler panic still crashes the daemon. Consider a recover in the service methods or the dispatch. - [ ] `ResolveIcon` passes through any value containing `/`, including a relative path a client might send.