pub struct AgentOrchestrator { /* private fields */ }Expand description
The main orchestrator that runs the dark factory.
Implementations§
Source§impl AgentOrchestrator
impl AgentOrchestrator
pub fn validate_agent_runtime( &self, request: &AgentRunRequest, ) -> Result<AgentRuntimeValidationReport, OrchestratorError>
Source§impl AgentOrchestrator
impl AgentOrchestrator
Sourcepub fn new(config: OrchestratorConfig) -> Result<Self, OrchestratorError>
pub fn new(config: OrchestratorConfig) -> Result<Self, OrchestratorError>
Create a new orchestrator from configuration.
Sourcepub fn from_config_file(
path: impl AsRef<Path>,
) -> Result<Self, OrchestratorError>
pub fn from_config_file( path: impl AsRef<Path>, ) -> Result<Self, OrchestratorError>
Create from a TOML config file path.
Loads the config, resolves include globs, and runs full validation
(banned providers, duplicate project ids, unknown project refs, mixed
mode). Returns Err if any check fails – does not panic or warn-and-
continue.
Sourcepub fn config(&self) -> &OrchestratorConfig
pub fn config(&self) -> &OrchestratorConfig
Return the validated configuration stored in this orchestrator.
Sourcepub fn dispatcher(&self) -> &Dispatcher
pub fn dispatcher(&self) -> &Dispatcher
Read-only access to the unified dispatcher queue.
Integration tests use this to assert that ROC v1 Step F polling
enqueued the expected dispatcher::DispatchTask::AutoMerge work without the
test itself holding a reference to the internal dispatcher.
Sourcepub fn auto_merge_enqueued(&self) -> &AutoMergeDedupeSet
pub fn auto_merge_enqueued(&self) -> &AutoMergeDedupeSet
Read-only access to the in-memory (project, pr_number, head_sha)
dedupe set populated by ROC v1 Step F polling and the Step G
AutoMerge handler. Integration tests use this to assert that a
successful merge leaves the revision recorded so subsequent polls
never re-enqueue the same auto-merge.
Sourcepub async fn run(&mut self) -> Result<(), OrchestratorError>
pub async fn run(&mut self) -> Result<(), OrchestratorError>
Run the orchestrator (blocks until shutdown signal).
- Spawns all Safety-layer agents immediately
- Enters the select! loop handling schedule events, drift alerts, and periodic tick
Sourcepub fn agent_statuses(&self) -> Vec<AgentStatus>
pub fn agent_statuses(&self) -> Vec<AgentStatus>
Get current status of all agents.
Sourcepub async fn trigger_compound_review(
&mut self,
git_ref: &str,
base_ref: &str,
) -> Result<CompoundReviewResult, OrchestratorError>
pub async fn trigger_compound_review( &mut self, git_ref: &str, base_ref: &str, ) -> Result<CompoundReviewResult, OrchestratorError>
Manually trigger a compound review (outside normal schedule).
Sourcepub async fn handoff(
&mut self,
from_agent: &str,
to_agent: &str,
context: HandoffContext,
) -> Result<(), OrchestratorError>
pub async fn handoff( &mut self, from_agent: &str, to_agent: &str, context: HandoffContext, ) -> Result<(), OrchestratorError>
Hand off a task from one agent to another.
Sourcepub fn latest_handoff_for(&self, to_agent: &str) -> Option<&HandoffContext>
pub fn latest_handoff_for(&self, to_agent: &str) -> Option<&HandoffContext>
Get the most recent handoff for a specific target agent. Returns the handoff context with the latest timestamp that hasn’t expired.
Sourcepub fn router(&self) -> &RoutingEngine
pub fn router(&self) -> &RoutingEngine
Get a reference to the routing engine.
Sourcepub fn router_mut(&mut self) -> &mut RoutingEngine
pub fn router_mut(&mut self) -> &mut RoutingEngine
Get a mutable reference to the routing engine.
Sourcepub fn rate_limiter(&self) -> &RateLimitTracker
pub fn rate_limiter(&self) -> &RateLimitTracker
Get a reference to the rate limiter.
Sourcepub fn rate_limiter_mut(&mut self) -> &mut RateLimitTracker
pub fn rate_limiter_mut(&mut self) -> &mut RateLimitTracker
Get a mutable reference to the rate limiter.
Sourcepub fn cost_tracker(&self) -> &CostTracker
pub fn cost_tracker(&self) -> &CostTracker
Get a reference to the cost tracker.
Sourcepub fn cost_tracker_mut(&mut self) -> &mut CostTracker
pub fn cost_tracker_mut(&mut self) -> &mut CostTracker
Get a mutable reference to the cost tracker.
pub fn set_quickwit_sink(&mut self, sink: QuickwitFleetSink)
pub fn quickwit_config(&self) -> Option<&QuickwitConfig>
Sourcepub fn quickwit_fleet_configs(&self) -> Vec<(String, QuickwitConfig)>
pub fn quickwit_fleet_configs(&self) -> Vec<(String, QuickwitConfig)>
Enumerate per-project Quickwit configurations plus a legacy fallback
for the top-level config, so the binary can build a
quickwit::QuickwitFleetSink covering every project.
Returns (project_id, QuickwitConfig) pairs. Projects without a
per-project Quickwit block inherit the top-level config. The legacy
single-project path emits a single entry keyed on
crate::dispatcher::LEGACY_PROJECT_ID.
Sourcepub async fn poll_pending_reviews(&mut self) -> Result<(), OrchestratorError>
pub async fn poll_pending_reviews(&mut self) -> Result<(), OrchestratorError>
Poll every project with a Gitea config for open PRs, parse the latest
structural-pr-review comment, and enqueue dispatcher::DispatchTask::AutoMerge
for any PR that clears every gate in
pr_review::AutoMergeCriteria::default.
Called once per reconcile tick after the
dispatcher has been drained so AutoMerge tasks enqueued here are
serviced on the next tick (deterministic ordering). The method is a
no-op when no project has a gitea config.
This is ROC v1 Step F — it enqueues auto-merge but does not
actually merge the PR; that lands in Step G. Dedupe is process-local
via pr_poller::AutoMergeDedupeSet; durable tracking is Step I.
Sourcepub async fn poll_pending_reviews_for_project<T: PrTracker + ?Sized>(
&mut self,
project_id: &str,
tracker: &T,
criteria: &AutoMergeCriteria,
)
pub async fn poll_pending_reviews_for_project<T: PrTracker + ?Sized>( &mut self, project_id: &str, tracker: &T, criteria: &AutoMergeCriteria, )
Inner per-project verdict poll. Accepts a generic pr_poller::PrTracker
so integration tests can drive it with an in-memory tracker.
Sourcepub async fn handle_auto_merge(
&mut self,
task: DispatchTask,
) -> Result<(), OrchestratorError>
pub async fn handle_auto_merge( &mut self, task: DispatchTask, ) -> Result<(), OrchestratorError>
Execute a DispatchTask::AutoMerge task — ROC v1 Step G.
Builds the per-project pr_poller::GiteaPrTracker from config and
delegates to AgentOrchestrator::handle_auto_merge_for_project.
The task’s project field must match a configured project with a
gitea block (or, for legacy configs, the top-level gitea);
otherwise the call logs-and-skips so the dispatcher keeps draining.
Sourcepub async fn handle_auto_merge_for_project<T: AutoMergeExecutor + ?Sized>(
&mut self,
task: DispatchTask,
tracker: &T,
) -> Result<(), OrchestratorError>
pub async fn handle_auto_merge_for_project<T: AutoMergeExecutor + ?Sized>( &mut self, task: DispatchTask, tracker: &T, ) -> Result<(), OrchestratorError>
Inner AutoMerge executor. Accepts any pr_poller::AutoMergeExecutor
so integration tests can drive the full handler with an in-memory
tracker. Real production code funnels through
AgentOrchestrator::handle_auto_merge.
Steps:
- Defensive re-check: list open PRs on the project. Skip when the PR is absent (already closed/merged) or the HEAD SHA has moved.
- Attempt the merge.
- On success — enqueue
DispatchTask::PostMergeTestGate, record the(pr, head_sha)in the dedupe set so late polls never re-enqueue the same revision. - On failure — open an
[ADF]tracking issue with the failure reason viapr_poller::AutoMergeExecutor::open_failure_issue; do not enqueue a post-merge gate.
Sourcepub async fn handle_post_merge_test_gate(
&mut self,
task: DispatchTask,
) -> Result<(), OrchestratorError>
pub async fn handle_post_merge_test_gate( &mut self, task: DispatchTask, ) -> Result<(), OrchestratorError>
Execute a DispatchTask::PostMergeTestGate task — ROC v1 Step H.
Defers the heavy lifting to post_merge_gate::run_workspace_tests
and post_merge_gate::revert_merge so those helpers stay fully
testable without orchestrator state. This method resolves the
project’s working_dir as repo_root, constructs the post_merge_gate::GateConfig
(picking up any overrides from [post_merge_gate] in
orchestrator.toml), and funnels the result through the inner
handle_post_merge_test_gate_for_project helper which takes a
post_merge_gate::CommandRunner so integration tests can drive the
full handler with a scripted runner.
Sourcepub async fn handle_post_merge_test_gate_with_runner<R>(
&mut self,
task: DispatchTask,
runner: &R,
) -> Result<(), OrchestratorError>where
R: CommandRunner + ?Sized,
pub async fn handle_post_merge_test_gate_with_runner<R>(
&mut self,
task: DispatchTask,
runner: &R,
) -> Result<(), OrchestratorError>where
R: CommandRunner + ?Sized,
Inner handler that accepts any post_merge_gate::CommandRunner.
Integration tests use a post_merge_gate::ScriptedRunner here to
assert on the exact cargo test / git revert / git push call
sequence without spawning real processes.
On green: logs post_merge_gate_verified at info.
On red: classifies the failure, runs git revert, pushes to the
configured remote, opens an [ADF] post-merge test gate reverted
tracking issue on the project’s Gitea repo, and logs
post_merge_gate_reverted at warn. Returns Ok(()) in every
case the dispatcher should continue draining — only hard I/O
errors that prevent even the attempt return Err.
Auto Trait Implementations§
impl Freeze for AgentOrchestrator
impl !RefUnwindSafe for AgentOrchestrator
impl Send for AgentOrchestrator
impl Sync for AgentOrchestrator
impl Unpin for AgentOrchestrator
impl UnsafeUnpin for AgentOrchestrator
impl !UnwindSafe for AgentOrchestrator
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more