diff --git a/hive-c0re/src/job_queue/mod.rs b/hive-c0re/src/job_queue/mod.rs index a812d4ec..597a564f 100644 --- a/hive-c0re/src/job_queue/mod.rs +++ b/hive-c0re/src/job_queue/mod.rs @@ -201,6 +201,12 @@ impl JobQueue { /// roots re-parented to the container). Returns the container's id as the /// DAG id — its rolled-up state is the DAG state. /// + /// The container is an ordinary node: it declares no resources, so the + /// scheduler claims it on the next pass, runs its (empty) logic and parks + /// it in `Finishing`, at which point its children become runnable. Nothing + /// here completes it by hand — a node with no work of its own still goes + /// the way every other node goes. + /// /// Takes the spec's recipe by generic, not as a boxed closure: a spec /// travels from the template that built it directly into this call, so /// there is nothing to allocate for. @@ -222,11 +228,6 @@ impl JobQueue { ) .map_err(|e| anyhow::anyhow!("job_queue: container insert failed: {e}"))?; insert_group(&mut inner, spec.declare, Some(container))?; - // Settle the container's own (no-op) logic immediately so it parks in - // `Finishing` and its children become runnable — it never needs claiming - // or executing, and stays out of `claim_ready`. It rolls up terminal when - // its whole subtree settles (that's the DAG-done signal). - inner.complete(container, Outcome::Done); drop(inner); self.notify.notify_one(); Ok(container.get()) diff --git a/hive-jobq/src/scheduler.rs b/hive-jobq/src/scheduler.rs index dadbac0d..1ab6015d 100644 --- a/hive-jobq/src/scheduler.rs +++ b/hive-jobq/src/scheduler.rs @@ -306,14 +306,10 @@ impl Scheduler { /// propagates up the parent chain. Claim again afterwards to start /// newly-unblocked work. /// - /// ⚠️ **Still `pub` for one caller**, and that caller is the last hole in - /// this wall: a host inserting a group root with no logic of its own - /// completes it immediately so it parks in `Finishing` and its children - /// become runnable. That is a statement about the *node* ("this one has no - /// work"), not an event to report, and it wants to be expressible at - /// insert time so completion can go `pub(crate)` alongside - /// [`Self::complete_growing`]. - pub fn complete(&mut self, id: NodeId, outcome: Outcome) { + /// `pub(crate)`: completion is reachable only from inside the future + /// [`Self::claim_next`] hands back, so it is not expressible without the + /// claim it answers. + pub(crate) fn complete(&mut self, id: NodeId, outcome: Outcome) { match outcome { Outcome::Failed(error) => { // Record the reason before the terminal transition so it's set