docs(01): research phase session discovery
This commit is contained in:
377
.planning/phases/01-session-discovery/01-RESEARCH.md
Normal file
377
.planning/phases/01-session-discovery/01-RESEARCH.md
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
# Phase 1: Session Discovery - Research
|
||||||
|
|
||||||
|
**Researched:** 2026-03-23
|
||||||
|
**Domain:** Linux process inspection + Claude Code JSONL parsing
|
||||||
|
**Confidence:** HIGH
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
La Phase 1 est un CLI one-shot (`vmux list`) qui scanne les processus Claude Code actifs via `/proc`, croise les PID avec les fichiers JSONL dans `~/.claude/projects/`, et affiche l'etat de chaque session.
|
||||||
|
|
||||||
|
Le format JSONL de Claude Code est bien documente et stable. Chaque message contient des metadonnees riches (sessionId, cwd, gitBranch, version). L'heuristique d'etat se base sur le `stop_reason` du dernier message `assistant` et le nom de l'outil si `stop_reason=tool_use`.
|
||||||
|
|
||||||
|
**Decouverte critique :** `sessions-index.json` n'est plus genere par les versions recentes de Claude Code (derniere MAJ: 2026-02-03). Seulement 13 des 91 dossiers projets en ont un. Il faut lire les metadonnees directement depuis le JSONL (chaque entree contient `sessionId`, `cwd`, `gitBranch`, `version`).
|
||||||
|
|
||||||
|
**Recommandation principale :** Ne pas dependre de `sessions-index.json`. Parser la premiere et la derniere entree du JSONL pour obtenir toutes les informations necessaires.
|
||||||
|
|
||||||
|
<user_constraints>
|
||||||
|
## User Constraints (from CONTEXT.md)
|
||||||
|
|
||||||
|
### Locked Decisions
|
||||||
|
- **D-01:** Scanner `/proc` pour trouver les PID des processus Claude Code actifs, puis enrichir avec les fichiers JSONL dans `~/.claude/projects/`. Un JSONL sans PID correspondant = session terminee, ignoree.
|
||||||
|
- **D-02:** Utiliser `sessions-index.json` (present dans chaque dossier projet sous `~/.claude/projects/`) comme source de metadonnees riches (sessionId, gitBranch, projectPath, summary, created, modified). Format verifie sur le poste.
|
||||||
|
- **D-03:** Le matching PID -> session se fait via le cwd du processus (`/proc/PID/cwd` -> readlink) croise avec le `projectPath` du sessions-index.
|
||||||
|
- **D-04:** Se baser uniquement sur le JSONL (tail-read de la derniere entree) pour determiner l'etat. Pas de lecture CPU en Phase 1.
|
||||||
|
- **D-05:** Heuristique d'etat basee sur le dernier message JSONL (voir details dans CONTEXT.md).
|
||||||
|
- **D-06:** Les JSONL peuvent faire > 100 Mo. Toujours tail-read, jamais charger le fichier entier.
|
||||||
|
- **D-07:** Couleurs activees par defaut pour l'etat (vert = Working, rouge/jaune = Needs Input, gris = Idle).
|
||||||
|
|
||||||
|
### Claude's Discretion
|
||||||
|
- Format d'affichage : tableau compact ou blocs detailles, libre de proposer un format hybride.
|
||||||
|
- Gestion du `--no-color` pour la compatibilite pipe.
|
||||||
|
|
||||||
|
### Deferred Ideas (OUT OF SCOPE)
|
||||||
|
None
|
||||||
|
</user_constraints>
|
||||||
|
|
||||||
|
<phase_requirements>
|
||||||
|
## Phase Requirements
|
||||||
|
|
||||||
|
| ID | Description | Research Support |
|
||||||
|
|----|-------------|------------------|
|
||||||
|
| DISC-01 | vmux detecte automatiquement les processus Claude Code actifs sur le poste | Scan `/proc/*/cmdline` pour trouver les processus `claude`. Verifie: 6 processus actifs trouves. |
|
||||||
|
| DISC-02 | vmux identifie le cwd et le worktree git de chaque session | `readlink /proc/PID/cwd` donne le cwd. Worktree git via `git rev-parse --show-toplevel` ou parsing `.git`. |
|
||||||
|
| DISC-03 | vmux affiche le nom de la branche git de chaque session | Champ `gitBranch` present dans chaque entree JSONL. Alternative: `git -C <cwd> branch --show-current`. |
|
||||||
|
| STATE-01 | vmux detecte l'etat de chaque session : travaille / attend input / idle | Heuristique basee sur `stop_reason` + `content[].type` du dernier message assistant. Voir section "Architecture Patterns". |
|
||||||
|
| STATE-02 | vmux affiche un apercu des dernieres lignes de sortie de chaque session | Champ `content[].text` du dernier message assistant type `text`. Aussi `summary` dans sessions-index.json quand disponible. |
|
||||||
|
</phase_requirements>
|
||||||
|
|
||||||
|
## Standard Stack
|
||||||
|
|
||||||
|
### Core
|
||||||
|
| Library | Version | Purpose | Why Standard |
|
||||||
|
|---------|---------|---------|--------------|
|
||||||
|
| Go | 1.25.7 | Langage | Deja utilise par piaire. Disponible via `nix-shell -p go`. |
|
||||||
|
| Go stdlib (os, encoding/json, path/filepath, fmt) | - | Tout le runtime | Aucune dependance externe necessaire pour Phase 1. /proc se lit avec os.ReadFile/os.Readlink. |
|
||||||
|
|
||||||
|
### Supporting
|
||||||
|
| Library | Version | Purpose | When to Use |
|
||||||
|
|---------|---------|---------|-------------|
|
||||||
|
| Aucune | - | - | Phase 1 = stdlib uniquement. Pas de CLI framework, pas de TUI, pas de deps. |
|
||||||
|
|
||||||
|
### Alternatives Considered
|
||||||
|
| Instead of | Could Use | Tradeoff |
|
||||||
|
|------------|-----------|----------|
|
||||||
|
| stdlib os pour /proc | prometheus/procfs | Over-engineered pour lire cmdline + cwd. API instable (WARNING dans leur doc). |
|
||||||
|
| stdlib flag | cobra/urfave | Over-engineered pour une seule commande `list`. flag suffit. |
|
||||||
|
| Reverse-read maison | hpcloud/tail | tail est pour le mode follow (Phase 2+). Pour un one-shot, un seek+read depuis la fin suffit. |
|
||||||
|
|
||||||
|
**Installation:**
|
||||||
|
```bash
|
||||||
|
# Rien a installer. Go stdlib uniquement.
|
||||||
|
nix-shell -p go --run "go mod init github.com/pieMusic/vmux"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture Patterns
|
||||||
|
|
||||||
|
### Recommended Project Structure
|
||||||
|
```
|
||||||
|
vmux/
|
||||||
|
├── main.go # Point d'entree, parsing des args
|
||||||
|
├── proc.go # Scan /proc pour les processus Claude
|
||||||
|
├── proc_test.go
|
||||||
|
├── session.go # Lecture JSONL + matching PID->session
|
||||||
|
├── session_test.go
|
||||||
|
├── state.go # Heuristique d'etat (Working/NeedsInput/Idle)
|
||||||
|
├── state_test.go
|
||||||
|
├── display.go # Formatage et affichage (couleurs, layout)
|
||||||
|
├── display_test.go
|
||||||
|
├── go.mod
|
||||||
|
└── shell.nix # Environnement de dev NixOS
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 1: Scan /proc pour les processus Claude
|
||||||
|
**What:** Lister tous les PID dont `/proc/PID/cmdline` contient `claude`.
|
||||||
|
**When to use:** Au demarrage de `vmux list`.
|
||||||
|
**Verification sur machine:** Les processus Claude Code apparaissent comme `claude` ou `claude -c` dans cmdline.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Verifie sur la machine : /proc/PID/cmdline contient "claude\x00" ou "claude\x00-c\x00"
|
||||||
|
func findClaudeProcesses() ([]Process, error) {
|
||||||
|
entries, err := os.ReadDir("/proc")
|
||||||
|
// Pour chaque entree numerique, lire /proc/PID/cmdline
|
||||||
|
// Si le premier argument est "claude", c'est un processus Claude Code
|
||||||
|
// Lire aussi /proc/PID/cwd via os.Readlink pour obtenir le cwd
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Encoding du chemin projet
|
||||||
|
**What:** Convertir un cwd en nom de dossier `~/.claude/projects/`.
|
||||||
|
**Verification:** `/home/pierre/Code/vibe/vmux` -> `-home-pierre-Code-vibe-vmux`. Les `/` et `.` sont remplaces par `-`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func encodePath(cwd string) string {
|
||||||
|
// Remplacer / et . par -
|
||||||
|
result := strings.ReplaceAll(cwd, "/", "-")
|
||||||
|
result = strings.ReplaceAll(result, ".", "-")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 3: Tail-read JSONL (lecture depuis la fin)
|
||||||
|
**What:** Lire les N dernieres lignes d'un JSONL sans charger le fichier entier.
|
||||||
|
**When to use:** Pour chaque session, lire la derniere entree pour determiner l'etat.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func tailReadJSONL(path string, n int) ([]json.RawMessage, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
// Seek vers la fin du fichier
|
||||||
|
// Lire des blocs de ~8KB en arriere jusqu'a trouver n lignes completes
|
||||||
|
// Parser chaque ligne comme JSON
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 4: Heuristique d'etat
|
||||||
|
**What:** Determiner l'etat d'une session a partir du dernier message JSONL.
|
||||||
|
**Verification sur machine (resultats reels) :**
|
||||||
|
|
||||||
|
| Dernier message | stop_reason | content_types | Etat |
|
||||||
|
|-----------------|-------------|---------------|------|
|
||||||
|
| `type=assistant` | `end_turn` | `['text']` | **Needs Input** (Claude a fini, attend l'utilisateur) |
|
||||||
|
| `type=assistant` | `tool_use` | `['tool_use']` avec `name=AskUserQuestion` | **Needs Input** (Claude pose une question) |
|
||||||
|
| `type=assistant` | `tool_use` | `['tool_use']` avec autre outil | **Working** (outil en cours d'execution) |
|
||||||
|
| `type=progress` | - | `data.type=agent_progress` | **Working** (subagent actif) |
|
||||||
|
| `type=progress` | - | `data.type=hook_progress` | **Working** (hook en cours) |
|
||||||
|
| `type=user` avec `content[].type=tool_result` | - | - | **Working** (resultat de tool envoye, Claude va repondre) |
|
||||||
|
| Aucun message recent (> seuil) | - | - | **Idle** |
|
||||||
|
|
||||||
|
**Important :** le `stop_reason` est dans `message.stop_reason`, pas au top-level.
|
||||||
|
|
||||||
|
### Pattern 5: Matching PID -> JSONL (REVISE par la recherche)
|
||||||
|
**What:** Trouver le bon JSONL pour un PID donne.
|
||||||
|
**Algorithme revise :**
|
||||||
|
1. Lire le cwd du PID via `readlink /proc/PID/cwd`
|
||||||
|
2. Encoder le cwd pour obtenir le nom du dossier dans `~/.claude/projects/`
|
||||||
|
3. Lister les fichiers `.jsonl` dans ce dossier (exclure le sous-dossier `subagents/`)
|
||||||
|
4. Prendre le fichier JSONL le plus recemment modifie (= session active)
|
||||||
|
5. **NE PAS dependre de `sessions-index.json`** (absent dans 85% des projets recents)
|
||||||
|
|
||||||
|
### Anti-Patterns to Avoid
|
||||||
|
- **Charger un JSONL entier en memoire :** Les fichiers peuvent depasser 100 Mo. Toujours tail-read.
|
||||||
|
- **Dependre de sessions-index.json :** Obsolete depuis ~fev 2026. Seulement 13/91 projets en ont un.
|
||||||
|
- **Utiliser `ps aux` via exec :** Lire `/proc` directement est plus fiable et ne depend pas du format de sortie de `ps`.
|
||||||
|
- **Ignorer les subagents :** Le dossier `<session-uuid>/subagents/` contient des JSONL de sous-agents. Ne pas les confondre avec les sessions principales.
|
||||||
|
|
||||||
|
## Don't Hand-Roll
|
||||||
|
|
||||||
|
| Problem | Don't Build | Use Instead | Why |
|
||||||
|
|---------|-------------|-------------|-----|
|
||||||
|
| Parsing des args CLI | Framework CLI (cobra, urfave) | `flag` stdlib | Une seule commande, pas besoin de framework |
|
||||||
|
| Couleurs terminal | Lib de couleurs (fatih/color) | Codes ANSI directs | 5 couleurs max, pas besoin d'une dependance |
|
||||||
|
| Lecture /proc | Lib procfs | `os.ReadFile` + `os.Readlink` | 3 fichiers a lire par PID, trivial |
|
||||||
|
|
||||||
|
**Insight :** Phase 1 est volontairement zero-dependency. La complexite est dans la logique metier (heuristique d'etat, tail-read), pas dans les outils.
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
|
||||||
|
### Pitfall 1: sessions-index.json absent
|
||||||
|
**What goes wrong:** Le code essaie de lire sessions-index.json et echoue silencieusement, pas de metadonnees.
|
||||||
|
**Why it happens:** Claude Code ne genere plus ce fichier depuis ~fevrier 2026.
|
||||||
|
**How to avoid:** Lire les metadonnees directement depuis les entrees JSONL (chaque entree contient sessionId, cwd, gitBranch, version).
|
||||||
|
**Warning signs:** 85% des projets recents n'ont pas de sessions-index.json.
|
||||||
|
|
||||||
|
### Pitfall 2: JSONL > 100 Mo charge en memoire
|
||||||
|
**What goes wrong:** OOM ou lenteur extreme pour une commande one-shot.
|
||||||
|
**Why it happens:** Les sessions longues generent des JSONL volumineux (max observe: 23 Mo pour un subagent).
|
||||||
|
**How to avoid:** Tail-read : `Seek(0, io.SeekEnd)` puis lire en arriere par blocs de 8-16 Ko.
|
||||||
|
**Warning signs:** Temps de reponse > 1s pour `vmux list`.
|
||||||
|
|
||||||
|
### Pitfall 3: Race condition sur le JSONL
|
||||||
|
**What goes wrong:** Le JSONL est en cours d'ecriture par Claude Code pendant la lecture.
|
||||||
|
**Why it happens:** Fichier append-only, ecriture concurrente.
|
||||||
|
**How to avoid:** Lire la derniere ligne **complete** (terminee par `\n`). Ignorer une derniere ligne tronquee.
|
||||||
|
**Warning signs:** Erreur JSON parse sur la derniere ligne.
|
||||||
|
|
||||||
|
### Pitfall 4: Processus Claude != session active
|
||||||
|
**What goes wrong:** Un PID Claude existe mais aucun JSONL recent ne correspond.
|
||||||
|
**Why it happens:** Claude Code peut etre en phase de demarrage, ou le dossier projet n'existe pas encore.
|
||||||
|
**How to avoid:** Afficher le processus avec un etat "Unknown" si aucun JSONL n'est trouve.
|
||||||
|
**Warning signs:** PID sans dossier encode correspondant dans `~/.claude/projects/`.
|
||||||
|
|
||||||
|
### Pitfall 5: Confusion subagent / session principale
|
||||||
|
**What goes wrong:** Des JSONL de subagents sont affiches comme des sessions separees.
|
||||||
|
**Why it happens:** Structure `<uuid>/subagents/agent-*.jsonl` dans le dossier projet.
|
||||||
|
**How to avoid:** Ne lister que les `*.jsonl` directement dans le dossier projet, pas dans les sous-dossiers.
|
||||||
|
**Warning signs:** Sessions fantomes qui apparaissent et disparaissent.
|
||||||
|
|
||||||
|
### Pitfall 6: Double-dash dans l'encoding des chemins avec des points
|
||||||
|
**What goes wrong:** `/home/user/.config` s'encode en `-home-user--config` (double dash). Le code d'encoding rate la correspondance.
|
||||||
|
**Why it happens:** Les `.` sont remplaces par `-`, ce qui cree un `--` quand un dossier commence par `.`.
|
||||||
|
**How to avoid:** L'encoding est simple : remplacer `/` ET `.` par `-`. Verifie sur la machine.
|
||||||
|
|
||||||
|
## Code Examples
|
||||||
|
|
||||||
|
### Lecture de /proc/PID/cmdline
|
||||||
|
```go
|
||||||
|
// Source: verification directe sur /proc/13736/cmdline
|
||||||
|
func readCmdline(pid int) ([]string, error) {
|
||||||
|
data, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", pid))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// cmdline est separe par des null bytes
|
||||||
|
parts := strings.Split(strings.TrimRight(string(data), "\x00"), "\x00")
|
||||||
|
return parts, nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure d'un message JSONL assistant
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"parentUuid": "...",
|
||||||
|
"isSidechain": false,
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"content": [
|
||||||
|
{"type": "text", "text": "..."},
|
||||||
|
{"type": "tool_use", "name": "Read", "id": "toolu_..."}
|
||||||
|
],
|
||||||
|
"stop_reason": "tool_use"
|
||||||
|
},
|
||||||
|
"type": "assistant",
|
||||||
|
"uuid": "...",
|
||||||
|
"timestamp": "2026-03-23T11:38:18.236Z",
|
||||||
|
"cwd": "/home/pierre/Code/vibe/vmux",
|
||||||
|
"sessionId": "3a0e1bbb-...",
|
||||||
|
"version": "2.1.81",
|
||||||
|
"gitBranch": "HEAD"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure d'un message progress (subagent)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "progress",
|
||||||
|
"data": {"type": "agent_progress"},
|
||||||
|
"timestamp": "2026-03-23T12:00:43.006Z",
|
||||||
|
"sessionId": "...",
|
||||||
|
"cwd": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure d'un message progress (hook)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "progress",
|
||||||
|
"data": {"type": "hook_progress", "hookEvent": "...", "hookName": "..."},
|
||||||
|
"timestamp": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure d'un message system (fin de tour)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "system",
|
||||||
|
"subtype": "turn_duration",
|
||||||
|
"durationMs": 82049,
|
||||||
|
"timestamp": "...",
|
||||||
|
"sessionId": "...",
|
||||||
|
"cwd": "...",
|
||||||
|
"gitBranch": "HEAD"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## State of the Art
|
||||||
|
|
||||||
|
| Old Approach | Current Approach | When Changed | Impact |
|
||||||
|
|--------------|------------------|--------------|--------|
|
||||||
|
| `sessions-index.json` pour les metadonnees | Metadonnees dans chaque entree JSONL | ~fev 2026 | Ne plus dependre de sessions-index.json |
|
||||||
|
| Claude Code v2.0.x | Claude Code v2.1.81 | mars 2026 | Champ `slug` ajoute, `agent_progress` pour les subagents |
|
||||||
|
|
||||||
|
## Validation Architecture
|
||||||
|
|
||||||
|
### Test Framework
|
||||||
|
| Property | Value |
|
||||||
|
|----------|-------|
|
||||||
|
| Framework | Go testing (stdlib) |
|
||||||
|
| Config file | Aucun (convention Go par defaut) |
|
||||||
|
| Quick run command | `go test ./...` |
|
||||||
|
| Full suite command | `go test -v -race ./...` |
|
||||||
|
|
||||||
|
### Phase Requirements -> Test Map
|
||||||
|
| Req ID | Behavior | Test Type | Automated Command | File Exists? |
|
||||||
|
|--------|----------|-----------|-------------------|-------------|
|
||||||
|
| DISC-01 | Detecter les processus Claude actifs | unit | `go test -run TestFindClaudeProcesses -v` | Wave 0 |
|
||||||
|
| DISC-02 | Identifier cwd et worktree git | unit | `go test -run TestProcessCwd -v` | Wave 0 |
|
||||||
|
| DISC-03 | Afficher la branche git | unit | `go test -run TestGitBranch -v` | Wave 0 |
|
||||||
|
| STATE-01 | Detecter l'etat (Working/NeedsInput/Idle) | unit | `go test -run TestDetectState -v` | Wave 0 |
|
||||||
|
| STATE-02 | Afficher un apercu de la sortie | unit | `go test -run TestExtractPreview -v` | Wave 0 |
|
||||||
|
|
||||||
|
### Sampling Rate
|
||||||
|
- **Per task commit:** `go test ./...`
|
||||||
|
- **Per wave merge:** `go test -v -race ./...`
|
||||||
|
- **Phase gate:** Full suite green before `/gsd:verify-work`
|
||||||
|
|
||||||
|
### Wave 0 Gaps
|
||||||
|
- [ ] `proc_test.go` -- couvre DISC-01, DISC-02 (testable avec des fixtures /proc simulees)
|
||||||
|
- [ ] `session_test.go` -- couvre DISC-03, STATE-02 (fixtures JSONL)
|
||||||
|
- [ ] `state_test.go` -- couvre STATE-01 (fixtures JSONL avec differents patterns)
|
||||||
|
- [ ] `display_test.go` -- couvre le formatage de sortie
|
||||||
|
- [ ] `go.mod` + `shell.nix` -- infrastructure de base
|
||||||
|
|
||||||
|
### Strategy TDD
|
||||||
|
Les tests pour `/proc` et JSONL doivent utiliser des fixtures (fichiers temporaires) plutot que de lire le vrai `/proc`. Cela permet :
|
||||||
|
- Executer les tests en CI sans processus Claude actifs
|
||||||
|
- Tester les cas limites (JSONL corrompu, processus zombie, etc.)
|
||||||
|
- Reproductibilite totale
|
||||||
|
|
||||||
|
## Environment Availability
|
||||||
|
|
||||||
|
| Dependency | Required By | Available | Version | Fallback |
|
||||||
|
|------------|------------|-----------|---------|----------|
|
||||||
|
| Go | Build & run | oui | 1.25.7 (via nix-shell) | - |
|
||||||
|
| /proc filesystem | Process detection | oui | procfs Linux 6.19 | - |
|
||||||
|
| git | Branch detection | oui | standard NixOS | Fallback sur gitBranch du JSONL |
|
||||||
|
|
||||||
|
**Missing dependencies with no fallback:** Aucune.
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
1. **Seuil Idle**
|
||||||
|
- Ce qu'on sait : D-05 mentionne "Derniere activite > seuil -> Idle" sans definir le seuil.
|
||||||
|
- Ce qui est flou : 30s ? 60s ? 5min ?
|
||||||
|
- Recommandation : Commencer a 60s. Configurable plus tard. En Phase 1, un const suffit.
|
||||||
|
|
||||||
|
2. **Sessions-index.json obsolete vs D-02**
|
||||||
|
- Ce qu'on sait : D-02 mentionne sessions-index.json comme source. La recherche montre qu'il est absent dans 85% des cas recents.
|
||||||
|
- Ce qui est flou : Faut-il quand meme le lire quand il existe (pour le champ `summary`) ?
|
||||||
|
- Recommandation : Lire sessions-index.json en bonus si present (pour `summary`), mais ne JAMAIS en dependre. Le JSONL est la source primaire.
|
||||||
|
|
||||||
|
3. **Multiple sessions par cwd**
|
||||||
|
- Ce qu'on sait : Pas observe sur la machine actuelle (6 PID, 6 cwd differents).
|
||||||
|
- Ce qui est flou : Est-ce possible d'avoir 2 processus Claude dans le meme repertoire ?
|
||||||
|
- Recommandation : Prendre le JSONL le plus recemment modifie. Si 2 PID partagent le meme cwd, afficher 2 sessions separees pointant vers les memes JSONL (cas rare, accepter l'imprecision en v1).
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
### Primary (HIGH confidence)
|
||||||
|
- Inspection directe de `/proc/*/cmdline`, `/proc/*/cwd` sur la machine (6 processus Claude actifs)
|
||||||
|
- Lecture directe de `~/.claude/projects/` : 91 dossiers projets, 13 avec sessions-index.json
|
||||||
|
- Analyse de fichiers JSONL reels (format des messages assistant, user, progress, system)
|
||||||
|
- Structure verifiee : `<uuid>/subagents/agent-*.jsonl` pour les sous-agents
|
||||||
|
|
||||||
|
### Secondary (MEDIUM confidence)
|
||||||
|
- Stack research (CLAUDE.md) : Go 1.25.7 verifie, Bubble Tea v2 pour phases futures
|
||||||
|
|
||||||
|
### Tertiary (LOW confidence)
|
||||||
|
- Encoding exact des chemins (verifie sur ~10 exemples, peut-etre des cas speciaux non couverts avec des caracteres Unicode ou des espaces)
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
**Confidence breakdown:**
|
||||||
|
- Standard stack: HIGH - Go stdlib uniquement, verifie sur machine
|
||||||
|
- Architecture: HIGH - Format JSONL et /proc verifies par inspection directe
|
||||||
|
- Pitfalls: HIGH - sessions-index.json obsolete decouvert par inspection reelle (13/91)
|
||||||
|
|
||||||
|
**Research date:** 2026-03-23
|
||||||
|
**Valid until:** 2026-04-23 (format JSONL stable, /proc stable)
|
||||||
Reference in New Issue
Block a user