---
issueRef: "#69"
version: 9
updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"}
updatedAt: 1784202783353
---
# Ticket #69 — Adaptibilité client téléphone (carnet de chantier)

Statut : **QA — en attente de validation live utilisateur sur un VRAI téléphone**.
Branche : `feature/ticket69-mobile-responsive-client` (base `develop` @ `506d589`). Commits : `e22ea5b` (shell), `8f15ad6` (terminal + tests), `6ed0087` (fix typecheck). Frontend uniquement — vérifié.

## Cadrage Architect
Ticket **frontend-pur** : aucun changement DTO, use case, ni modèle `LayoutTree`. Contrats HTTP/WS et layout/terminal inchangés. Mais PAS du « CSS pur ».

## ⚠️ Le cadrage initial reposait sur un modèle FAUX (constat majeur)
Le lot 2 prévoyait « remplacer les docks gauche/droite/floating par une pile verticale/drawer/bottom sheet ». **Il n'y a rien à remplacer** : le client web n'a JAMAIS eu de docks, de fenêtres flottantes ni de `LayoutTree`. `main.tsx` route le mode `http` vers `WebApp`, surface autonome livrée par #13 : pairing **ou** `WebWorkspace`, déjà une colonne verticale unique. Les seuls imports `@/features/*` de tout `features/web/` sont `terminals` et `workstate` — le shell desktop n'est pas atteignable depuis le web.
⇒ **La question « bottom sheet vs drawer » ne se pose pas.** Frontière épinglée par un test (`WebMobile.test.tsx`) + mémoire `web-client-is-single-column-no-desktop-shell`, pour que le cadrage ne reparte pas du même modèle faux.

## Le vrai blocage était le terminal, pas le layout
Le clavier virtuel n'a ni Esc, ni Tab, ni Ctrl, ni flèches : on pouvait taper un prompt à un agent CLI mais pas l'interrompre, compléter un chemin, sortir d'un éditeur ou rappeler l'historique.

## Livré
- **Lot 1 (shell)** : `100dvh` (le `height:100%` se résolvait sur le *large* viewport ⇒ la barre d'URL rétractable masquait le bas), `viewport-fit=cover` + safe-area insets, padding responsive, `inputMode="numeric"` sur le code d'appairage. Zoom laissé libre (accessibilité).
- **Lot 2 (réinterprété)** : `AgentLiveRow` + rangée de tâche de fond (statut/kind/Cancel/Retry ne tenaient pas à 360px) s'empilent sous `sm`, ligne unique dès `sm`.
- **Lot 3 (terminal)** : `TerminalView` expose `onReady(api)` **optionnel** (desktop inchangé) ; `api.send` passe par `term.input()` — même chemin qu'une frappe réelle, donc relais PTY + suspension du write-portal s'appliquent à l'identique (écrire sur le handle aurait court-circuité le portal). `TerminalKeyBar` : Esc/Tab/Ctrl-C/Ctrl-D/flèches en chips 44px ; **chaque tap annule le déplacement de focus** puis refocalise xterm (sinon le clavier virtuel se referme à chaque touche). Cellule `h-64` → `h-[60dvh]`.

## Vérif QA (exécution réelle) — VERT
- `npm run typecheck` exit 0 · `npx vitest run` → 85 files / **774 passed** · `VITE_TRANSPORT=http npx vite build` OK.
- **CSS mobile confirmé DANS le bundle** (les valeurs arbitraires Tailwind avec `env()` no-opent en silence) : `100dvh`, `60dvh`, les 4 `safe-area-inset-*`, `viewport-fit=cover`, `.h-\[60dvh\]{height:60dvh}`.
- Non-régression desktop : `LayoutGrid` ne passe pas `onReady` ; chemin desktop inchangé.
- Rendu réel Chrome headless 360×780 : pairing tient sans débordement horizontal.

## Réserve ASSUMÉE — trou de couverture réel
**jsdom n'évalue PAS les media queries** : les tests sont structurels, pas visuels. Ils ne prouvent NI le rendu aux breakpoints, NI l'effet réel de `dvh`, NI les safe areas, NI le clavier virtuel/focus sur navigateur mobile. QA : « acceptable pour merger avec réserve explicite », pas rouge. **C'est exactement ce que la validation utilisateur doit couvrir.**
Workspace + keybar non vérifiés visuellement à 360px (demande un serveur appairé + PTY vivant = territoire #65) — angle mort restant.

## Écart de périmètre à arbitrer (Playwright)
Lot 4 demandait « Playwright ou équivalent ». DevFrontend a livré l'équivalent (vitest/jsdom) et REFUSÉ d'installer Playwright unilatéralement (binaires navigateur + surface CI = décision de dépendance qui remonte à Architect/Main). Avis QA : non bloquant pour ce lot, mais vitest/jsdom **n'est pas un équivalent complet** pour un ticket dont le risque principal est visuel mobile. ⇒ **Follow-up à décider** : ticket « tests de rendu réel aux breakpoints » si le projet accepte une dépendance navigateur/CI.

## Prochaine étape
Validation live utilisateur sur un vrai téléphone (build `VITE_TRANSPORT=http`, servi par `idea --serve`/`idea-serve`, accès LAN). Si OK → Git merge dans develop (Git passera #69 avant #65 si les deux sont prêts : petit, frontend-pur, faible risque).
