- Réglages → Claude CLI : override du chemin du binaire `claude` (effet à la
prochaine session, fallback `which claude`), diagnostic de détection, et
override de la racine ~/.claude (effet au redémarrage). Validateurs stricts.
- Push : notifie aussi sur le front busy→idle (session redevenue disponible).
- Renomme l'état affiché idle → « disponible » / « available » (web EN/FR + VS Code) ;
l'enum SessionActivity du protocole reste inchangé.
- POST /api/v1/projects : crée <root>/<name> (mkdir non récursif, 409 si existant),
git init optionnel, puis lance une session dedans. Anti-traversal sur le nom (core/project.ts).
- Web : NewProjectModal (racine préremplie scanRoots[0], case git init) + bouton dans SessionsListView.
- SessionContextBar : badge du groupe (cliquable) + repos couverts avec leur branche dans l'en-tête
de session ; session simple = repo+branche déduits du cwd.
- 14 tests (unitaires + route).
- Recherche : le watcher débouncé du singleton useWorktreeView est créé dans un effectScope
détaché → ne gèle plus après une navigation ; recherche aussi par label de dépôt ; accès à
la palette depuis le MoreSheet mobile (sidebar/⌘K indisponibles sur mobile).
- Sessions : sessionsForCwd exclut désormais toujours les sessions masquées ; les sessions
externes (discovered) sont masquées par défaut côté UI, avec puce de révélation par carte et
case globale dans le dashboard.
- Terminal : ACK découplé du callback de rendu (armé à la réception + flush au retour de
visibilité) → plus de pause PTY quand l'onglet passe en arrière-plan ; repaint forcé sur
perte de contexte WebGL / resize / retour en avant-plan. Historique élargi : REPLAY_TAIL_BYTES
1 Mo, RING_CAPACITY 4 Mo, scrollback xterm 20k.
- Grille de groupe : bouton « plein écran » sur chaque cellule ouvrant /sessions/:id.
- addWorktree résout la branche par dépôt (branchExists) : checkout si présente, suivi de origin/<b> si seulement remote, sinon création (-b) depuis la branche par défaut. Corrige le 'fatal: invalid reference' sur les groupes hétérogènes ; newBranch -> mode (déprécié, mappé en route).
- Nouvelles opérations git : commit (add -A), push (upstream auto), promotion « en principal » (la branche du worktree devient le checkout principal, sans merge ni conflit, ancienne branche conservée). Routes /worktrees/{commit,push,promote} auditées + GET /repos/:id/branches.
- Web : actions Commit/Push/Promouvoir sur WorktreeCard, sélecteur de branche de base (datalist) dans RepoSection et GroupSessionModal, agrandissement d'un terminal au choix dans TerminalGrid.
- Court-circuite la session de groupe quand aucun worktree n'a pu être créé (fini le masquage par « no resolvable worktree »).
- Tests : git.ts (branchExists/listBranches/commitAll/auto), worktree-manager (commit/promote/branches) ; acceptance P5 étend le scénario worktree de groupe sur branche neuve + commit + promotion.
Masquage persistant des sessions Claude découvertes (lancées hors Arboretum)
qui polluent la liste — calqué sur repos.hidden :
- table hidden_sessions (#9) clé claudeSessionId ; helpers DB
- DiscoveryService pose le champ additif SessionSummary.hidden (resume/fork
restent possibles, survit à un re-scan)
- routes POST/DELETE /sessions/:id/hide, POST /sessions/hide-discovered
(masse, un clic), GET /sessions?includeHidden=true
- UI : bouton Masquer par ligne, « Masquer l'historique externe », toggle
« Afficher les masquées », badge masquée ; store + i18n EN/FR + audit
Terminal plein écran (corrige le sizing) :
- SessionView root s'étire (flex-1) → xterm calcule les bonnes dimensions
- refit robuste (requestAnimationFrame + après resync), h-full sur le wrapper
- bouton plein écran (API Fullscreen), tabbar mobile masquée en fullbleed
DialogPrompt : options en liste verticale pleine largeur (plus de troncature
ni de chevauchement sur les libellés longs / multi-lignes).
Doc : centre d'aide (sessions), README EN/FR, site (showcase), CLAUDE.md.
Tests : discovery (hidden) + route hide/unhide/hide-discovered.
Ajoute le choix « créer un worktree OU bosser sur la branche principale » au
moment de démarrer le travail, sur deux surfaces :
- bouton « Démarrer » (claude/bash) sur chaque WorktreeCard, y compris le
checkout principal (badge « principal ») — comblait un manque : impossible
jusqu'ici de lancer une session sur un worktree existant depuis le dashboard ;
- toggle de mode (Worktree / Branche principale) dans le formulaire d'entête
de RepoSection.
Option git « créer & basculer » : nouvel endpoint POST /api/v1/repos/:id/session
qui lance UNE session dans le checkout principal (repo.path), avec création ou
bascule de branche optionnelle (git switch[-c]) — refusée en 409 si l'arbre est
sale. Pas de hooks ni de pré-trust (c'est le dépôt réel de l'utilisateur).
- shared : type additif StartRepoSessionRequest.
- server : git.switchBranch + WorktreeManager.startMainSession + route.
- web : store worktrees.startMainSession, UI WorktreeCard/RepoSection, i18n fr/en.
- tests : +5 unitaires (switchBranch, startMainSession) ; acceptance-p3 étendue.
Un groupe lance désormais UNE seule session Claude couvrant tous ses
repos/worktrees (--add-dir) au lieu d'une session par repo, pour
travailler en simultané dans une conversation partagée. Le transport WS,
le flow control et l'attach sont inchangés (toujours 1 session, 1 channel).
- shared: SessionSummary.addedDirs/groupId (champs additifs optionnels) ;
CreateGroupSessionRequest / GroupSessionResponse.
- server: --add-dir dans claude-launcher ; spawn({addDirs,groupId}) +
persistance (migration #8 : sessions.added_dirs/group_id) ;
POST /api/v1/groups/:id/session (résolution des dirs cote serveur) ;
resume re-relie les dirs ; deleteGroup nullifie group_id.
- web: GroupSessionModal (modes feature / checkouts principaux) ;
createGroupFeature/createGroupSession ; badge « groupe · N depots » ;
sessionsInGroup dedupliquee.
- site: textes EN/FR « une seule session Claude » + diagramme hub.
- tests: claude-launcher, pty-manager (groupe), group-manager ;
acceptation P5 etendue (session de groupe multi-repo). 272 tests verts.
Gitea
- lien « Code source » hardcodé (REPO_SOURCE_URL) vers le dépôt, toujours visible
- retrait complet du réglage configurable (api.ts, route+store settings, SettingsView, i18n, help, tests)
Découverte des dépôts
- aucune racine de scan par défaut → pas de scan au premier démarrage (clean install)
- corrige la découverte des dépôts à l'INTÉRIEUR d'une racine qui est elle-même un repo
(depth 0 = conteneur de scan, on descend ; depth > 0 = feuille)
Sécurité « enterprise-deployable »
- en-têtes HTTP durcis (CSP, X-Frame-Options, nosniff, Referrer-Policy, HSTS conditionnel, no-store API), header Server retiré
- permissions DB 0o600 / dossier de données 0o700 ; error handler sanitisé ; garde Content-Type sur les mutations
- chiffrement au repos AES-256-GCM des secrets (server_secret, clé privée VAPID) via SecretBox
- journal d'audit (migration #7) + endpoint /audit-logs + RGPD export/effacement + UI Réglages
- SECURITY.md, docs/ENTERPRISE_DEPLOYMENT.md, sections README EN/FR, SBOM CycloneDX en CI
CI
- pack-smoke packe depuis le contexte du package (cd packages/server) au lieu de « npm pack -w » :
corrige l'embarquement de @arboretum/shared dans le tarball
Purge des données personnelles du dépôt public
- suppression de spikes/s4-discovery/result.json, reformulation du VERDICT
- chemin de test générique, anonymisation des 5 fixtures de dialogues
Scan borné du système de fichiers (racines configurables, défaut home ; profondeur/nombre/timeout bornés ; symlinks non suivis ; exclusions node_modules/dotdirs) qui auto-enregistre les nouveaux dépôts. Insertion atomique ON CONFLICT DO NOTHING (idempotence + anti-résurrection d'un dépôt masqué + anti-course). Scan au démarrage + bouton manuel + re-scan périodique (RepoDiscoveryService, démarré dans runDaemon). Colonne repos.hidden : masquer = conservé en DB mais exclu du dashboard et jamais ré-ajouté ; supprimer = re-découvrable. UI : bouton œil par dépôt + bascule afficher-les-masqués sur le dashboard, section Découverte dans les Réglages (racines + intervalle, allow-list stricte). Robustesse : listAllWorktrees tolère l'échec git par dépôt ; flag --no-discover (escape hatch + hermétisme des acceptations).
- PWA: public/manifest.webmanifest + icon.svg + meta index.html (theme-color, apple-touch-icon)
- public/sw.js: service worker push-only (push → showNotification tag=sessionId ;
notificationclick → focus/ouvre /sessions/<id>) — pas de précache (hors périmètre)
- lib/push.ts + stores/push.ts: enable/disable, abonnement VAPID, enregistrement SW au boot
- DashboardView: toggle « Notifications » (gardé par pushSupported) + i18n en/fr
- campagne de fiabilité (verdict S3): classification de tous les types de dialogue sur captures
réelles (trust/permission×2/question) + refus Esc (deny-esc2) + plan (synthétique)
- acceptance-p4.mjs: VAPID/auth/Origin, subscribe idempotent/unsubscribe, answer (rejets)
Choix: SW écrit à la main plutôt que vite-plugin-pwa (qui tirait ~295 paquets Workbox +
2 vulns esbuild high pour un SW push-only). Zéro dépendance front nouvelle. 175 tests verts,
acceptance p1..p4 ALL GREEN.
Fan-out integration + fixes found by the test/acceptance pass:
- FIX ring-buffer: chunks >= capacity skipped bytes now count into the
monotonic offset (invariant: stream byte k lives at k % capacity) —
window order was corrupted on unaligned big chunks
- FIX auth: non-numeric cookie expiry no longer bypasses expiration
- FIX protocol: safe-integer validation on ack.bytes / hello.protocol
- FIX @fastify/websocket v11: websocket route must be registered in an
encapsulated context after plugin load (handler got REST signature)
- FIX flow-control deadlock found by e2e acceptance: client only ACKs
on data receipt, so pausing with an unACKed residue in (LOW,
ACK_EVERY] stalled both sides at 0.9 MB. ACK_EVERY now 64 KiB (<=
LOW invariant, tested) + trailing debounced ACK in the web client
- Web: Vue 3 + Vite + Pinia + Tailwind 4 + vue-i18n (EN/FR) + xterm 6
(fit + webgl fallback), multiplexed ws-client with reconnect/backoff
and resync epochs
- Tests: 100 vitest (protocol fuzz, ring edges, auth, pty-manager flow
control with mocked pty, REST e2e) ; CI Node 22/24 + pack-smoke
- scripts/acceptance-p1.mjs: real daemon + real WS client — boot,
login, attach, stdin, 10 MB flood w/ ACK (13.7 MB/1.9s, RSS bounded),
brutal disconnect + replay resync, kill broadcast, SIGTERM drain