feat(04-01): integrate notifications and focus mode into daemon

- Notifier + FocusTimer fields in Daemon, initialized in NewDaemon
- processHookEvent notifies on Working -> Needs Input only (D-01)
- Focus mode suppresses notifications when active (D-05)
- FocusArgs in protocol, "focus" handler in daemon
- CLI "vmux focus <minutes>" command
- Tests for all notification transitions and focus handler
This commit is contained in:
Pierre Martin
2026-03-23 21:26:02 +01:00
parent b96c6d05be
commit efbe31928e
5 changed files with 183 additions and 3 deletions

View File

@@ -168,6 +168,8 @@ type Daemon struct {
httpServer *http.Server
lastHookTime time.Time
mu sync.Mutex // protects lastHookTime
notifier Notifier
focus *FocusTimer
}
// NewDaemon creates a daemon ready to start.
@@ -181,6 +183,8 @@ func NewDaemon(sockPath, procDir, claudeDir string, labels *LabelStore) *Daemon
pollInterval: 5 * time.Second,
stopCh: make(chan struct{}),
hookPort: 3119,
notifier: &ExecNotifier{},
focus: &FocusTimer{},
}
}
@@ -439,6 +443,15 @@ func (d *Daemon) handleConnection(conn net.Conn) {
}
writeResponse(conn, Response{OK: true})
case "focus":
var args FocusArgs
if err := json.Unmarshal(req.Args, &args); err != nil {
writeResponse(conn, Response{Error: "invalid focus args: " + err.Error()})
return
}
d.focus.Set(time.Duration(args.Minutes) * time.Minute)
writeResponse(conn, Response{OK: true, FocusRemaining: d.focus.Remaining().Minutes()})
case "stop":
writeResponse(conn, Response{OK: true})
d.Stop()