chore(wip): checkpoint P8/C avant chantier Codex inter-agents

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>
This commit is contained in:
2026-06-13 21:42:53 +02:00
parent 4509f0db9d
commit fdcf16c387
76 changed files with 3783 additions and 1404 deletions

View File

@ -16,10 +16,10 @@ use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use domain::agent::{AgentManifest, ManifestEntry};
use domain::events::{DomainEvent, OrchestrationSource};
use domain::ids::NodeId;
use domain::ids::SkillId;
use domain::ids::{AgentId, ProfileId, ProjectId};
use domain::markdown::MarkdownDoc;
use domain::ids::NodeId;
use domain::ports::{
AgentContextStore, AgentRuntime, ContextInjectionPlan, DirEntry, EventBus, EventStream,
ExitStatus, FileSystem, FsError, IdGenerator, OutputStream, PreparedContext, ProfileStore,
@ -295,7 +295,6 @@ impl PtyPort for FakePty {
}
}
#[derive(Default, Clone)]
struct NoopBus;
impl EventBus for NoopBus {
@ -471,11 +470,7 @@ fn build_service_with_mailbox(
}
/// Pre-seeds a live PTY terminal session for `agent_id` so `ask_agent` reuses it.
fn seed_live_pty(
sessions: &TerminalSessions,
agent_id: AgentId,
session_id: SessionId,
) {
fn seed_live_pty(sessions: &TerminalSessions, agent_id: AgentId, session_id: SessionId) {
sessions.insert(
PtyHandle { session_id },
TerminalSession::starting(
@ -650,7 +645,11 @@ async fn ask_request_surfaces_reply_alongside_detail() {
let agent_id = contexts.seed_agent("architect");
let (service, mailbox, sessions) = build_service_with_mailbox(contexts.clone());
// Target already live in the PTY registry, so the ask reuses its terminal.
seed_live_pty(&sessions, agent_id, SessionId::from_uuid(Uuid::from_u128(4242)));
seed_live_pty(
&sessions,
agent_id,
SessionId::from_uuid(Uuid::from_u128(4242)),
);
let req = tmp.0.join("ask-req.json");
std::fs::write(
@ -770,7 +769,8 @@ async fn non_ask_request_omits_reply_key() {
#[test]
fn legacy_response_without_reply_round_trips_without_reintroducing_key() {
// A response payload exactly as a pre-D6b IdeA would have written it.
let legacy = r#"{"ok":true,"action":"spawn_agent","detail":"launched agent dev-backend in background"}"#;
let legacy =
r#"{"ok":true,"action":"spawn_agent","detail":"launched agent dev-backend in background"}"#;
let parsed: OrchestratorResponse =
serde_json::from_str(legacy).expect("legacy response must still parse");
@ -873,7 +873,12 @@ async fn watcher_publishes_processed_event_tagged_file_source() {
let event = found.expect("watcher must publish a processed beacon within the poll budget");
match event {
DomainEvent::OrchestratorRequestProcessed { source, ok, requester_id, .. } => {
DomainEvent::OrchestratorRequestProcessed {
source,
ok,
requester_id,
..
} => {
assert_eq!(source, OrchestrationSource::File, "fs door must tag File");
assert!(ok, "the spawn request succeeded");
assert_eq!(requester_id, "Main", "requester id = request subdirectory");