Panneau Permissions: idea_ask_agents est câblé côté backend MCP mais absent
du groupe « Délégation agents » du panneau — ajout de l'outil et de son
label, catalogue mock MCP aligné en conséquence.
Terminaux: ProjectsView remonte LayoutGrid via une key au changement de
projet, donc refitEpoch n'aide pas ; le montage de TerminalView ne
maintenait pas assez longtemps le fit tant que la nouvelle cellule ne
s'était pas stabilisée. Le chemin de montage garde désormais une traîne de
refits plus longue (MOUNT_SETTLE_REFIT_FRAMES) avant de laisser la main au
ResizeObserver.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The web shell never adopted the desktop's #61 fix: WebAgentCell/WebWorkspace
didn't pass any refitSignal to TerminalView, so a cell opened after another
kept a stale xterm scaling — desktop "fixed" it via an incidental window
resize, but mobile has no such escape hatch.
- TerminalView: a refit landing on a transient 0x0 container now reschedules
on the next few frames instead of giving up for good (bounded retries),
closing the independent timing gap Architect identified. refitSignal stays
the single explicit-refit mechanism; the terminal/PTY is never recreated,
and resize is still pushed to the PTY only when rows/cols actually change.
- WebAgentCell: new optional refitSignal prop, forwarded to TerminalView
as-is (no key change, no remount).
- WebWorkspace/LiveProjectPanel: new cellLayoutVersion counter, the web
equivalent of desktop useLayout.layoutVersion, bumped on every cell
open/close and forwarded as refitSignal to the visible WebAgentCell.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Le ResizeObserver de TerminalView ne déclenche pas toujours un événement
utile quand une cellule voisine apparaît/disparaît (split/merge), forçant
l'utilisateur à redimensionner la fenêtre pour rafraîchir le scaling xterm.
useLayout expose un layoutVersion bumpé à chaque commit d'arbre (chargement
initial inclus), relayé par LayoutGrid comme refitSignal à chaque
TerminalView survivant pour déclencher fit.fit() sans rouvrir le PTY.
Co-Authored-By: Claude Sonnet 5 <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>
Câble la surface frontend des profils IA locaux/LAN OpenAI-compatible,
en parité avec l'adapter backend additif (aab4bca).
- domain: types de profil OpenAI-compatible
- first-run: édition/validation du profil dans le FirstRunWizard
- adapters/mock: mock de profil pour les tests
- terminals: rendu des round-trips et erreurs endpoint (role=alert)
Validé QA (frontend GO): typecheck exit 0, vitest 59 fichiers / 566 tests,
0 echec ; couverture timeouts round-trip + erreur endpoint role=alert
prouvees ; pas de regression sur les tests de bail headless.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Durcit le portail d'écriture de délégation et son acheminement bout-en-bout
(commande Tauri → orchestrateur → file d'entrée infrastructure → portail
frontend), avec une journalisation du submit pour diagnostiquer les cas où la
délégation n'était pas remise. Couvre le portail d'écriture côté front
(useWritePortal) avec ses tests.
QA : checks application/front/infrastructure/app-tauri verts. Les tests loopback
socket Unix réels ne sont pas exécutables en sandbox (UnixListener::bind →
PermissionDenied) ; alternatives avec skips vertes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fiabilise la livraison des délégations inter-agents dans le terminal :
écriture par chunks UTF-8 bornés (512 o, délai 8 ms) pour éviter les
comportements de paste/drop des TUI sur agents froids, et réconciliation
de l'attachement front (frontAttachedAgentRef / reconcileFrontAttachment)
pour ne reporter « front attaché » qu'une fois les DelegationReady
réellement consommés. Tests vitest associés.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sauvegarde de l'arbre de travail en cours (persistance P8, conversations
C-series, write-portal frontend, médiation d'entrée) avant d'attaquer le
support de la délégation inter-agents pour les profils Codex.
Le round-trip inter-agent question/réponse est couvert sans tokens par
les tests loopback existants (state::mcp_e2e_loopback_tests).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Un agent ne peut tourner que dans une seule cellule à la fois. La garde dans
LaunchAgent refuse le spawn si l'agent est déjà vivant dans un autre node
(AGENT_ALREADY_RUNNING) ; idempotent sur le même node ; le chemin resume
(agent mort) reste inchangé. Le node_id est désormais plombé jusqu'au use case.
Corrige le reset asymétrique d'une cellule au changement d'onglet : deux leaves
partageant le même agent id rendaient session_for_agent/is_agent_live/stop_agent
ambigus (cible arbitraire). Le churn reset/reattach déclenchait aussi les accents
mélangés (FIFO intact, non touché).
- snapshot agentWasRunning calculé par node (is_node_live) et non par agent
- commande list_live_agents + live_agents()/node_for_agent()/is_node_live()
- UI : dropdown grise les agents déjà placés ailleurs ; 2e cellule en doublon
affiche « disponible » au lieu d'une relance fantôme
Tests : cargo test (application + app-tauri) vert ; tsc + vitest vert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Permet de recharger la conversation CLI précédente de chaque cellule à la
réouverture du projet, de façon universelle (indépendant du modèle/CLI).
- profil AgentRuntime: bloc déclaratif optionnel `session { assignFlag, resumeFlag }`
- LeafCell: `conversationId` (persistant, distinct du SessionId PTY) + `agentWasRunning`
- runtime: SessionPlan (None/Assign/Resume) + composition pure des args
- LaunchAgent: décide Assign vs Resume, génère l'UUID, remonte l'id assigné
(persistance par l'appelant via setCellConversation — découplage SRP)
- close: SnapshotRunningAgents fige `agentWasRunning` avant le kill-all
(statut clot/en cours universel, sans parsing CLI)
- SessionInspector: port optionnel best-effort + adapter ClaudeTranscriptInspector
- popup de reprise par cellule (statut + sujet/tokens si dispo), intercalée
avant le Resume auto, jamais sur le chemin reattach
fix(terminals): sérialise les écritures PTY (file FIFO par handle) — corrige
les caractères mélangés/accents dus au réordonnancement des invoke Tauri concurrents
fix(layout): l'opération `move` préservait mal les champs du leaf (perdait `agent`)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Navigating (layout/tab switch) tore the xterm view down and called
handle.close(), killing the backend PTY and cutting off running AIs. Now
the view's cleanup only detaches; only an explicit user action kills a PTY.
Backend:
- PortablePtyAdapter: per-session scrollback ring buffer (~100KB, most
recent) + re-subscribable fan-out broadcast replacing the single-take
output_rx. Reader thread feeds both the ring buffer and current
subscribers; on EOF it closes subscribers (streams end) while keeping
scrollback for late re-attach.
- PtyPort: new scrollback() method; subscribe_output is now re-subscribable
(all impls + test fakes updated).
- reattach_terminal IPC command: returns scrollback and re-wires a fresh
output channel on the live session without re-spawning.
- CloseRequested hook kills all live PTYs cleanly on app shutdown.
- TerminalSessions::handles() to enumerate live sessions at shutdown.
Frontend:
- TerminalHandle.detach(); TerminalGateway/AgentGateway.reattach() + mocks.
- TerminalView cleanup detaches (never close); on mount it re-attaches to a
persisted session (repainting scrollback) instead of opening a new PTY.
- LayoutGrid persists the cell's session id via setSession; AgentsPanel
tracks per-agent session ids — both drive reattach-vs-open.
Tests: ring buffer bounds to 100KB keeping newest bytes; scrollback retained;
re-subscription delivers post-reattach output; TerminalView detaches (not
closes) on unmount and reattaches with a known session; mock detach/reattach.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>