chore(wip): état runtime .ideai (flux conversation live)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -76,3 +76,5 @@
|
||||
{"id":"b9900b46-41ff-4276-a225-991520cf0923","conversation":"d5068bc8-786e-0428-1d14-83b93961a15e","atMs":1781976051405,"source":{"kind":"agent","agentId":"73c853d1-c0fd-463b-ad17-1d24fefa371f"},"role":"response","text":"Lot C backend/Tauri `workstate conversation summaries` **implémenté et vert** sur `feature/workstate-conversation-summaries`. **Rien commité.**\n\n## Fichiers modifiés (6 ; aucun infra/domain — ports HandoffStore/ConversationLog réutilisés)\n- `crates/application/src/workstate/mod.rs` — modèle + algo best-effort\n- `crates/application/src/lib.rs` — re-exports\n- `crates/app-tauri/src/dto.rs` — DTO camelCase\n- `crates/app-tauri/src/state.rs` — wiring composition root\n- `crates/application/tests/workstate.rs` — fakes + 9 tests\n- `crates/app-tauri/tests/dto_agents.rs` — +1 test + 2 littéraux existants mis à jour\n\n## Signatures/types ajoutés\n**Application :**\n- `ProjectWorkState.conversations: Vec<ConversationWorkSummary>` (top-level)\n- `ConversationWorkSummary { conversation_id, status, objective_preview: Option<String>, summary_preview: Option<String>, summary_len: usize, up_to: Option<TurnId>, recent_turns: Vec<ConversationTurnWorkPreview> }`\n- `enum ConversationPreviewStatus { Ready, Missing, Partial, Unavailable }`\n- `ConversationTurnWorkPreview { role: TurnRole, source: TicketWorkSource, at_ms: u64, text_preview: String, text_len: usize }`\n- `trait ConversationLogProvider { fn conversation_log_for(&self, root: &ProjectPath) -> Option<Arc<dyn ConversationLog>> }` (nouveau, jumeau de `HandoffProvider`)\n- `GetProjectWorkState::with_conversation_sources(handoffs: Arc<dyn HandoffProvider>, logs: Arc<dyn ConversationLogProvider>)` (builder)\n- Constantes : `HANDOFF_PREVIEW_MAX_CHARS=480`, `OBJECTIVE_PREVIEW_MAX_CHARS=160`, `RECENT_TURNS_MAX=3`, `TURN_PREVIEW_MAX_CHARS=220`\n\n**DTO Tauri :** `ProjectWorkStateDto.conversations`, `ConversationWorkSummaryDto`, `ConversationPreviewStatusDto` (`ready/missing/partial/unavailable`), `ConversationTurnWorkPreviewDto`. **state.rs :** `AppConversationLogProvider` (matérialise `FsConversationLog::new(root)`), câblé via `.with_conversation_sources(AppHandoffProvider, AppConversationLogProvider)`.\n\n## Choix exacts / divergences\n1. **Réutilisé `HandoffProvider` existant (P7)** comme source primaire + ajouté le jumeau `ConversationLogProvider` pour le repli. Résolus **par project root** (`input.project.root`) car `GetProjectWorkState` est singleton AppState alors que les `Fs*` figent leur racine à la construction — strictement parallèle au pattern P7/P8b.\n2. **Builder `with_conversation_sources`** plutôt que d'étendre `new(...)` : sources OFF par défaut, zéro régression sur call sites/tests existants (best-effort absent = aucune summary).\n3. **« provider non câblé » = handoff Absent (chemin Missing), jamais une erreur.** `Unavailable` strictement = handoff **erreur** ET log erreur/absent. `Missing` reste Missing même si le log échoue (alors recentTurns vide). Conforme aux étapes 4/5/6 du cadrage.\n4. **Ready** ne remplit pas `recent_turns` (le handoff EST le résumé) ; recentTurns peuplé seulement en Missing/Partial. Re-cap défensif à `RECENT_TURNS_MAX` en plus de `log.last(_, 3)`.\n5. **Dédup** des `conversation_id` sur tous les tickets projetés (humains inclus), **ordre first-seen** pour refléter l'ordre du panneau.\n6. **`TurnRole` domaine réutilisé tel quel dans le DTO** (sérialise déjà camelCase `prompt/response/toolActivity`), cohérent avec le réemploi de `AgentBusyState` ; `source` du tour réutilise `TicketWorkSourceDto` (`kind: human/agent`).\n7. **Champs preview optionnels sérialisés en `null`** quand absents (pas omis) — prévisible pour le front, aligné sur le pattern `live` (divergence assumée vs `ConversationDetailsDto` qui omet).\n8. **Normalisation factorisée** : helper `preview(text, max)` partagé (trim + collapse whitespace + troncature char-safe), `task_preview` (Lot B) refactoré dessus.\n\n## Commandes exécutées + résultats réels\n- `cargo fmt --all -- --check` → **clean** (après `cargo fmt --all`).\n- `cargo test -p application --test workstate` → **21 passed; 0 failed** (12 existants + 9 nouveaux : has_no_conversations, dedups, ready, missing+bounded(3), partial, unavailable, preview_failure_preserves_agents/live/busy/tickets, previews_truncated+normalised, turn_text_truncated).\n- `cargo test -p app-tauri --test dto_agents` → **21 passed; 0 failed** (+1 `project_work_state_dto_serialises_conversations_camelcase`).\n- `cargo check -p app-tauri` → **clean** (domain/application/infrastructure/app-tauri compilent).\n\nPas d'adapter infra créé (réemploi de `FsHandoffStore`/`FsConversationLog` existants). Dirty runtime `.ideai/*` ignoré. Reste : types TS (DevFrontend) + commit/merge (Git) + validation e2e."}
|
||||
{"id":"0834676a-dc01-4cdf-97a4-37cff81bf3d2","conversation":"d5068bc8-786e-0428-1d14-83b93961a15e","atMs":1781976363926,"source":{"kind":"agent","agentId":"a6ced819-b893-4213-b003-9e9dc79b9641"},"role":"prompt","text":"QA Lot C est verte mais signale un warning Rust non bloquant: `variant Absent is never constructed` dans `crates/application/tests/workstate.rs:173:5`, probablement un enum/fake de test `HandoffOutcome::Absent` inutilisé.\n\nMerci de nettoyer ce warning de façon minimale sans changer le comportement applicatif, puis relance au moins:\n- `cargo fmt --all -- --check`\n- `cargo test -p application --test workstate`\n\nNe committe pas. Retourne le diff conceptuel, les fichiers modifiés, et les résultats réels."}
|
||||
{"id":"8e30c171-2d32-48ab-9971-c6d23a010052","conversation":"d5068bc8-786e-0428-1d14-83b93961a15e","atMs":1781976412762,"source":{"kind":"agent","agentId":"73c853d1-c0fd-463b-ad17-1d24fefa371f"},"role":"response","text":"Warning nettoyé. **Rien commité.**\n\n## Diff conceptuel\nLa variante `HandoffOutcome::Absent` du fake de test n'était jamais construite : l'absence de handoff était déjà modélisée en **ne configurant pas** la conversation (le `load` du fake retombait sur l'arm `_ => Ok(None)`). Correctif minimal, zéro impact applicatif (uniquement le fixture de test) :\n- Suppression de la variante `Absent` (+ doc-comment expliquant que l'absence = conversation non configurée).\n- Le match de `FakeHandoffStore::load` passe de `_ => Ok(None)` à `None => Ok(None)` (désormais exhaustif sur `Present`/`Error`/`None`, plus de wildcard).\nAucun test ne référençait `Absent` (le test `missing` repose sur une conversation non configurée), donc aucune logique de test ni d'assertion modifiée.\n\n## Fichier modifié\n- `crates/application/tests/workstate.rs` (uniquement)\n\n## Résultats réels\n- `cargo fmt --all -- --check` → **clean** (exit 0).\n- `cargo test -p application --test workstate` → **21 passed; 0 failed**, **aucun warning** (le `variant Absent is never constructed` a disparu)."}
|
||||
{"id":"6092e15f-2659-4986-960a-0a1b3bc705ff","conversation":"d5068bc8-786e-0428-1d14-83b93961a15e","atMs":1781976761247,"source":{"kind":"agent","agentId":"a6ced819-b893-4213-b003-9e9dc79b9641"},"role":"prompt","text":"Implémente le backend/Tauri du Lot D `workstate controlled actions` sur la branche active `feature/workstate-controlled-actions`.\n\nPérimètre backend prioritaire:\n1. Faire porter Attach par un contrat agent-level fiable, sans spawn:\n - Use case applicatif `AttachLiveAgent` si nécessaire.\n - Input: `project`, `agent_id`, `node_id`.\n - Output: `agent_id`, `node_id`, `session_id`, `kind: LiveSessionKind`.\n - Comportement: chercher la session live par agent dans PTY puis structured, rebind `node_id` sans créer de session, idempotent si déjà attaché à ce node, NOT_FOUND si agent non live.\n - Ne touche pas log/handoff/provider sessions.\n\n2. Ajouter `StopLiveAgent` agent-level:\n - Input: `project`, `agent_id`.\n - Output: `agent_id`, `session_id`, `kind`.\n - Comportement: résoudre la session live par agent; si PTY déléguer à la primitive existante de fermeture/kill et retirer registry; si structured shutdown + retirer registry; NOT_FOUND si absent.\n - Ne supprime pas agent, tickets, conversation summary, handoff.\n - Publier/laisser publier les events existants d'exit si l'infra le fait déjà; ne pas inventer un bus si absent.\n\n3. Tauri:\n - Commandes camelCase:\n - `attach_live_agent({ request: { projectId, agentId, nodeId } }) -> { agentId, nodeId, sessionId, kind }`\n - `stop_live_agent({ request: { projectId, agentId } }) -> { agentId, sessionId, kind }`\n - Réutiliser/enrichir DTO `LiveAgent` si cohérent, sinon DTO dédié.\n - Mapper INVALID ids et NOT_FOUND.\n\nContraintes:\n- Ne pas lancer d'agent neuf, ne jamais appeler `launch_agent`.\n- Ne pas créer de cellule/layout côté backend pour Lot D.\n- Ne pas modifier le frontend.\n- Ne committe pas.\n- Ignore dirty runtime `.ideai/*`.\n\nTests attendus:\n- Application Rust: attach PTY rebind sans changer `session_id`; attach structured; attach absent NOT_FOUND; attach même node idempotent; stop PTY retire session live; stop structured shutdown + retire; stop absent NOT_FOUND.\n- App-tauri tests DTO/command wiring: request/response camelCase, `kind`, INVALID/NOT_FOUND si conventions existantes le permettent.\n\nCommandes minimales:\n- `cargo fmt --all -- --check`\n- tests ciblés application pertinents (à choisir selon modules existants)\n- tests app-tauri pertinents\n- `cargo check -p app-tauri`\n\nRetourne fichiers modifiés, signatures/commandes ajoutées, résultats réels, et blocages/écarts éventuels."}
|
||||
{"id":"ec87367b-50e1-44fb-b4dd-88c284f02cae","conversation":"d5068bc8-786e-0428-1d14-83b93961a15e","atMs":1781977281733,"source":{"kind":"agent","agentId":"73c853d1-c0fd-463b-ad17-1d24fefa371f"},"role":"response","text":"Lot D `workstate controlled actions` **implémenté et vert** sur `feature/workstate-controlled-actions`. **Rien commité.**\n\n## Fichiers modifiés / créés\n- **NOUVEAU** `crates/application/src/workstate/actions.rs` — use cases `AttachLiveAgent` + `StopLiveAgent`\n- **NOUVEAU** `crates/application/tests/workstate_actions.rs` — 7 tests\n- `crates/application/src/workstate/mod.rs` — `mod actions;` + re-exports\n- `crates/application/src/lib.rs` — re-exports crate-root\n- `crates/app-tauri/src/dto.rs` — DTO request/response\n- `crates/app-tauri/src/commands.rs` — commande `attach_live_agent` réécrite + `stop_live_agent`\n- `crates/app-tauri/src/state.rs` — wiring composition root + champs AppState\n- `crates/app-tauri/src/lib.rs` — enregistrement `stop_live_agent` dans le handler\n- `crates/app-tauri/tests/dto_agents.rs` — 4 tests DTO\n\n## Signatures ajoutées\n**Application :**\n- `AttachLiveAgent::new(live: Arc<LiveSessions>)` ; `execute(AttachLiveAgentInput { project, agent_id, node_id }) -> Result<AttachLiveAgentOutput { agent_id, node_id, session_id, kind: LiveSessionKind }, AppError>` (sync — rebind pur).\n- `StopLiveAgent::new(live: Arc<LiveSessions>, close: Arc<CloseTerminal>)` ; `async execute(StopLiveAgentInput { project, agent_id }) -> Result<StopLiveAgentOutput { agent_id, session_id, kind }, AppError>`.\n\n**Tauri (camelCase) :**\n- `attach_live_agent({ request: { projectId, agentId, nodeId } }) -> { agentId, nodeId, sessionId, kind }`\n- `stop_live_agent({ request: { projectId, agentId } }) -> { agentId, sessionId, kind }`\n- DTO dédiés `AttachLiveAgentResponseDto` / `StopLiveAgentRequestDto` / `StopLiveAgentResponseDto` ; `kind` réutilise `LiveWorkSessionKindDto` (`pty`/`structured`).\n\n## Choix exacts / écarts\n1. **Attach = use case dédié** (l'ancienne commande ne gérait que le PTY via `rebind_agent_node` direct) : désormais PTY **puis** structured, idempotent (rebind sur le même node = no-op renvoyant la même session), NOT_FOUND sinon. Zéro spawn, ne touche pas log/handoff/provider sessions.\n2. **Stop polymorphe** : PTY → délègue à la primitive existante `CloseTerminal` (remove registry + kill) ; structured → `remove` puis `shutdown()`. Ne supprime ni agent, ni tickets, ni summary, ni handoff. Aucun bus inventé — l'event d'exit est laissé à l'infra existante (pump PTY / backend session).\n3. **Ordre PTY-first** pour les deux (conforme au libellé cadrage « PTY puis structured » et à `LiveSessions::session_id_for_agent`) ; non ambigu par l'invariant « 1 session vivante/agent ».\n4. **`project` accepté mais non utilisé pour la logique** (registres globaux par agent) — gardé pour la frontière/symétrie, pas de check manifest (le cadrage ne l'exige pas).\n5. **⚠️ ÉCART contrat frontend** : `attach_live_agent` renvoyait `LiveAgentListDto` (tableau) ; il renvoie désormais l'objet `{ agentId, nodeId, sessionId, kind }` imposé par le cadrage. Je n'ai **pas** touché le frontend (consigne respectée) ⇒ **mismatch transitoire FE/BE à réconcilier par DevFrontend dans son Lot D**. À flaguer.\n6. Pas de cellule/layout créée côté backend (hors périmètre Lot D).\n\n## Résultats réels\n- `cargo fmt --all -- --check` → **clean** (après `cargo fmt --all`).\n- `cargo test -p application --test workstate_actions` → **7 passed; 0 failed** (attach PTY rebind sans changer session_id ; attach structured ; attach absent NOT_FOUND ; attach même node idempotent ; stop PTY kill+remove ; stop structured shutdown+remove ; stop absent NOT_FOUND).\n- `cargo test -p application --test workstate` → **21 passed** (non-régression Lots A/B/C).\n- `cargo test -p app-tauri --test dto_agents` → **25 passed** (+4 nouveaux : request/response camelCase + `kind` pour attach & stop ; pas de fuite snake_case).\n- `cargo test -p app-tauri --test list_live_agents_r0b` → **5 passed** (non-régression de la liste live).\n- `cargo check -p app-tauri` → **clean**.\n\n## Blocages\nAucun blocage technique. Seul point d'attention : l'écart de contrat (#5) qui requiert l'adaptation frontend (DevFrontend) + commit/merge (Git) + validation e2e. Dirty runtime `.ideai/*` ignoré."}
|
||||
|
||||
Reference in New Issue
Block a user