# 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).