// Package orchestration implements the sub-agent orchestration layer of the // Cyrene v2 runtime (DevDocs/design/04-运行时.md §2 and DevDocs/design/05-子代理.md). // // When the front session (agent loop) decides a task is complex it hot-switches to // orchestration mode and spawns background sub-agents that run concurrently // without blocking the front session. Each sub-agent is an agent instance bound // to a role + behavior mode, executing in an isolated context with its own // working memory. Progress and status are streamed back to the front session via // the agent-to-agent bus, and once all sub-agents finish their outcomes are // merged for the front session. // // # Lifecycle // // A Scheduler is created once via New with its injected dependencies (a loop // template, the bus, an optional comm probe, memory/sink, tracer, approver). A // sub-agent is created with Spawn, which registers it, publishes a "dispatched" // progress event and launches its execution in the background. The execution is // gated by MaxParallel so at most that many sub-agents run at once; excess ones // queue. Each run is bounded by PerAgentTimeout. The sub-agent moves // pending -> running -> one of {done, failed, aborted}, and on every terminal // transition a summary is written and a progress event is published. Abort and // CancelAll stop a single sub-agent or every sub-agent (anti-runaway). // // # Result merging // // Join waits until every spawned sub-agent reaches a terminal state (or ctx is // canceled) and returns a MergedResult aggregating each sub-agent's summary and // loop result. // // # Isolation // // Sub-agent context and working memory are isolated by construction: Spawn deep // copies Spec.Context into SubAgent.Context and creates a fresh WorkingMemory per // sub-agent, so a sub-agent never shares the front session's context. // // # Governance // // Sensitive operations are audited through the injected *audit.Approver (see // Approve): policy judgement belongs to the upper layer; the scheduler only // triggers the audit record. Task-memory sinking is available through SinkMemory, // which delegates to the injected *memory.Store so scope classification // (user/persona/project) stays at the call site. package orchestration