Files

10 KiB

phase, verified, status, score, human_verification
phase verified status score human_verification
04-notifications-et-i3bar 2026-03-23T21:00:00Z human_needed 3/3 must-haves verified
test expected why_human
Lancer une session Claude Code active, declencher une transition Working -> Needs Input via un hook reel Une notification dunst apparait dans la barre de notifications Necessite notify-send + dunst installe et display actif. Impossible a tester sans env graphique.
test expected why_human
Configurer i3bar avec status_command = vmux i3bar, puis recharger i3 Un bloc vmux apparait dans la barre i3 avec le statut des sessions. Couleur rouge si une session attend, verte sinon. Necessite un environnement i3 en cours d'execution avec le daemon vmux actif.
test expected why_human
Tester vmux i3bar en standalone: lancer ./vmux i3bar dans un terminal Header {"version":1}, puis [, puis lignes JSON avec bloc vmux toutes les 2 secondes Necessite que le daemon tourne. Verification du format visuel en temps reel.

Phase 4: Notifications et i3bar - Rapport de Verification

Phase Goal: L'utilisateur est notifie passivement quand une session a besoin de lui, sans ouvrir vmux Verifie: 2026-03-23 Statut: human_needed Re-verification: Non (verification initiale)

Resultats par critere de succes

Verites observables

# Verite Statut Preuve
1 Une notification dunst apparait quand une session passe de "Working" a "Needs Input" VERIFIED hook.go:84 — condition state == "Needs Input" && prevState == "Working" && !d.focus.IsActive() + d.notifier.Notify(...). Tests TestNotification_WorkingToNeedsInput et TestNotification_FocusExpired passent.
2 Le mode focus supprime temporairement les notifications (vmux focus <minutes>) VERIFIED main.go:105-130case "focus" parse les minutes, envoie FocusArgs au daemon. daemon.go:446-453d.focus.Set(...). hook.go:84!d.focus.IsActive() bloque la notif. Test TestFocusHandler + TestNotification_FocusActive passent.
3 Un widget i3bar affiche en temps reel le nombre de sessions et combien attendent de l'input VERIFIED i3bar.go complet avec formatI3BarBlocks, queryVmuxBlock, runI3Bar (standalone + wrapped). main.go:145-158case "i3bar" avec detection TTY. 10 tests dans i3bar_test.go passent.

Score: 3/3 verites verifiees

Artefacts requis

Artefact Fournit Niveau 1 (Existe) Niveau 2 (Substantiel) Niveau 3 (Cable) Statut
notify.go Notifier interface, ExecNotifier, NullNotifier, shortName Oui 44 lignes, implementation reelle avec exec.Command + timeout 5s Importe via d.notifier dans daemon.go et hook.go VERIFIED
notify_test.go Tests ExecNotifier, NullNotifier, shortName Oui 5 tests substantiels N/A (test file) VERIFIED
focus.go FocusTimer thread-safe (Set/IsActive/Remaining) Oui 38 lignes, mutex, logique correcte Utilise dans daemon.go champ focus *FocusTimer et hook.go VERIFIED
focus_test.go Tests FocusTimer Oui 4 tests couvrant Set/Expired/Remaining/ZeroValue N/A (test file) VERIFIED
i3bar.go I3BarBlock, formatI3BarBlocks, queryVmuxBlock, runI3Bar Oui 177 lignes, protocole i3bar complet, wrapping i3status Appele depuis main.go case "i3bar" VERIFIED
i3bar_test.go Tests formatage i3bar Oui 10 tests couvrant tous les cas N/A (test file) VERIFIED

Verification des liens cles (Niveau 3)

De Vers Via Statut Detail
hook.go notify.go d.notifier.Notify() apres transition Working -> Needs Input WIRED hook.go:88d.notifier.Notify("vmux: "+shortName(info), ...)
hook.go focus.go d.focus.IsActive() pour bloquer les notifications WIRED hook.go:84!d.focus.IsActive() dans la condition
main.go daemon.go case "focus" envoie action focus au daemon WIRED main.go:105case "focus", daemon.go:446case "focus"
i3bar.go protocol.go formatI3BarBlocks consomme []SessionInfo WIRED i3bar.go:24func formatI3BarBlocks(sessions []SessionInfo)
main.go i3bar.go case "i3bar" appelle runI3Bar WIRED main.go:145case "i3bar", main.go:158runI3Bar(sockPath, i3statusCmd)

Trace de flux de donnees (Niveau 4)

Artefact Variable Source Produit des donnees reelles Statut
i3bar.go sessions []SessionInfo queryVmuxBlock -> client.Send(Request{Action: "list"}) -> daemon socket Oui — le daemon repond avec les sessions actives depuis le registre FLOWING
hook.go prevState d.registry.sessions[event.SessionID].PrevState Oui — lu depuis le registre avant UpdateFromHook FLOWING

Verifications comportementales (Spot-checks)

Comportement Commande Resultat Statut
Build propre nix-shell -p go --run "go build -o /dev/null ." build OK PASS
Suite de tests complete avec race detector nix-shell -p go --run "go test ./... -count=1 -race" ok github.com/pieMusic/vmux 7.169s PASS
Tests notification (5 tests) go test -run 'TestNotification|TestFocusHandler' Tous PASS PASS
Tests FocusTimer (4 tests) go test -run 'TestFocusTimer' Tous PASS PASS
Tests shortName (4 tests) go test -run 'TestShortName' Tous PASS PASS
Tests formatI3Bar (10 tests) go test -run 'TestFormatI3Bar' Tous PASS PASS
notification dunst reelle Necessite display actif Non testable en CI SKIP
widget i3bar dans barre i3 Necessite i3 + daemon actif Non testable en CI SKIP

Couverture des requirements

Requirement Plan source Description Statut Preuve
NOTIF-01 04-01-PLAN.md vmux notifie (dunst) quand une session passe de "travaille" a "attend input" SATISFIED hook.go:84-88 — condition + appel d.notifier.Notify. Tests TestNotification_WorkingToNeedsInput, TestNotification_IdleToNeedsInput (negatif).
NOTIF-02 04-01-PLAN.md vmux supporte un mode focus qui supprime temporairement les notifications SATISFIED focus.goFocusTimer. daemon.go:446-453 — handler "focus". main.go:105-130 — CLI vmux focus <minutes>. Test TestNotification_FocusActive.
I3-03 04-02-PLAN.md vmux fournit un widget i3bar affichant le statut des sessions en temps reel SATISFIED (code OK, verification visuelle necessaire) i3bar.go complet. main.go:145-158case "i3bar". 10 tests passent. Note: REQUIREMENTS.md a encore [ ] au lieu de [x] pour I3-03 — inconsistance documentaire.

Note: REQUIREMENTS.md marque encore I3-03 comme Pending ([ ] a la ligne 28 et Pending dans la table de tracabilite ligne 79). L'implementation est complete mais le fichier n'a pas ete mis a jour. Ce n'est pas un gap fonctionnel.

Verite non testee du prompt de verification

Le prompt indique vmux focus on/off comme critere de succes. Le ROADMAP.md dit vmux focus <minutes>. L'implementation utilise un timer (pas un toggle on/off), ce qui est conforme au ROADMAP et aux decisions de conception D-04. La formulation on/off dans le prompt est incorrecte — le critere reel est satisfait.

Anti-patterns detectes

Aucun anti-pattern bloquant. TestExecNotifier_CallsNotifySend dans notify_test.go est minimaliste (verifie uniquement l'interface, pas l'appel reel a notify-send) mais c'est une limitation justifiee : le test reel necessite un display actif, il est delogue en verification manuelle.

Verification humaine requise

1. Notification dunst lors d'une transition reelle

Test: Avec un daemon vmux actif et dunst qui tourne, declencher un hook Stop sur une session en etat "Working" (par exemple en laissant Claude Code finir une tache). Attendu: Une notification dunst apparait avec le titre vmux: <nom-session> et le corps Session needs input (question). Pourquoi humain: Necessite notify-send installe, un display X11/Wayland actif, et dunst en cours d'execution. L'environment de CI n'a pas ces prerequis.

2. Widget i3bar dans la barre i3

Test: Ajouter status_command /chemin/vers/vmux i3bar dans ~/.config/i3/config, recharger i3 (i3-msg reload), s'assurer que le daemon vmux tourne. Attendu: Un bloc vmux: all working (N) (vert) ou vmux: nom[!] (rouge) apparait dans la barre i3 aux cotes des infos systeme de i3status. Rafraichissement toutes les 2 secondes. Pourquoi humain: Necessite un environnement i3 actif avec le daemon et au moins une session Claude Code.

3. Mode standalone vmux i3bar

Test: Dans un terminal, lancer ./vmux i3bar (avec le daemon actif). Attendu: Affichage du header {"version":1}, puis [, puis une ligne JSON toutes les 2 secondes du type [{"full_text":"vmux: all working (N)","color":"#00ff00","name":"vmux"}]. Pourquoi humain: Necessite le daemon actif et des sessions detectees. La sortie visuelle est difficile a valider automatiquement en mode interactif.


Resume

Phase 4 atteint son objectif fonctionnel. Les trois mecanismes cles sont implementes, cables et testes :

  1. Notifications : ExecNotifier appelle notify-send --urgency=critical sur la seule transition pertinente (Working -> Needs Input). Les 4 scenarios de notification (normal, idle->needsinput, focus actif, focus expire) sont couverts par des tests avec spyNotifier.

  2. Mode focus : FocusTimer thread-safe avec Set/IsActive/Remaining. CLI vmux focus <minutes> fonctionne de bout en bout via le daemon. Le focus bloque les notifications mais pas l'i3bar (D-05 respecte).

  3. Widget i3bar : formatI3BarBlocks produit le format compact vmux: auth[!] portal[W] avec les bonnes couleurs. runI3Bar implemente le protocole i3bar v1 en mode standalone et en mode wrapping i3status. La detection TTY evite le fallback texte brut.

La seule chose non verifiable automatiquement est le rendu visuel final dans l'environnement graphique (dunst + i3bar).


Verifie : 2026-03-23 Verificateur : Claude (gsd-verifier)