--- phase: 01-session-discovery plan: 01 type: execute wave: 1 depends_on: [] files_modified: - shell.nix - go.mod - types.go - proc.go - proc_test.go autonomous: true requirements: - DISC-01 - DISC-02 must_haves: truths: - "vmux detecte les processus Claude Code actifs via /proc" - "vmux lit le cwd de chaque processus via /proc/PID/cwd" - "vmux encode le cwd en nom de dossier ~/.claude/projects/" artifacts: - path: "shell.nix" provides: "Environnement de dev NixOS avec Go" contains: "go" - path: "go.mod" provides: "Module Go" contains: "module github.com/pieMusic/vmux" - path: "types.go" provides: "Types partages (Process, Session, SessionState)" exports: ["Process", "Session", "SessionState", "Working", "NeedsInput", "Idle"] - path: "proc.go" provides: "Scan /proc pour les processus Claude" exports: ["FindClaudeProcesses", "EncodePath"] - path: "proc_test.go" provides: "Tests unitaires pour proc.go" contains: "TestFindClaudeProcesses" key_links: - from: "proc.go" to: "/proc/*/cmdline" via: "os.ReadFile + strings.Split sur null bytes" pattern: "ReadFile.*cmdline" - from: "proc.go" to: "/proc/*/cwd" via: "os.Readlink" pattern: "Readlink.*cwd" --- Scaffolding du projet Go et detection des processus Claude Code via /proc. Purpose: Poser les fondations (module Go, types, environnement NixOS) et implementer la brique de base : trouver les processus Claude actifs avec leur cwd. Output: Un module Go fonctionnel avec `FindClaudeProcesses()` teste qui retourne les PID + cwd des processus Claude. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-session-discovery/01-CONTEXT.md @.planning/phases/01-session-discovery/01-RESEARCH.md Task 1: Scaffolding projet + types partages shell.nix, go.mod, types.go .planning/phases/01-session-discovery/01-RESEARCH.md Creer 3 fichiers a la racine du projet : **shell.nix** : environnement NixOS avec `go` et `gopls` : ```nix { pkgs ? import {} }: pkgs.mkShell { buildInputs = with pkgs; [ go gopls ]; } ``` **go.mod** : initialiser le module Go : ``` module github.com/pieMusic/vmux go 1.25 ``` **types.go** (package main) : definir les types partages utilises par tous les autres fichiers : ```go package main type SessionState int const ( Working SessionState = iota NeedsInput Idle Unknown ) func (s SessionState) String() string // "Working", "Needs Input", "Idle", "Unknown" type Process struct { PID int Cmd []string // arguments cmdline Cwd string // readlink /proc/PID/cwd } type Session struct { Process Process SessionID string GitBranch string State SessionState Preview string // dernieres lignes de sortie CwdPath string // cwd du processus Worktree string // git worktree (peut differer du cwd) } ``` Le `SessionState` a 4 valeurs : `Working`, `NeedsInput`, `Idle`, `Unknown`. `Unknown` est utilise quand aucun JSONL n'est trouve pour un processus (per D-04, pitfall 4 de la recherche). cd /home/pierre/Code/vibe/vmux && nix-shell --run "go build ./..." - shell.nix contient `go` et `gopls` dans buildInputs - go.mod contient `module github.com/pieMusic/vmux` - types.go contient `type SessionState int` - types.go contient `Working SessionState = iota` - types.go contient `NeedsInput` - types.go contient `Idle` - types.go contient `Unknown` - types.go contient `type Process struct` - types.go contient `type Session struct` - `go build ./...` compile sans erreur Le projet compile. Les types Process, Session et SessionState sont definis et exportes. Task 2: Scan /proc + encoding chemin + tests proc.go, proc_test.go types.go .planning/phases/01-session-discovery/01-RESEARCH.md - TestFindClaudeProcesses: avec un faux /proc contenant 3 repertoires (2 processus "claude", 1 processus "bash"), retourne exactement 2 Process avec les bons PID, Cmd et Cwd. - TestFindClaudeProcesses_PermissionDenied: un /proc/PID/cmdline illisible (permission denied) est ignore silencieusement, pas de crash. - TestFindClaudeProcesses_EmptyProc: un /proc vide retourne un slice vide sans erreur. - TestEncodePath: "/home/pierre/Code/vibe/vmux" -> "-home-pierre-Code-vibe-vmux" - TestEncodePath_DotDir: "/home/pierre/.config/app" -> "-home-pierre--config-app" (les `.` sont remplaces par `-`, d'ou le double dash) **proc.go** (package main) : `FindClaudeProcesses(procDir string) ([]Process, error)` : - Accepte le chemin vers /proc en parametre (permet le test avec un faux /proc). En production, passer "/proc". - Lire `os.ReadDir(procDir)`, filtrer les entrees dont le nom est numerique (PID). - Pour chaque PID, lire `procDir/PID/cmdline` via `os.ReadFile`. Le contenu est separe par des null bytes (`\x00`). Splitter avec `strings.Split(strings.TrimRight(data, "\x00"), "\x00")`. - Si le premier argument (index 0) se termine par `claude` ou est exactement `claude`, c'est un processus Claude Code (per D-01). - Lire le cwd via `os.Readlink(procDir/PID/cwd)` (per D-01). - Ignorer silencieusement les erreurs de lecture (permission denied, processus disparu) : `continue` dans la boucle. - Retourner un `[]Process` avec PID (int parse du nom de dossier), Cmd ([]string des arguments) et Cwd (string du readlink). `EncodePath(path string) string` : - Remplacer tous les `/` par `-` et tous les `.` par `-` (per RESEARCH Pattern 2, pitfall 6). - Utiliser `strings.NewReplacer("/", "-", ".", "-").Replace(path)`. **proc_test.go** (package main) : Utiliser des fixtures temporaires pour simuler /proc (per strategie TDD de la recherche) : - `createFakeProc(t *testing.T, entries map[int]fakeProcEntry) string` : cree un repertoire temporaire avec la structure /proc simulee. - `fakeProcEntry` : struct avec `cmdline string` (contenu brut avec \x00) et `cwd string` (chemin cible du symlink). - Creer des symlinks pour `cwd` (`os.Symlink`). - Creer des fichiers pour `cmdline` (`os.WriteFile`). 5 tests decrits dans la section behavior. cd /home/pierre/Code/vibe/vmux && nix-shell --run "go test -v -run 'TestFindClaudeProcesses|TestEncodePath' ./..." - proc.go contient `func FindClaudeProcesses(procDir string) ([]Process, error)` - proc.go contient `func EncodePath(path string) string` - proc_test.go contient `TestFindClaudeProcesses` qui cree un faux /proc - proc_test.go contient `TestEncodePath` - proc_test.go contient `TestEncodePath_DotDir` - Tous les tests passent avec `go test -v -run 'TestFindClaudeProcesses|TestEncodePath' ./...` - FindClaudeProcesses accepte un parametre procDir (pas de /proc en dur) FindClaudeProcesses detecte les processus Claude dans un faux /proc. EncodePath convertit correctement les chemins. Tous les tests passent. - `go build ./...` compile sans erreur - `go test -v ./...` : tous les tests passent - `go vet ./...` : pas de warning - Le projet Go est initialise avec shell.nix et go.mod - Les types Process, Session, SessionState sont definis - FindClaudeProcesses retourne les processus Claude depuis /proc - EncodePath encode les chemins en noms de dossiers ~/.claude/projects/ - Tests unitaires couvrent les cas normaux et les cas limites After completion, create `.planning/phases/01-session-discovery/01-01-SUMMARY.md`