Les tickets legacy sans champ createdBy faisaient noircir la fenêtre
tickets côté frontend. Les adapters (ticket.ts, streamGateways.ts)
normalisent désormais ce champ absent, avec couverture de test dédiée.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les lignes de ticket persistées avant l'introduction de ces champs peuvent
arriver sans assignedAgentIds (ni links/attachments), ce que TicketsPanel
déréférence sans garde côté rendu : la fenêtre de liste rend quelques lignes
puis devient noire dès qu'une ligne legacy est itérée. Les deux gateways
(Tauri et HTTP/stream) normalisent désormais chaque ticket et chaque item de
liste avant de les retourner à l'UI.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Stockage flat côté ticket + métadonnées d'attachments, lecture exposée côté
backend/MCP, et UI minimale de liste/ajout dans TicketDetail. Traverse le
domaine (Issue, ports), l'application (usecases + assistant de ticket), les
adaptateurs infra/MCP (issues store, orchestrateur), les DTO backend/web-
server/app-tauri, et le frontend (domain/ports/adapters/hooks/UI).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
createdBy était déjà présent dans le frontmatter des tickets mais ni exposé
ni exploitable côté UI. Ajout du DTO (domain/ports/mock), affichage dans
TicketDetail, colonne/filtre créateur dans TicketsPanel, et persistance du
filtre. ticketActor.ts introduit pour porter la logique de filtrage côté
frontend, sans changement backend nécessaire (lot frontend pur).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
Le popup viewport-positionné utilisait zIndex.menuDropdown (40), inférieur à
zIndex.floatingWindow (50) : il s'affichait derrière une fenêtre flottante
ouverte. Ajout de zIndex.transientPopup (65), au-dessus de floatingWindow et
floatingWindowNested, pour tout popup transitoire porté par document.body
depuis une FloatingWindow.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remplace les <select> natifs de la vue Tickets (statut, priorité, tri,
lien, agent assigné/assistant, sprint) par TicketViewportSelect, qui
repositionne intelligemment son overlay selon l'espace disponible dans
la fenêtre au lieu de toujours ouvrir vers le bas.
QA vert : 80/80 (frontend/src/features/tickets), tsc --noEmit propre.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Le toast de fin de tâche de fond liée à un rendez-vous inter-agent passe
de « Main -> DevBackend completed » à « Appel Main -> DevBackend terminé »
(idem en échec / annulé), pour nommer explicitement l'appel plutôt qu'un
état brut. Fallback générique conservé quand requester/target sont absents.
Validations obtenues avant commit : tests frontend annoncés verts pour #91.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Câble un canal attachable au flux de sortie d'une tâche de fond (runner
infrastructure + commande app-tauri + port/adaptateurs frontend) et le
panneau ProjectWorkStatePanel s'y abonne pour un rendu live au lieu d'un
état figé au dernier snapshot.
Validations obtenues avant commit :
- cargo test -p infrastructure --test background_task_runner : vert
- cargo check -p backend -p app-tauri : vert
- npx vitest run src/features/workstate/workstate.test.tsx : vert
- npm run typecheck : vert
- verdict QA #58 : vert
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ajout du catalogue enrichi pour les modèles Codex et Claude avec:
- Compatibilité estimée avec la version CLI locale détectée
- Source d'origine (catalogue/Provider) pour chaque entrée
- Support du catalogue Provider API externe
- Matrice de compatibilité embarquée dans l'application
Frontend:
- UI de configuration des modèles avec affichage des états de compatibilité
- Suggestions dynamiques avec badges de compatibilité
- Messages d'aide contextuels (compatible/unknown/likelyTooRecent)
- Alertes non-bloquantes pour les modèles trop récents
- Gestion des échecs de catalogue avec saisie manuelle conservée
Backend:
- Ports CliVersionReader, ProviderModelCatalogue, CompatibilityMatrixSource
- Implémentations: ProcessCliVersionReader, HttpProviderModelCatalogue, EmbeddedCompatibilityMatrix
- Enrichissement des DTOs avec compatibility, cli_version, warnings
- Tests unitaires complets pour le resolver de catalogue
Le picker de provider OpenCode du first-run wizard consomme le
catalogue dynamique exposé par le backend et propose une option
« provider personnalisé » avec un formulaire de saisie libre
(id + clé API) quand le provider souhaité n'y figure pas.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute l'UI de configuration des providers OpenCode cloud dans le wizard
first-run (sélection, édition, sauvegarde, suppression), le domaine et
les ports associés, ainsi que les adapters HTTP/mock correspondants.
Build + 952 tests verts, comportements clés vérifiés en exécution réelle,
y compris un test de couverture ajouté pour le parcours d'édition.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lots F1-F4 : runtime de chargement/registre plugin, extension des menus
existants, panneau de gestion des plugins, types de layout custom
(sélecteur, fallback, cellule dédiée) branchés sur le port plugin.
Suite npm typecheck/test verte (947/947).
Co-Authored-By: Claude Sonnet 5 <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>
Ajoute l'option de lancement automatique du serveur web au démarrage
d'IdeA (#89) : déclenchement backend Tauri au boot selon la
préférence utilisateur persistée, réglage frontend dans les
paramètres de déploiement avec erreur port occupé actionnable.
QA : 57 tests backend app-tauri verts (embedded_server/auto_start
compris), 895/895 tests frontend, tsc propre.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Étend ServerExposureSettings avec autoStart (défaut false, mock aligné sur le
backend). useDeployment expose setAutoStart, qui persiste immédiatement le
draft sans jamais appeler start() ni toucher le comportement de stop(), et ne
met à jour l'état local qu'après confirmation de la sauvegarde (même piste de
validation que start/save). DeploymentSettings ajoute la case à cocher sous
le panneau Serveur, et des actions « Modifier le port »/« Réessayer » quand le
statut échoue avec le code PORT_IN_USE stabilisé côté backend.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WebWorkspace gagne un menu « Panneaux » qui route la surface principale du
projet ouvert vers les panneaux transport-neutres déjà réutilisables
(contexte, agents, templates, skills, permissions, mémoire, git) en plus des
surfaces web existantes (travail live, tickets, sprints), ainsi qu'un variant
web du panneau Projets (création par chemin serveur saisi manuellement, sans
browse natif). WebApp gagne un menu « Paramètres » (Profils IA, Appareils,
Déploiement désactivé "Desktop uniquement") qui remplace l'ancien bouton
unique "Appareils".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
WebWorkspace replie désormais par défaut la liste des background tasks
par agent dans le panneau Work ; QA a ajouté les cas de test associés
dans WebWorkspaceLive.test.tsx (887 tests verts, tsc --noEmit clean).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
QA-flagged gap: the web surface could only ADD a ticket to a sprint, never
change or clear it, despite the backend already exposing both
ticket_assign_sprint and ticket_unassign_sprint.
- useTicketDetail: new setSprint(sprintId | null) method (additive, also
available to the desktop TicketDetail — unused there today, no behaviour
change), routing through the existing TicketGateway.setTicketSprint.
- WebTicketDetail: Sprint selector in "Statut et priorité", immediate save
like status/priority; empty value clears back to "Sans sprint".
- WebSprintsView: each sprint card now shows its tickets (compact list,
resolved client-side like the desktop SprintManager) with a "Retirer du
sprint" action per ticket, calling assignSprint(ref, null) — symmetric
with "Ajouter tickets". Extracted the card into a SprintCard subcomponent
to keep the growing card readable.
- Tests: WebTicketsSprints.test.tsx now has 16 tests (was 10) — added
sprint change/clear, sprint removal from the Sprints tab, agent
assign/unassign, ticket link/unlink, carnet save, and free-text search
filtering.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
Écoute l'event Tauri `app-exit-work-guard` (émis par le backend quand la
fermeture de la fenêtre main est interceptée) et affiche une popup modale
"Du travail est encore en cours" avec le résumé pluralisé exact du carnet
#83, le détail agents/tâches capé à 5 lignes, et les deux actions Annuler
(focus par défaut, no-op local) / Quitter quand même (danger, appelle
confirm_app_exit). Pas d'option "ne plus demander".
- domain/ports/adapters (Tauri listen+invoke, HTTP desktop-only stub, mock
avec helpers de test) : onAppExitWorkGuard/confirmAppExit sur
SystemGateway, suivant le patron déjà utilisé pour focused-project et les
domain events.
- AppExitConfirmDialog : mounted une fois près de la racine (App.tsx), à
côté d'AnnouncementsProvider — role="alertdialog", focus trap, Échap =
Annuler, pas de fermeture au clic extérieur, ne se referme jamais
automatiquement (un event pendant l'ouverture rafraîchit juste le résumé).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds the "Tools MCP IdeA" tab to the project Permissions panel, alongside
the existing "Système" (file/command) tab. Lets the user grant/revoke MCP
tool capabilities per agent or project-wide default, grouped by domain
(Lecture projet, Lecture tickets, Délégation agents, Contexte et mémoire,
Tickets, Travail et exécution, Skills) instead of a flat 25-checkbox list,
per the UX conception in carnet #82.
- domain/ports/adapters (Tauri, HTTP, mock): wire get_mcp_tool_permissions,
update_project_mcp_tool_permissions, update_agent_mcp_tool_permissions
(already merged backend API, #82 lots B1-B4) onto PermissionGateway.
- useMcpToolPermissions: view-model owning the durable MCP tool policy
document, distinct from the file/command permissions in usePermissions.
- McpToolPermissionsPanel: target selector (Défaut projet + agents with
Hérité/Override badges) and grouped editor — inherited agents are
read-only until "Créer un override" (prefilled with the effective
allowlist), per-row Ajouté/Retiré diffing against the project default,
inline confirmation before granting a write tool at project-default
level, and unsaved-draft protection on target change.
- mcpToolGroups.ts: presentational-only domain grouping and short French
labels — the read/write classification itself always comes from the
backend-provided catalogue, never hardcoded here.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ticket #79 : fix du flake PermissionsPanel > saves project defaults
(PermissionEditor draft resync clobbering in-flight edits). QA vert sur le
périmètre du ticket (2/2 stable + suite complète non-shuffled) ; le rouge
observé en shuffle vient d'un autre test préexistant sans rapport
(setCellAgent.test.tsx, tracé séparément en #85).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
UX decision (carnet #78): the human UI of IdeA is French by default,
uniform per surface — proper nouns and technical acronyms (URL, LAN,
IP/CIDR, HTTPS, API, CLI…) stay as-is. Settings mixed English (AI
Profiles, Deployment) with French (Appareils, frozen by UX for #77).
Renames the Settings menu/nav, the Profils IA and Déploiement panels
(titles, actions, states, help text) to French, per the carnet's
exhaustive list. Updates the affected tests accordingly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The draft-resync useEffect fired on every new `draft` object (initial load,
refresh, another save), even when its content matched `local`. If it flushed
after the user started editing, it silently discarded the edit — flaky in
tests where a passive effect can settle after a synchronous fireEvent
sequence, and a real risk in production if a fetch lands mid-edit. Now it
only resyncs when `local` still matches the last-adopted draft.
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>
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>
Vérifie sur les artefacts réels que `dist` résout `tauri` et `dist-web`
`http`, en lisant le marqueur `__IDEA_TRANSPORT__` des assets JS émis. La
régression de #74 était invisible aux tests unitaires : elle vivait dans la
conf de build et de packaging, pas dans le code testé.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le transport est figé au build par Vite : un seul `dist` ne peut pas servir
à la fois le desktop (IPC Tauri) et le navigateur (HTTP+WS). Le serveur
embarqué servait donc un bundle desktop, d'où `__TAURI_INTERNALS__ is
undefined` côté navigateur.
- `vite.config.ts` devient une factory `({ mode })` : le mode par défaut émet
le bundle desktop (`dist`), `--mode web` lit `.env.web` et émet le bundle
navigateur (`dist-web`).
- `.env.web` porte `VITE_TRANSPORT=http` dans un fichier de mode plutôt qu'en
préfixe de commande, syntaxe qui n'existe pas sous Windows (bundle NSIS).
- `transport.ts` extrait le prédicat `transportFromEnv()`, partagé par l'app et
la config de build : le constant `__IDEA_TRANSPORT__` et le transport résolu
dérivent de la même variable via le même prédicat, ils ne peuvent pas diverger.
- `main.tsx` publie `__IDEA_TRANSPORT__` sur `window` : l'affectation est un
effet de bord, elle survit à la minification et rend un bundle identifiable
sans grep d'un symbole minifié. Les deux jeux d'adapters étant présents dans
les deux bundles, leur présence ne prouve rien.
Le chemin desktop est inchangé : le web reste opt-in.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Donne à l'utilisateur la surface pour activer le serveur depuis l'app.
- `features/settings/` : `SettingsView`, `DeploymentSettings`, `useDeployment`.
- `adapters/desktopServer.ts` + port `DesktopServerGateway` et DTO associés ;
adapters mock et http/unsupported alignés (le mode web n'expose pas le
contrôle du serveur qui l'héberge).
- `ProjectsView` : le `showSettings: boolean` devient une navigation interne
`AI Profiles` / `Deployment`. Le libellé alternant « Close AI Profiles »
disparaît — Settings existait déjà dans cette vue, la surface évolue au lieu
d'ajouter un `PanelId`.
CORRECTION D'UN BRIEF FAUX, remontée spontanément par DevFrontend et qui mérite
de survivre : le cadrage décrivait le mode `remoteProxyOtherMachine` avec deux
champs. `validate_settings` en exige un troisième, `lanBindAddress`, et rejette
loopback comme unspecified. Construit selon la spec, chaque save et chaque start
en mode 3 aurait échoué — le lot serait parti vert et cassé. Le panneau expose
donc un select alimenté par `candidateLanAddresses` fourni par le backend :
la règle « le frontend n'invente jamais une IP » tient.
QA ré-exécutée par Git avant merge : `npm run typecheck` exit 0 ·
`npx vitest run` 87 files / 789 passed, 0 échec.
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>