docs(01-session-discovery): create phase plan
This commit is contained in:
223
.planning/phases/01-session-discovery/01-01-PLAN.md
Normal file
223
.planning/phases/01-session-discovery/01-01-PLAN.md
Normal file
@@ -0,0 +1,223 @@
|
||||
---
|
||||
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"
|
||||
---
|
||||
|
||||
<objective>
|
||||
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.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.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
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Scaffolding projet + types partages</name>
|
||||
<files>shell.nix, go.mod, types.go</files>
|
||||
<read_first>
|
||||
.planning/phases/01-session-discovery/01-RESEARCH.md
|
||||
</read_first>
|
||||
<action>
|
||||
Creer 3 fichiers a la racine du projet :
|
||||
|
||||
**shell.nix** : environnement NixOS avec `go` et `gopls` :
|
||||
```nix
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
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).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/pierre/Code/vibe/vmux && nix-shell --run "go build ./..."</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 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
|
||||
</acceptance_criteria>
|
||||
<done>Le projet compile. Les types Process, Session et SessionState sont definis et exportes.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 2: Scan /proc + encoding chemin + tests</name>
|
||||
<files>proc.go, proc_test.go</files>
|
||||
<read_first>
|
||||
types.go
|
||||
.planning/phases/01-session-discovery/01-RESEARCH.md
|
||||
</read_first>
|
||||
<behavior>
|
||||
- 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)
|
||||
</behavior>
|
||||
<action>
|
||||
**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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/pierre/Code/vibe/vmux && nix-shell --run "go test -v -run 'TestFindClaudeProcesses|TestEncodePath' ./..."</automated>
|
||||
</verify>
|
||||
<acceptance_criteria>
|
||||
- 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)
|
||||
</acceptance_criteria>
|
||||
<done>FindClaudeProcesses detecte les processus Claude dans un faux /proc. EncodePath convertit correctement les chemins. Tous les tests passent.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `go build ./...` compile sans erreur
|
||||
- `go test -v ./...` : tous les tests passent
|
||||
- `go vet ./...` : pas de warning
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 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
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/01-session-discovery/01-01-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user