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 |
|
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-130 — case "focus" parse les minutes, envoie FocusArgs au daemon. daemon.go:446-453 — d.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-158 — case "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:88 — d.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:105 — case "focus", daemon.go:446 — case "focus" |
i3bar.go |
protocol.go |
formatI3BarBlocks consomme []SessionInfo |
WIRED | i3bar.go:24 — func formatI3BarBlocks(sessions []SessionInfo) |
main.go |
i3bar.go |
case "i3bar" appelle runI3Bar |
WIRED | main.go:145 — case "i3bar", main.go:158 — runI3Bar(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.go — FocusTimer. 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-158 — case "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 :
-
Notifications :
ExecNotifierappellenotify-send --urgency=criticalsur la seule transition pertinente (Working -> Needs Input). Les 4 scenarios de notification (normal, idle->needsinput, focus actif, focus expire) sont couverts par des tests avecspyNotifier. -
Mode focus :
FocusTimerthread-safe avec Set/IsActive/Remaining. CLIvmux focus <minutes>fonctionne de bout en bout via le daemon. Le focus bloque les notifications mais pas l'i3bar (D-05 respecte). -
Widget i3bar :
formatI3BarBlocksproduit le format compactvmux: auth[!] portal[W]avec les bonnes couleurs.runI3Barimplemente 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)