Symptôme: stopper un agent (ex Main sur UnityPlugin) laissait des travaux
poursuivre, la cascade n'atteignait pas les agents lancés et la pastille
restait orange pendant que l'agent continuait à en appeler d'autres.
- barrière d'admission par génération d'exécution (ExecutionControl): un stop
ferme l'admission de tout le sous-arbre propriété/attente AVANT toute
annulation asynchrone — plus aucune nouvelle action inter-agents après stop
- arbre de propriété durable en-process (launched_by) + dépendances d'attente
actives: la cascade couvre transitivement agents et travaux lancés
- commandes d'un agent arrêté rejetées (AppError::AgentStopped); stop
lui-même admis pour rester idempotent; réactivation sur relance humaine
(génération +1) et enregistrement du propriétaire au spawn
- admission exposée aux adaptateurs hors commandes cœur (tickets, templates,
plugins) via ensure_agent_execution_active; MCP server/tools, web-server et
commandes Tauri alignés
- cohérence live-state: statut Idle avec intent « Arrêté » ou
« Arrêt incomplet — Certains travaux sont encore actifs » selon l'issue de
la cascade; workstate et surfaces UI (AgentsPanel, LayoutGrid,
ProjectWorkStatePanel) reflètent l'état réel, plus de pastille orange fantôme
- tests: orchestrator_service (cascade/générations/idempotence),
workstate_actions, background_task_cancel, error_codes, agents, layout,
workstate
QA verte sur fix/320-agent-stop-cascade. Aucun push.
La cellule expose un bouton Redémarrer l'agent valable pour les trois
modes de présentation (headless, TUI native, CLI custom), sans jamais
prendre la présentation pour vérité runtime.
- Application: use case RestartCellAgentRuntime validant le binding
exact cellule/runtime via les snapshots live (RestartRuntimeNotFound,
ConflictAgentVisibleElsewhere, AgentNotBoundToCell) puis déléguant au
scheduler self-restart existant (schedule_cell); CellAgentPresentation
purement informationnelle.
- Backend/app-tauri/web-server: commande restart_cell_agent sur contrat
DTO identique Tauri/HTTP, stop borné par timeout typé
(RestartStopTimeout), relance préservant routage TUI natif, géométrie
de cellule (node/rows/cols) et conversation; évenements domaine
enrichis.
- Frontend: bouton dans la barre de cellule avec confirmation,
overlay d'état Redémarrage…/échec (libellés par code d'erreur, Fermer/
Réessayer), gardes d'identité de cellule et de restarts externes,
gateway/mock/http adapters et ports alignés.
- Tests: dto_agents, workstate_actions, contrats web-server,
LayoutGrid.cellControlsLayering, adapters agent/mock/http.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cause: update_project_settings remplaçait tout ProjectSettings avec la
seule couleur fournie — champ absent et null indistinguables — et des
réponses de chargement/sauvegarde obsolètes d'un projet précédent
pouvaient réafficher/écraser la couleur lors d'un changement de projet
rapide, d'où l'impression que la couleur ne prenait pas sur tous les
projets.
- DTO tri-état (absent = inchangé, null = défaut produit) avec
Deserialize manuel et use case de mise à jour partielle du champ
theme_color; commandes Tauri et web-server alignées sur le même
contrat.
- Garde-fous de course frontend: séquences load/save + révision thème
par projet (pub/sub onProjectThemeChanged) dans ProjectSettingsPanel,
garde de révision de focus dans ViewWindow.
- Tests: infrastructure settings, contrats web-server (inchangé/reset),
ProjectSettingsPanel, ViewWindow, projects.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- détachement: le panneau Paramètres du projet devient détachable (mapping historique panel=context → projectSettings dans parseViewWindowParams, DETACHABLE/ViewPanelBody alignés, ProjectsView ne court-circuitant plus le refus); Retry d'échec de détachement préservé
- couleurs projet: projectTheme publie idea:project-theme-changed localement + BroadcastChannel inter-webviews (fenêtres OS détachées), garde de révision par projet dans ProjectsView/ViewWindow contre les lectures settings en course — plus de flash/retour au bleu par défaut
- conversation custom CLI: transcript_restore_expected ne considère plus l'absence de scrollback volatile comme une restauration échouée quand la session rouvre en SessionPlan::None (continuation vide valide); CustomAgentChatView n'affiche plus le faux « conversation liée n'a pas pu être restaurée »
- images: conservation des images de conversation après changement de projet puis retour
- menus Panneaux: retrait des entrées Projects et Project Context (panelOrder WebWorkspace, création/switch via tab-bar +, contexte projet fusionné dans Paramètres du projet)
- QA verte: tests frontend ciblés window/ViewWindow/ProjectSettingsPanel/ProjectsView.detach/projects/CustomAgentChatView/WebDesktopWorkspace + cargo test -p application lifecycle transcript_restore_expected; fichiers .ideai/* (tickets 308-315, index/counter, agents/test, chat-drafts, system-permissions, project-settings.json, attachments/) et scripts/ hors périmètre préservés en worktree; aucun push
#305: nouvel agrégat durable ScheduledProjectTask dans domain (scheduled_task.rs, ids, ports ScheduledProjectTaskStore), source de vérité <app_data_dir>/scheduled-project-tasks/<projectId>.json, schedules bornés V1 interval/daily/weekly avec fuseau, cycle À approuver/Active/Suspendue avec approbation obligatoire des tâches demandées par agent; use cases application/scheduled_task (list/create/update/delete/run_now/reconcile/fire) réutilisant BackgroundTask pour les runs avec distinction planifié/manuel; store infrastructure dédié + scheduler reconcile au boot sans rattrapage en rafale, cwd confiné au projet; 7 tools MCP idea_scheduled_task_* (list/read lecture seule, create/update/delete/run_now/set_enabled write-actions soumises aux permissions natives); commandes Tauri + routes HTTP aux contrats DTO identiques (camelCase nextRunAtMs/lastRunAtMs/lastTaskId/createdBy/updatedBy); frontend: gateways Tauri/HTTP/mock + types ports/domain, surface projet 'Tâches planifiées' (liste utilisateur+agent unifiée, création/édition avec récapitulatif avant activation, approbation/refus, exécuter maintenant, suspendre/reprendre, suppression), catalogage surface web (webSurfaceCatalog/viewPlacement/ViewPanelBody/WebWorkspace); docs/scheduled-project-tasks.md et sdk docs/services.md (047c38b: pas un service plugin V1, pas d'émulation via cron système).
#314: correction de 'Conversation liée — transcript indisponible' après reboot: restauration du transcript lié côté application (orchestrator service, lifecycle, session_limit, background sink, terminal registry) et côté frontend (adapters agent/http frames/stream/requestResponse, workStateNormalization, CustomAgentChatView avec état et action utile), tests dto_chat/agent_lifecycle/structured_registry_d1/background_completion_sink étendus.
QA verte rapportée par QA sur feature/305-scheduled-project-tasks-mcp, sans bloquant, pour #305 et #314.
Hors périmètre worktree: tickets non liés, attachments/, scripts/; aucun push.
- #310: horodatage de tous les messages et événements de conversation visibles — composant partagé EntryTimestamp, timestamps propagés dans le transcript chat, les annonces inter-agent et le viewer de conversation, normalisation côté domain/adapters (conversation_log, paginate).
- #311: stop d'agent robuste pour PTY non monté, sessions headless et CLI custom — lifecycle/orchestrator durcis, ponts chat app-tauri/web-server alignés, arrêt fiable sans session orpheline.
- #312: préférence globale d'interface terminal par défaut — nouveau store settings (domain/application/infrastructure + tests), DTO et commandes backend, adapter frontend userSettings, panneau TerminalSettings dans les paramètres globaux.
- #313: Paramètres du projet — contexte de projet éditable et couleur de thème par projet (ProjectSettingsPanel + projectTheme), teinte des onglets projet, persistance via DTO projet.
QA verte (GO QA sur feature/batch-310-311-312-313-chat-stop-prefs-theme) — vérifications Git: git diff --cached --check OK; staging borné à crates/ et frontend/ (74 fichiers, +2105/-531), commit unique de lot conforme à la convention des lots (précédents batch-151/158/159, batch-210/211/212) car les fichiers partagés (dto.rs, commands.rs, CustomAgentChatView) entrelacent les 4 tickets.
fichiers .ideai/* (agents/test.md, chat-drafts.json, system-permissions.json, tickets/counter.json, tickets/index.json, tickets/308-313/), attachments/ et scripts/ hors périmètre et préservés en worktree ; aucun push.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cause: la politique de lancement Codex divergeait selon le chemin de composition. compile_codex_launch_policy ajoutait les roots extra (temp géré) AVANT de calculer le mode de sandbox, et le builder PTY (append_codex_pty_managed_temp_roots) n'appliquait QUE ces roots temp, ignorant project root et politique compilée ; sans permissions explicites, codex_permission_writable_roots renvoyait une liste vide, donc le premier lancement TUI partait sans --add-dir project root et rejetait les roots additionnels (« Error adding directories: Ignoring --add-dir … because the effective permissions do not allow additional writable roots ») ; un --add-dir <project root> préexistant dans spec.args n'était pas réconcilié, d'où des comportements différents entre first-run, stop/relaunch, CLI custom et délégation headless — invisible sur le projet IdeA lui-même du fait de ses permissions déjà configurées.
fix: codex_permission_writable_roots retourne par défaut le project root quand aucune permission explicite n'est configurée (jamais vide si root non vide) ; compile_codex_launch_policy n'ajoute les roots extra qu'en mode workspace-write et reste vide en read-only (deny explicite ne gagne jamais project root ni temp géré) ; nouveau apply_codex_pty_launch_policy unique source de vérité PTY Codex — réécrit la valeur --sandbox existante ou l'ajoute, draine le --add-dir <project root> préexistant puis pose les roots compilés dédupliqués, composition identique pour first-run, relaunch, custom CLI et headless ; unconfigured_policy_writes_project_and_deduplicated_managed_temp, explicit_write_deny_never_gains_project_or_managed_temp_root, partial_allow_exposes_only_its_computed_rw_grant + tests lifecycle de réécriture d'args ajoutés.
QA verte: cargo targeted tests OK, npm targeted/typecheck OK — reconfirmée par Git: git diff --check OK, cargo fmt --all -- --check OK, cargo test -p application --lib codex_permissions 3/3, cargo test -p application --lib lifecycle 48/48.
fichiers .ideai/* (agents/test.md, chat-drafts.json, system-permissions.json, tickets/counter.json, tickets/index.json, tickets/308/, tickets/309/), attachments/ et scripts/ hors périmètre et préservés en worktree ; aucun push.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
intègre feature/308-remove-project-from-registry commit b9f8ed3 — use case RemoveProjectFromRegistry + port ProjectStore::remove_project, adapter partagé Tauri/HTTP remove_project avec déactivation et purge open-projects restore, surface frontend ProjectActionsMenu + RemoveProjectDialog avec confirmation explicite et rechargement de la liste ; QA verte: cargo targeted tests/check OK, npm targeted/typecheck/build OK (suite npm test large rouge non bloquante hors #308, échecs préexistants) ; fichiers .ideai/* et scripts/ hors périmètre préservés en worktree ; aucun push.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cause: l'utilisateur ne pouvait pas retirer un projet du registre IdeA (projects.json) ; la seule issue laissait l'entrée fantôme dans la liste des projets, sans capacité générique de retrait.
domain: port ProjectStore::remove_project(id) -> Option<Project> avec implémentation par défaut « not supported » pour ne pas casser les stores spécialisés.
infrastructure: FsProjectStore implémente remove_project — retire l'entrée du registre persisté et la renvoie, None si id inconnu, ordre relatif du registre préservé ; test store dédié.
application: use case RemoveProjectFromRegistry (remove.rs) — NotFound explicite si id absent, retourne le projet retiré + registre rafraîchi.
backend/app-tauri/web-server: DTO RemoveProjectRequestDto/RemoveProjectResponseDto (removed, projects, restore_state, was_open), adapter partagé remove_project_for_adapter réutilisé par la commande Tauri remove_project et la route HTTP — même contrat desktop/web ; remove_project_and_deactivate désactive le projet s'il était ouvert, purge l'entrée open-projects restore correspondante et renvoie was_open/restore_state ; test adapter vérifiant le contrat de bout en bout (entrée retirée, restore purgé, root intact).
frontend: DTO + ProjectGateway.removeProject (HTTP + mock), ProjectsView expose un menu d'actions projet (ProjectActionsMenu) avec entrée Retirer, RemoveProjectDialog — confirmation explicite précisant que le dossier disque n'est pas supprimé, invalidation/rechargement de la liste des projets après succès (useProjects), tests ProjectsView/projects/adapters/httpInvoker/services.
QA verte: cargo targeted tests/check OK (domain, application project_usecases, infrastructure project_store, backend, app-tauri, web-server), npm targeted/typecheck/build OK ; suite npm test complète rouge non bloquante hors #308 (échecs préexistants listProjectSettings/web). Vérifications Git: git diff --check OK, cargo fmt --all -- --check OK.
fichiers .ideai/tickets/308/, tickets/counter.json, tickets/index.json, attachments/ et scripts/ hors périmètre et préservés en worktree (sync store traité séparément) ; aucun push.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recalcule la policy structured Codex lors des reprises custom/headless afin que le project root et le managed tmp soient transmis en writable_roots. Fail-closed si une session Codex structured est lancée sans policy explicite.