pub struct Plan {
pub goal: Option<String>,
pub aggregation: Aggregation,
pub subtasks: Vec<Subtask>,
}Expand description
A complete plan, or a fragment of one.
Serializes to TOML as an optional goal + aggregation scalar plus a
[[subtask]] array-of-tables. goal is optional precisely so a bare
[[subtask]] fragment parses (fragment-validity, §module docs).
Fields§
§goal: Option<String>The overall goal this plan pursues. None in a fragment.
aggregation: AggregationHow child results are combined back into the plan (default Concat).
subtasks: Vec<Subtask>The subtasks, as TOML [[subtask]] tables. (Rust field subtasks,
TOML key subtask.)
Implementations§
Source§impl Plan
impl Plan
Sourcepub fn from_toml_str(s: &str) -> Result<Self, Error>
pub fn from_toml_str(s: &str) -> Result<Self, Error>
Parse a plan (or fragment) from its TOML form.
§Errors
Returns the toml deserialization error on malformed input or an
unknown field (the schema is deny_unknown_fields — one canonical shape).
Sourcepub fn to_toml_string(&self) -> Result<String, Error>
pub fn to_toml_string(&self) -> Result<String, Error>
Sourcepub fn roots(&self) -> Vec<&Subtask>
pub fn roots(&self) -> Vec<&Subtask>
Root subtasks — those with no Subtask::parent (the top of the
decomposition tree).
Sourcepub fn children(&self, id: &str) -> Vec<&Subtask>
pub fn children(&self, id: &str) -> Vec<&Subtask>
Direct children of id — subtasks whose parent is id.
Sourcepub fn leaves(&self) -> Vec<&Subtask>
pub fn leaves(&self) -> Vec<&Subtask>
Leaves — subtasks that no other subtask names as parent. A leaf is the
dispatch/execute unit (a leaf is a CrewTask); a non-leaf is a branch
(grouping / aggregation). In a flat, single-level plan every subtask is a
leaf, so this degrades to “all subtasks” — the pre-tree behaviour, so
existing flat plans are unaffected.
Sourcepub fn next_ready_leaf(&self) -> Option<&Subtask>
pub fn next_ready_leaf(&self) -> Option<&Subtask>
The next ready leaf to dispatch — the execution cursor. A leaf that
is SubtaskStatus::Pending and whose every dep is
SubtaskStatus::Done. None when nothing is ready (all done, every
pending leaf is dep-blocked, or work is in flight). A dep counts as
satisfied iff the named subtask exists and is Done; an absent (e.g.
cross-fragment) dep is treated as unsatisfied, so a plan never runs a leaf
ahead of a prerequisite it cannot see.
Sourcepub fn next_dispatch(&self, parent: &Caveats) -> Option<(String, CrewTask)>
pub fn next_dispatch(&self, parent: &Caveats) -> Option<(String, CrewTask)>
The next leaf to dispatch, as (id, CrewTask) — next_ready_leaf
projected through Subtask::to_crew_task. This is the drive loop’s read
step: dispatch the CrewTask, then mark the id
Done/Failed and call again. None when the plan is complete or stalled
(every remaining leaf blocked by a non-Done dep). The id is returned
because the projected CrewTask deliberately drops it (it is the plan’s
bookkeeping, not the child’s).
Sourcepub fn mark(&mut self, id: &str, status: SubtaskStatus, result: Option<String>)
pub fn mark(&mut self, id: &str, status: SubtaskStatus, result: Option<String>)
Record a leaf’s outcome — set its status and, when
result is Some, its result. No-op if id is
absent. The drive loop calls this after each dispatch; marking a leaf
Done may unblock its dependents on the next next_dispatch, and
marking it Failed leaves them blocked (deps require Done), so the run
stops honestly at the first failure without a separate “stop” flag.
Sourcepub fn set_instruction(&mut self, id: &str, instruction: &str)
pub fn set_instruction(&mut self, id: &str, instruction: &str)
Overwrite a subtask’s instruction by id — used by failure-driven re-grounding (#692) to steer a retried leaf at the symbol’s real file.
Sourcepub fn clear_context(&mut self, id: &str)
pub fn clear_context(&mut self, id: &str)
Drop a subtask’s file scope by id (#812). Used by re-grounding: a reground means the leaf’s grounding was demonstrably wrong, so a derived-from-the-same-grounding fence is stale — the retry runs unfenced rather than deterministically re-refusing the corrected edit.
Sourcepub fn set_artifact_commit(
&mut self,
id: &str,
commit: &str,
branch: Option<&str>,
)
pub fn set_artifact_commit( &mut self, id: &str, commit: &str, branch: Option<&str>, )
#1062: bind a node to the commit that realizes it — set
artifact_ref.commit (and branch when given),
preserving any existing pr/branch. This is what lets the objective
evaluator (crate::roadmap_eval) close a Task from git truth instead of
a human mark. No-op if id is absent.
Sourcepub fn set_artifact_issue(&mut self, id: &str, issue: u64)
pub fn set_artifact_issue(&mut self, id: &str, issue: u64)
#1083: bind node id to the forge issue it realizes, preserving any
existing branch/commit/pr refs, so the objective evaluator
(crate::roadmap_eval) can require the issue CLOSED before Done.
No-op if id is absent (same contract as
set_artifact_commit).
Sourcepub fn next_uncaptured_task_under(&self, plan_id: &str) -> Option<&Subtask>
pub fn next_uncaptured_task_under(&self, plan_id: &str) -> Option<&Subtask>
#1062 auto-capture: the next Task under plan_id that still needs a commit
— the leftmost Pending Task in plan_id’s subtree whose
artifact_ref.commit is unset. None if plan_id
isn’t a Plan, or every Task beneath it is already captured or closed.
Document order encodes sibling order, so “leftmost” is the first match —
the same rule the DFS cursor uses — giving the 1-commit-→-1-Task default.
Sourcepub fn is_complete(&self) -> bool
pub fn is_complete(&self) -> bool
Every leaf is Done — the plan finished successfully (branches are
grouping nodes, so only leaf completion is load-bearing). An empty plan is
trivially complete.
Sourcepub fn next_ready_node(&self) -> Option<&Subtask>
pub fn next_ready_node(&self) -> Option<&Subtask>
#1030 tree cursor: the next node to act on in depth-first, sibling order
— the leftmost SubtaskStatus::Pending subtask whose every dep is
Done and whose direct children are all Done. Generalizes
next_ready_leaf to interior nodes: a leaf (no children) is ready as
soon as its deps clear; a branch (Roadmap/Phase/Plan grouping) becomes
ready only once its subtree has completed — which is exactly when its
evaluator should run and fold the children’s results upward, then the
cursor returns to the branch’s parent. Document order encodes sibling
order, so “leftmost” is the first match. None when nothing is ready
(all done, or every pending node is blocked by a dep or an open child).
Sourcepub fn subtree_complete(&self, id: &str) -> bool
pub fn subtree_complete(&self, id: &str) -> bool
#1030: is node id and its entire subtree Done? A missing id is
false — a node we cannot see is not provably complete (mirroring the
unsatisfied-absent-dep rule). The traversal uses this to decide when a
branch’s children have all finished so it may return up to the parent.
Sourcepub fn path_to(&self, id: &str) -> Vec<String>
pub fn path_to(&self, id: &str) -> Vec<String>
#1030: the ancestor chain from the root down to id (inclusive) as a vec
of ids — the breadcrumb a driver shows and a resume uses to descend.
Empty when id is absent. A cycle in the soft parent
pointers is broken by stopping at the first revisited id.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Plan
impl<'de> Deserialize<'de> for Plan
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Plan
impl StructuralPartialEq for Plan
Auto Trait Implementations§
impl Freeze for Plan
impl RefUnwindSafe for Plan
impl Send for Plan
impl Sync for Plan
impl Unpin for Plan
impl UnsafeUnpin for Plan
impl UnwindSafe for Plan
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<T> ErasedDestructor for Twhere
T: 'static,
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