Files
IdeA/.ideai/tickets/307/carnet.md

16 KiB

issueRef, version, updatedBy, updatedAt
issueRef version updatedBy updatedAt
#307 7
kind agent_id
agent 1ff94b51-3e17-4a39-8543-7715d1ff0f80
1789054288135

2026-09-10 — Main

Signalement utilisateur: au lancement d'IdeA, l'UI indique des tasks/états en cours alors qu'aucune tâche réelle n'est active. Capture: cellule Main affichant Conversation liée — récupération du transcript en cours.

Cadrage Architect:

  • Bug backend prioritaire avec validation frontend.
  • Vérifier/corriger la chaîne BackendCore::activate_project() -> reconcile_layouts, reconcile_live_state, reconcile_background_tasks.
  • Sources persistées à réconcilier: live-state.json (working/waiting/blocked sans session vivante -> idle) et BackgroundTaskStore (Running/Waiting/Cancelling sans handle runtime -> terminal + delivery pending si nécessaire).
  • GetProjectWorkState ne doit pas reprojeter de tâche non terminale orpheline après activation projet.
  • Le message transcript peut être l'effet direct du live-state fantôme; si un conversationId persiste seul sans tours ni session active, ajouter un garde-fou frontend minimal pour ne pas rester indéfiniment sur récupération du transcript en cours.

Fichiers probables backend/domain: crates/backend/src/lib.rs, crates/application/src/workstate/reconcile.rs, crates/domain/src/live_state.rs, crates/infrastructure/src/store/background_task.rs, tests crates/application/tests/workstate.rs et backend autour de la réconciliation.

Fichiers probables frontend: frontend/src/features/agents/CustomAgentChatView.tsx, frontend/src/features/workstate/ProjectWorkStatePanel.tsx, frontend/src/features/layout/LayoutGrid.tsx, frontend/src/adapters/workStateNormalization.ts.

QA attendue: démarrage avec live-state fantôme, background task Running orpheline, completion pending/non livrée, completion déjà livrée, multi-projets, et capture UI équivalente sans blocage transcript infini.

2026-09-10 — DevBackend

Correctif backend/domain implémenté sur develop, sans commit/merge/push et sans modification frontend.

Diagnostic:

  • LiveState::reconcile_orphans remettait bien les lignes working/waiting/blocked sans session vivante à idle, mais conservait leur correlationId. Or cette corrélation représente une requête cross-project active; après reboot, elle ne correspond plus à aucun runtime reprenable/annulable et maintient une relation fantôme.
  • AppBackgroundTaskStore::reconcile_project_boot(project_id, ...) déléguait à FsBackgroundTaskStore::reconcile_boot, qui balayait tous les documents présents sous le root. De même, list_undelivered_for_project ne filtrait pas le résultat global sur le projet demandé. L'activation n'était donc pas strictement bornée au projectId activé.

Implémentation:

  • crates/domain/src/live_state.rs: une ligne active orpheline efface désormais aussi correlation_id, en plus de ticket et last_delegation; test domaine renforcé avec une corrélation réellement présente.
  • crates/infrastructure/src/store/background_task.rs: ajout de reconcile_project_boot(project_id, live_task_ids, now_ms) et factorisation interne; l'API historique reconcile_boot reste disponible, tandis que l'activation utilise la variante bornée.
  • crates/backend/src/lib.rs: réconciliation et collecte des complétions strictement filtrées sur le projet activé; test B7 renforcé pour vérifier que la tâche orpheline terminalisée disparaît de list_open_for_agent, source ouverte de GetProjectWorkState.
  • crates/infrastructure/tests/background_task_store.rs: test multi-projets prouvant que l'activation d'un projet ne répare ni ne rapporte une tâche étrangère.
  • crates/backend/src/lib.rs: test d'intégration #307 qui persiste un live-state working corrélé et une tâche Running, appelle réellement BackendCore::activate_project(), puis vérifie idle, corrélation/ticket/délégation effacés, tâche Failed et aucune tâche ouverte reprojetable.

Commandes exécutées, toutes vertes:

  • cargo fmt --all -- --check
  • cargo test -p domain live_state::tests::reconcile_orphans — 4/4
  • cargo test -p infrastructure --test background_task_store reconcile — 4/4
  • cargo test -p backend background_tasks_b7_tests — 1/1
  • cargo test -p backend ticket307_activation_reconcile_tests — 1/1
  • cargo test -p application --test workstate — 29/29
  • cargo check -p backend
  • git diff --check

Frontend:

  • Aucun changement nécessaire pour le défaut backend reproduit/corrigé.
  • QA doit encore faire le smoke test UI/AppImage de fermeture-relance demandé par le cadrage. Si le message Conversation liée — récupération du transcript en cours. subsiste avec un conversationId frontend isolé malgré les états backend assainis, le garde-fou frontend minimal décrit par Architect reste un lot séparé à confirmer sur preuve live.

2026-09-10 — QA

Verdict QA: VERT pour le correctif backend/domain/infrastructure du ticket #307.

Relu:

  • Diff de crates/domain/src/live_state.rs, crates/infrastructure/src/store/background_task.rs, crates/infrastructure/tests/background_task_store.rs, crates/backend/src/lib.rs.
  • BackendCore::activate_project() appelle toujours reconcile_layouts, reconcile_live_state, reconcile_background_tasks.
  • GetProjectWorkState filtre les background tasks par task.project_id == project.id avant projection.
  • Frontend: CustomAgentChatView garde le message Conversation liée — récupération du transcript en cours. quand displayTurns.length === 0 && hasLinkedConversation; hasLinkedConversation reste vrai avec un conversationId seul.

Test QA frontend ajouté:

  • frontend/src/features/agents/CustomAgentChatView.test.tsx: keeps the linked-conversation placeholder when an isolated conversation id has no recovered turns.
  • Ce test ne modifie pas le code de production; il prouve que le garde-fou frontend UX reste nécessaire si un conversationId isolé survit indépendamment de l'état live/backend.

Commandes exécutées et sorties réelles:

$ cargo fmt --all -- --check
<no output, exit 0>
$ git diff --check
<no output, exit 0>
$ cargo test -p domain live_state::tests::reconcile_orphans
running 4 tests
test live_state::tests::reconcile_orphans_does_not_mutate_self ... ok
test live_state::tests::reconcile_orphans_downgrades_dead_active_rows_and_rewrites_fields ... ok
test live_state::tests::reconcile_orphans_covers_working_waiting_blocked_only ... ok
test live_state::tests::reconcile_orphans_spares_live_agents ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 307 filtered out; finished in 0.00s
$ cargo test -p infrastructure --test background_task_store reconcile
running 4 tests
test reconcile_marks_cancelling_without_live_handle_cancel_failed_and_pending ... ok
test reconcile_uses_monotonic_timestamp_when_clock_is_behind ... ok
test project_reconcile_does_not_repair_or_report_foreign_project_tasks ... ok
test reconcile_marks_running_without_live_handle_failed_and_pending ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 8 filtered out; finished in 0.00s
$ cargo test -p backend background_tasks_b7_tests
running 1 test
test background_tasks_b7_tests::app_reconcile_requeues_wake_owner_marks_record_only_and_repairs_orphan_running ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 101 filtered out; finished in 0.09s
$ cargo test -p backend ticket307_activation_reconcile_tests
running 1 test
test ticket307_activation_reconcile_tests::activate_project_clears_stale_live_correlation_and_terminalizes_orphan_task ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 101 filtered out; finished in 0.07s
$ cargo test -p application --test workstate
running 29 tests
...
test workstate_projects_open_and_undelivered_background_tasks_by_agent ... ok
test result: ok. 29 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
$ cargo check -p backend
Checking domain v0.3.0 (/home/anthony/Documents/Projects/IdeA/crates/domain)
Checking application v0.3.0 (/home/anthony/Documents/Projects/IdeA/crates/application)
Checking infrastructure v0.3.0 (/home/anthony/Documents/Projects/IdeA/crates/infrastructure)
Checking backend v0.3.0 (/home/anthony/Documents/Projects/IdeA/crates/backend)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 9.44s
$ npm test -- CustomAgentChatView.test.tsx
npm error enoent Could not read package.json: Error: ENOENT: no such file or directory, open '/home/anthony/Documents/Projects/IdeA/package.json'
$ (cd frontend && npm test -- CustomAgentChatView.test.tsx)
Test Files  1 passed (1)
Tests  72 passed (72)
Duration  4.36s

Conclusion:

  • Le smoke automatisé backend BackendCore::activate_project() couvre l'équivalent fermeture/redémarrage: live-state working corrélé persisté + background task Running orpheline -> activation -> live-state idle, correlation_id/ticket/délégation effacés, task Failed, aucune task ouverte reprojetable.
  • La réconciliation background est bien bornée par projectId et ne terminalise/rapporte pas les tâches étrangères.
  • Le correctif backend suffit pour le défaut live-state/background-task fantôme validé ici.
  • Risque résiduel frontend: le message Conversation liée — récupération du transcript en cours. peut encore apparaître avec un conversationId isolé sans tours récupérés; le garde-fou UX reste pertinent comme lot séparé si ce cas persiste après backend assaini.

2026-09-10 — DevFrontend (réouverture QA)

Diagnostic:

  • Le rendu vide de CustomAgentChatView utilisait hasLinkedConversation après la fin de openOrAttach, sans distinguer une récupération encore active d'une récupération terminée sans aucun tour.
  • Un conversationId isolé suffisait donc à conserver indéfiniment le libellé Conversation liée — récupération du transcript en cours. après un retour utile vide.

Implémentation minimale:

  • frontend/src/features/agents/CustomAgentChatView.tsx: une fois opening terminé et sans tour affichable, une conversation toujours liée affiche désormais littéralement Conversation liée — transcript indisponible.. Le spinner reste borné à opening; la cellule et le conversationId ne sont ni fermés ni effacés.
  • frontend/src/features/agents/CustomAgentChatView.test.tsx: le test ciblé QA attend le nouvel état terminal et vérifie l'absence de l'ancien libellé, de spinner et de bouton Réessayer dans le scénario de récupération vide.
  • Les alertes techniques existantes restent inchangées afin de ne pas masquer les erreurs de lancement/rattachement hors de ce scénario vide.

Commandes exécutées:

$ (cd frontend && npm test -- CustomAgentChatView.test.tsx)
Test Files  1 passed (1)
Tests  72 passed (72)
Duration  4.04s
$ (cd frontend && npm run typecheck)
tsc --noEmit
exit 0
$ git diff --check
<no output, exit 0>

Risque résiduel:

  • Le correctif repose sur la terminaison de la tentative openOrAttach; il ne crée pas un nouveau timeout frontend autour d'un appel transport qui ne se résoudrait jamais. Cette extension serait hors du garde-fou minimal demandé et modifierait le contrat de transport.

2026-09-10 — QA finale après garde-fou frontend

Verdict QA final: VERT pour #307, backend + garde-fou frontend.

Relu:

  • Diff backend/domain/infrastructure déjà validé: réconciliation live-state avec correlation_id effacé, réconciliation background bornée par projectId, smoke BackendCore::activate_project().
  • Diff frontend: CustomAgentChatView.tsx remplace l'état vide post-récupération par Conversation liée — transcript indisponible..
  • Test frontend: CustomAgentChatView.test.tsx couvre le cas conversationId isolé sans tours récupérés et vérifie l'absence de l'ancien libellé, du spinner et du bouton Réessayer.

Commandes exécutées et sorties réelles:

$ git diff --check
<no output, exit 0>
$ cargo test -p domain live_state::tests::reconcile_orphans
running 4 tests
test live_state::tests::reconcile_orphans_does_not_mutate_self ... ok
test live_state::tests::reconcile_orphans_covers_working_waiting_blocked_only ... ok
test live_state::tests::reconcile_orphans_spares_live_agents ... ok
test live_state::tests::reconcile_orphans_downgrades_dead_active_rows_and_rewrites_fields ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 307 filtered out; finished in 0.00s
$ cargo test -p infrastructure --test background_task_store reconcile
running 4 tests
test reconcile_uses_monotonic_timestamp_when_clock_is_behind ... ok
test reconcile_marks_cancelling_without_live_handle_cancel_failed_and_pending ... ok
test project_reconcile_does_not_repair_or_report_foreign_project_tasks ... ok
test reconcile_marks_running_without_live_handle_failed_and_pending ... ok
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 8 filtered out; finished in 0.00s
$ cargo test -p backend ticket307_activation_reconcile_tests
running 1 test
test ticket307_activation_reconcile_tests::activate_project_clears_stale_live_correlation_and_terminalizes_orphan_task ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 101 filtered out; finished in 0.01s
$ cargo test -p backend background_tasks_b7_tests
running 1 test
test background_tasks_b7_tests::app_reconcile_requeues_wake_owner_marks_record_only_and_repairs_orphan_running ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 101 filtered out; finished in 0.00s
$ cargo test -p application --test workstate
running 29 tests
...
test workstate_lists_two_tickets_in_fifo_order ... ok
test result: ok. 29 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
$ (cd frontend && npm test -- CustomAgentChatView.test.tsx)
Test Files  1 passed (1)
Tests  72 passed (72)
Duration  3.97s
$ (cd frontend && npm run typecheck)
> idea-frontend@0.3.0 typecheck
> tsc --noEmit

Conclusion:

  • Le backend ne reprojette plus l'activité fantôme validée par le smoke d'activation.
  • Le frontend ne reste plus sur Conversation liée — récupération du transcript en cours. après récupération vide; il affiche un état terminal explicite Conversation liée — transcript indisponible..
  • Risque résiduel limité: le garde-fou frontend suppose toujours que openOrAttach finit par se résoudre/rejeter; il n'ajoute pas de timeout transport.

Git — 2026-09-10

  • Reprise après déblocage; état laissé par la session Git précédente (interrompue après le merge) inspecté puis validé.
  • Branche: fix/307-startup-ghost-states-reconciliation créée depuis develop @ 99b400a; commit fix 57cf825 (6 fichiers domain/infrastructure/backend/frontend), QA verte reconfirmée par Git avant commit.
  • Merge no-ff vers develop: e1dbe56; branche feature conservée après merge (convention récente).
  • Rebuild AppImage du 14:21 déjà formalisé en amont du merge: commit dédié 99b400a (vide, trace durable in-repo) + tag annoté v0.46.0.
  • Vérifications à la reprise: git diff eb86366..e1dbe56 --stat = exactement les 6 fichiers du correctif; artefact target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage (119871992 octets, mtime 2026-09-10 14:21:49) de sha256 e6e22132970357d8a67338edaf4c3b0adbee7a66265e09211e733abfa08825da identique à celui documenté par 99b400a — l'AppImage v0.46.0, buildée depuis le worktree incluant le WIP #307 complet, correspond au contenu de develop post-merge. Décision: aucun nouveau rebuild ni incrément de tag, un même artefact ne porte pas deux versions.
  • Store de tickets synchronisé sur develop dans le chore(tickets) portant ce carnet (tickets 299-307, index/counter, #296); attachments/ et scripts/ maintenus hors périmètre non suivis.
  • Aucun push (develop en avance de 320 commits sur origin/develop).
  • Restants: remplacement de l'AppImage installée par l'artefact v0.46.0 + relance manuels, validation live fermeture/relance (plus de LED fantôme ni de spinner transcript infini), puis clôture du ticket.