# Spike S5 — Extension VSCode (intégration native) — ÉTUDE : ✅ GO (phasé)

> **✅ IMPLÉMENTÉ** dans `packages/vscode` (`git-arboretum`, privé) — phases A→D livrées : connexion +
> auth SecretStorage, arbres temps réel (Repos/Groups), terminaux natifs `Pseudoterminal`, status bar +
> notifications `waiting` (commande `answer`), mutations git, conscience du workspace. Bundle esbuild
> (shared inliné), packagé en VSIX (`npm run build:vscode` puis `vsce package --no-dependencies`).
> CI : `.gitea/workflows/vscode-release.yml` sur tag `vscode-vX.Y.Z`. L'étude ci-dessous reste la
> justification de conception.


Étude de conception (pas de mesure Go/No-Go : c'est un design + plan d'implémentation phasé). Objectif
validé avec l'utilisateur : **une vraie intégration native dans VSCode, pas un simple webview** — une
connexion réelle avec ce qui se passe dans l'éditeur (terminaux natifs, arbre, statut, notifications,
conscience du workspace).

## Contexte & contrainte

Arboretum est déjà un daemon qui sert une SPA et expose :
- une **API REST** (`/api/v1/...`) : repos, worktrees (+ mutations git commit/push/promote), sessions,
  groupes, auth ;
- un **protocole WebSocket** multiplexé (`@arboretum/shared` → `protocol.ts`) : attach/stdin/resize,
  frames binaires `[type u8][channel u32le][payload]`, flow-control par watermarks (`FLOW`), events
  temps réel `sessions`/`worktrees`/`groups`, commande `answer` (dialogues), `hello`/`hello_ok`.

Un plugin n'a donc **rien à réimplémenter côté logique** : il est un **client** de cette API. La question
n'est pas « comment afficher le dashboard » mais « comment exposer Arboretum avec les primitives natives
de VSCode ». Le webview (iframe du dashboard) reste un *fallback* optionnel ; ce n'est pas le cœur.

## Pourquoi pas « juste un webview »

- Un webview = iframe vers `http://127.0.0.1:7317` : lourd, isolé (CSP stricte, `acquireVsCodeApi`
  indisponible dans l'iframe), pas d'intégration avec les terminaux/arbres/statut de VSCode, auth à
  re-bricoler (cookie/token dans une iframe cross-origin). On retrouve les bugs xterm-in-webview
  (rendu, scrollback) qu'on cherche justement à éviter.
- Une intégration native réutilise le **rendu terminal, le scrollback, le copier/coller, les liens** de
  VSCode (gratuitement robustes), et place Arboretum là où l'utilisateur travaille déjà.

## Architecture proposée — `packages/vscode`

Nouveau workspace privé `@arboretum/vscode`, extension TypeScript, packagée en **VSIX** via `vsce`
(build `esbuild`). Le `@arboretum/shared` est résolu en dev par le symlink workspace et **inliné** au
packaging (même principe que `scripts/inline-shared.mjs` côté serveur) → VSIX autonome.

### Connexion au daemon
- Réglages : `arboretum.url` (défaut `http://127.0.0.1:7317`), `arboretum.token`.
- **Auth** : commande `Arboretum: Sign in` qui demande le token et le stocke dans **VS Code
  SecretStorage** (les tokens daemon sont stockés *hashés* et le bootstrap ne s'affiche qu'une fois →
  impossible de « lire » le token existant ; on le saisit une fois). Option avancée : commande qui
  **spawn** le daemon (`npx @johanleroy/git-arboretum`) et capture le bootstrap token au premier
  démarrage.
- Le check Origin strict du daemon ne s'applique qu'aux navigateurs (en-tête `Origin`) : un client
  Node/extension n'envoie pas d'`Origin` → OK ; l'auth par token (en-tête/cookie) reste requise.

### Réutilisation du protocole (le « vrai » lien)
Importer `@arboretum/shared` : `decodeBinaryFrame`/encodage, `BINARY_FRAME`, `FLOW`, `PROTOCOL_VERSION`,
types de messages et `SessionSummary`/`WorktreeSummary`/`GroupSummary`. Le pont terminal et la liste
restent **synchronisés** avec le serveur par construction.

### Surfaces natives

1. **Activity Bar + TreeView(s)** (`vscode.window.createTreeView`) : arbre **Repos → Worktrees →
   Sessions**, avec badges d'état fins (`activity` busy/waiting/idle, `dialog`) déjà portés par
   `SessionSummary`. Une vue **Groupes** en parallèle. Rafraîchi en temps réel par les events WS
   (`onDidChangeTreeData`).

2. **Terminaux VSCode natifs via `Pseudoterminal`** *(pièce maîtresse)* :
   `vscode.window.createTerminal({ name, pty })` où le `Pseudoterminal` ponte la session Arboretum :
   - `open()` → `wsClient.attach(sessionId)` ;
   - OUTPUT WS (frames binaires) → `writeEmitter.fire(text)` (`onDidWrite`) ;
   - `handleInput(data)` → WS `stdin` ;
   - `setDimensions({columns, rows})` → WS `resize` ;
   - `close()` → `detach`.
   On réutilise le **renderer + scrollback natifs de VSCode** : règle au passage, côté VSCode, les
   problèmes de rendu et d'historique de la SPA. Flow-control : réutiliser `FLOW`/les ACK du protocole
   (envoyer un ACK des octets écrits) pour ne pas saturer.

3. **Status bar** (`createStatusBarItem`) : compteur des sessions `waiting` (à traiter) ; clic → focus
   de l'arbre / quick-pick des sessions en attente.

4. **Notifications natives** : sur transition d'une session vers `waiting` (event WS), `showInformation
   Message` avec actions (« Ouvrir le terminal », « Oui »/« Non » → commande WS `answer`). Doublonne
   utilement le Web Push : ici, natif dans l'éditeur.

5. **Conscience du workspace** : mapper `workspace.workspaceFolders` → repo/worktree Arboretum (par
   chemin). Actions contextuelles : « Démarrer une session Claude ici », « Créer un worktree pour ce
   repo », et les mutations git existantes (commit/push/promote via REST). Met aussi en évidence dans
   l'arbre le worktree correspondant au dossier ouvert.

6. **Commandes** (`contributes.commands` + palette VSCode) : sign in, ouvrir le dashboard (webview
   *optionnel*), rafraîchir, attacher/observer une session, créer worktree, commit/push/promote,
   start/hide session, répondre à un dialogue.

7. **Webview** : seulement en *option* (vue dashboard complète pour qui la veut). UX primaire = native.

## Découpage phasé (livrable séparé — non implémenté dans ce lot)

- **A — Lecture & connexion** : auth (SecretStorage) + client REST/WS + TreeView lecture seule
  (repos/worktrees/sessions/groupes) en temps réel. *Valeur immédiate, risque faible.*
- **B — Terminaux natifs** : `Pseudoterminal` attach/observe via pont WS réutilisant `@arboretum/shared`
  (flow-control inclus). *Le cœur de la valeur ; à faire juste après A.*
- **C — Actions & supervision** : mutations (créer worktree, commit/push/promote, start/hide), status
  bar `waiting`, notifications + commande `answer`.
- **D — Workspace-aware** : mapping dossier ↔ repo/worktree + actions contextuelles.

## Intégration monorepo & packaging

- `packages/vscode/` : `package.json` d'extension (`engines.vscode`, `activationEvents`,
  `contributes.{commands,views,viewsContainers,configuration}`), build `esbuild` (bundle Node), test via
  `@vscode/test-electron` (optionnel). Publication : VSIX (`vsce package`) — le registre privé Gitea ne
  sert pas d'extensions VSCode, donc distribution par VSIX (et/ou Open VSX) plutôt que le Marketplace si
  l'on veut rester privé.
- Le `tsconfig` reste hors du `tsc -b` server/shared actuel (build séparé) pour ne pas alourdir le
  typecheck CI existant.

## Risques / questions ouvertes

- **Auth bootstrap** : saisie manuelle du token vs spawn+capture. MVP = saisie manuelle (SecretStorage).
- **Flow-control côté extension** : reprendre `FLOW` (ACK par octets) pour les terminaux natifs ; un
  `Pseudoterminal` n'expose pas de back-pressure → ACK « ce qui a été émis dans `onDidWrite` ».
- **Remote/SSH/Codespaces** : si l'on veut le webview fallback, prévoir `vscode.env.asExternalUri` +
  `portMapping`. Les surfaces natives (REST/WS via `arboretum.url`) restent valides tant que le daemon
  est joignable depuis l'hôte de l'extension.
- **Multi-fenêtres VSCode** : une connexion WS par fenêtre (acceptable, outil mono-utilisateur).

## Verdict

**GO** sur une extension native `packages/vscode`, en commençant par **A → B** (TreeView temps réel +
terminaux natifs `Pseudoterminal`), qui apportent l'essentiel de la valeur et réutilisent directement
l'API REST + le protocole WS de `@arboretum/shared`. Le webview n'est qu'un fallback optionnel.
Références API : Webview, Tree View, Pseudoterminal/`createTerminal`, StatusBarItem, SecretStorage,
`asExternalUri` (docs officielles VSCode).
