Adds a Live/Tickets/Sprints tab navigation to WebWorkspace after a project
is opened — a mobile-first adaptation, not a port of the desktop docks/
floating windows, per carnet #86. The web-server transport (17 ticket_*/
sprint_* commands) and the HttpTicketGateway were already wired (lot 1 +
pre-existing gateway code); this lot is UI only.
- Tickets tab: search/filters, list grouped by sprint, create screen,
detail view with stacked accordion sections (Résumé/Statut et priorité/
Carnet open by default; Agents assignés/Liens/Zone dangereuse collapsed),
delete confirmation, optimistic-concurrency conflict banner.
- Sprints tab: create/rename/reorder (Monter/Descendre)/delete with
confirmation, add tickets via a mobile full-screen ticket picker (never
a small desktop modal), "Voir tickets" filters the Tickets tab to one
sprint.
- Reuses the transport-neutral hooks as-is (useTickets, useTicketDetail,
useTicketSearch) — only presentation and copy are web-specific, in
French per decision #78 (new local label module, not a reuse of the
English desktop ticketMeta labels).
- Workaround: `list_agents` isn't in the web-server allowlist, so agent
names/assignment options are derived from `get_project_work_state`
(already used by the Live tab) instead of the desktop's useProjectAgents.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Expose la gestion des appareils appairés introduite en B1-B4, sur une
surface unique partagée par le web et le desktop.
- Écran Appareils : liste, renommage, révocation unitaire ou globale,
activité formatée, panneau de code éphémère.
- Le parcours d'appairage demande un nom d'appareil, pour qu'une
révocation porte sur quelque chose d'identifiable par l'utilisateur.
- Gateways DeviceGateway en trois adapters (Tauri, HTTP, Mock), le port
restant le seul contrat connu de la feature.
Les erreurs sont mappées localement et le message du serveur n'est jamais
affiché tel quel : un échec d'appairage ne doit pas devenir un oracle pour
qui teste des codes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le code d'appairage est de l'hexadécimal majuscule (p. ex. 3F7A9C21),
pas une suite de chiffres. Le champ appelait pourtant le pavé numérique
des mobiles, rendant les lettres A-F non saisissables.
Le champ passe donc en inputMode="text" avec autoCapitalize="characters",
ce qui revient sur le choix inverse fait en #69 : ce ticket avait supposé
un code purement numérique. Le placeholder et l'aide du champ décrivent
désormais le format réel.
La saisie est normalisée (majuscules, espaces retirés) avant pair() car
le serveur compare le code strictement ; la dette correspondante côté
backend est suivie en #76.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`npm run build` est `tsc --noEmit && vite build` : un import non utilisé
casse le build (TS6133), pas seulement le lint.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lots 3 et 4 du ticket #69. Sans ça un agent CLI est indriveable depuis un
téléphone : le clavier virtuel n'a ni Esc, ni Tab, ni Ctrl, ni flèches, donc
on peut taper un prompt mais pas l'interrompre, compléter un chemin, sortir
d'un éditeur ou rappeler l'historique.
- `TerminalView` expose un `onReady(api)` optionnel (donc desktop inchangé,
et inerte quand xterm ne monte pas). `api.send` passe par `term.input()` :
le *même* chemin qu'une frappe réelle, donc le relais PTY, le comptage de
lignes et la suspension du write-portal s'appliquent à l'identique. Écrire
sur le handle aurait court-circuité le portal.
- `TerminalKeyBar` (web-only) : Esc/Tab/Ctrl-C/Ctrl-D/flèches en chips
tactiles 44px, scroll horizontal. Chaque tap annule le déplacement de
focus et refocalise xterm — sinon le clavier virtuel se referme à chaque
touche.
- La cellule agent passe de `h-64` fixe (une letterbox d'~20 lignes) à
`h-[60dvh]` sur téléphone, `sm:h-80` au-delà.
- Tests : séquences d'octets émises, préservation du focus, état désactivé
avant montage de xterm, et garde de non-régression sur la frontière —
le client web ne monte aucun layout-grid/split/dock desktop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lots 1 et 2 du ticket #69 : rendre le client web (#13) utilisable sur un
téléphone. Le client web n'a jamais eu de docks ni de fenêtres flottantes —
il est déjà une colonne verticale unique — donc le lot 2 se réduit aux
rangées qui débordaient réellement à 360px.
- `100dvh` sur html/body/#root : `height: 100%` se résout sur le *large*
viewport, donc la barre d'URL rétractable d'un navigateur mobile masquait
le bas de l'app. Desktop inchangé (dynamic == large viewport).
- `viewport-fit=cover` + padding `env(safe-area-inset-*)` sur le header et
le workspace : l'app peut peindre sous une encoche sans perdre ses
contrôles. Le zoom reste libre (accessibilité).
- Padding responsive (`p-4 sm:p-6`) : 48px de gouttière sur 360px, c'était
13% de la largeur.
- `AgentLiveRow` et la rangée de tâche de fond empilent leurs contrôles sur
téléphone (nom / badges / actions) et retrouvent leur ligne unique dès
`sm` — à 360px les boutons Cancel+Retry ne tenaient pas.
- Code d'appairage : `inputMode="numeric"`, pas d'autocapitalisation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Flow logout : POST /api/logout puis retour à l'écran de pairing et
déconnexion du live. 401 renvoie au pairing sans boucle. Bannière de
reconnexion couvrant le cas live-only et le serveur indisponible.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lot F5 du chantier server/client mode : le client web consomme les frames
event.domain (B7) pour animer ses surfaces live.
- webLive.ts : consommation du flux event.domain (workstate, background,
inbox).
- useLiveReconnect.ts : reconnexion du flux live.
- wsLiveClient.ts / index.ts : câblage du transport live.
- WebWorkspace.tsx : surfaces live branchées.
- Tests : WebWorkspaceLive.test.tsx, wsLiveClientReconnect.test.ts,
WebApp.test.tsx.
Validé : frontend 753 tests verts, desktop non régressé.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lot F4 du chantier server/client mode : le client web expose une cellule
agent branchée sur le PTY WebSocket, en face de agent.launch (B6).
- wsLiveClient.ts : launchAgent sur le transport WebSocket.
- streamGateways.ts : gateway agent alignée sur le contrat serveur B6.
- WebAgentCell.tsx : cellule agent web, câblée dans WebWorkspace et index.
- Tests : agentGateway.test.ts, WebApp.test.tsx.
Validé : frontend 749 tests verts, contrat B6↔F4 aligné (aucun écart de
frame), desktop non régressé.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lot F2 du chantier server/client mode : client web read-only complétant le
premier incrément livrable — pairing, liste des projets, ouverture et
snapshot de l'état, sans PTY.
- frontend/src/adapters/http/webSession.ts : session web (pairing/cookie).
- frontend/src/features/web : PairingScreen, WebWorkspace, WebApp, index.
- Câblage main.tsx et adaptations httpInvoker.ts / index.ts (cas 401).
- Tests : webSession.test.ts, WebApp.test.tsx, cas 401 dans
httpInvoker.test.ts.
Validé : frontend 736 tests verts, build vert, garde no-direct-invoke
verte, contrat B4↔F2 aligné, desktop non régressé.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>