pub struct Lineage {
pub root: Option<Node>,
pub incoming: Vec<Relation>,
pub outgoing: Vec<Relation>,
pub related_nodes: Vec<Node>,
}Fields§
§root: Option<Node>§incoming: Vec<Relation>§outgoing: Vec<Relation>Implementations§
Source§impl Lineage
impl Lineage
pub fn from_graph(graph: &Graph, id: &NodeId) -> Self
Sourcepub fn to_markdown(&self) -> String
pub fn to_markdown(&self) -> String
Examples found in repository?
examples/behavior_subscription.rs (line 46)
8async fn main() -> Result<(), Box<dyn std::error::Error>> {
9 let state = YoAgentState::load(MemoryEventStore::new()).await?;
10 let mut runtime = YoAgentRuntime::new(state.clone());
11
12 runtime.register_behavior(FnBehavior::new(
13 BehaviorId::new("behavior_failure_to_task"),
14 EventPattern::Kind("failure.observed".to_string()),
15 |_ctx: BehaviorContext, event: Event| async move {
16 let title = event
17 .payload
18 .get("title")
19 .and_then(|value| value.as_str())
20 .unwrap_or("Investigate failure");
21 Ok(vec![StateOp::CreateNode {
22 id: NodeId::new("task_from_failure"),
23 kind: "task".to_string(),
24 props: json!({
25 "title": format!("Investigate: {title}"),
26 "status": "Open",
27 "created_by_behavior": "behavior_failure_to_task",
28 }),
29 }])
30 },
31 ));
32
33 runtime
34 .emit_event(Event::new(
35 ActorRef::agent("demo"),
36 "failure.observed",
37 json!({ "title": "retry timeout loses state" }),
38 ))
39 .await?;
40
41 print!(
42 "{}",
43 state
44 .lineage(NodeId::new("task_from_failure"))
45 .await
46 .to_markdown()
47 );
48 Ok(())
49}More examples
examples/basic_lineage.rs (line 41)
5async fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let state = YoAgentState::load(MemoryEventStore::new()).await?;
7 let actor = ActorRef::agent("example");
8
9 let failure = NodeId::new("failure_retry_timeout");
10 let hypothesis = NodeId::new("hypothesis_retry_state_lost");
11
12 state
13 .apply_ops(
14 actor,
15 vec![
16 StateOp::CreateNode {
17 id: failure.clone(),
18 kind: "failure".to_string(),
19 props: json!({
20 "title": "Retry state is lost after timeout",
21 "summary": "The next retry starts from attempt zero."
22 }),
23 },
24 StateOp::CreateNode {
25 id: hypothesis.clone(),
26 kind: "hypothesis".to_string(),
27 props: json!({
28 "title": "Attempt count is scoped to the cancelled future"
29 }),
30 },
31 StateOp::CreateRelation {
32 from: hypothesis.clone(),
33 rel: "explains".to_string(),
34 to: failure,
35 props: json!({}),
36 },
37 ],
38 )
39 .await?;
40
41 print!("{}", state.lineage(hypothesis).await.to_markdown());
42 Ok(())
43}examples/patch_eval_decision.rs (line 84)
8async fn main() -> Result<(), Box<dyn std::error::Error>> {
9 let state = YoAgentState::load(MemoryEventStore::new()).await?;
10 let actor = ActorRef::agent("yoyo-evolve");
11
12 let failure = NodeId::new("failure_17");
13 state
14 .record_failure(
15 actor.clone(),
16 failure.clone(),
17 "tool_retry_survives_timeout fails",
18 "Retry state is lost when timeout cancels the future.",
19 )
20 .await?;
21
22 let patch_id = PatchId::new("patch_42");
23 let mut patch = StatePatch::new(
24 patch_id.clone(),
25 "Persist retry state across timeout",
26 "Add RetryState and keep attempt count outside the cancelled future.",
27 actor.clone(),
28 );
29 patch.evidence.push(failure);
30 patch.preconditions.push(Precondition::TestStillFailing {
31 name: "tool_retry_survives_timeout".to_string(),
32 });
33 patch.expected_effects.push(ExpectedEffect::TestPasses {
34 name: "tool_retry_survives_timeout".to_string(),
35 });
36 patch.artifacts.push(
37 ArtifactRef::new("git.diff", "file://.yoyo/artifacts/patch_42.diff")
38 .with_summary("Fix retry persistence and add timeout regression test")
39 .with_metadata(json!({
40 "base_commit": "abc123",
41 "files_changed": [
42 "crates/yoagent-runtime/src/tool.rs",
43 "crates/yoagent-runtime/tests/retry.rs"
44 ]
45 })),
46 );
47
48 state.propose_patch(patch).await?;
49 state
50 .record_eval_result(
51 actor,
52 NodeId::new("eval_55"),
53 patch_id.clone(),
54 "cargo test tool_retry_survives_timeout",
55 true,
56 )
57 .await?;
58 state
59 .record_decision(
60 ActorRef::user("yuanhao"),
61 NodeId::new("decision_9"),
62 patch_id.clone(),
63 true,
64 "Eval passed; approve promotion",
65 )
66 .await?;
67 state
68 .update_patch_status(
69 patch_id.clone(),
70 PatchStatus::Approved,
71 Some("Eval passed".to_string()),
72 )
73 .await?;
74 state
75 .update_patch_status(
76 patch_id.clone(),
77 PatchStatus::Promoted,
78 Some("Promoted as commit def456".to_string()),
79 )
80 .await?;
81
82 print!(
83 "{}",
84 state.lineage(NodeId::new(patch_id.0)).await.to_markdown()
85 );
86 Ok(())
87}examples/yoyo_evolve_demo.rs (line 83)
8async fn main() -> Result<(), Box<dyn std::error::Error>> {
9 let state = YoAgentState::load(yoagent_state::MemoryEventStore::new()).await?;
10 let actor = ActorRef::agent("yoyo-evolve");
11
12 let failure = NodeId::new("failure_retry_timeout");
13 state
14 .record_failure(
15 actor.clone(),
16 failure.clone(),
17 "Retry eval fails after timeout",
18 "The retry attempt count is reset when the timeout cancels the future.",
19 )
20 .await?;
21
22 let changed = parse_git_name_status(
23 "M crates/yoagent-runtime/src/tool.rs\nA crates/yoagent-runtime/tests/retry.rs\n",
24 );
25 let patch_id = PatchId::new("patch_retry_timeout");
26 let mut patch = StatePatch::new(
27 patch_id.clone(),
28 "Persist retry state across timeout",
29 "Move attempt count into RetryState and keep it outside the cancelled future.",
30 actor.clone(),
31 );
32 patch.base_project_ref = Some(project_ref(
33 "yoagent",
34 Some("main".to_string()),
35 Some("abc123".to_string()),
36 None,
37 ));
38 patch.evidence.push(failure);
39 patch
40 .preconditions
41 .push(Precondition::ProjectCommitIs("abc123".to_string()));
42 patch.expected_effects.push(ExpectedEffect::TestPasses {
43 name: "tool_retry_survives_timeout".to_string(),
44 });
45 patch.artifacts.push(diff_artifact(
46 ".yoyo/artifacts/patch_retry_timeout.diff",
47 "Persist retry state and add timeout regression test",
48 "abc123",
49 &changed,
50 ));
51 patch
52 .ops
53 .extend(changed_file_ops(patch_id.clone(), &changed));
54
55 state.propose_patch(patch).await?;
56 state
57 .record_eval_result(
58 actor,
59 NodeId::new("eval_retry_timeout"),
60 patch_id.clone(),
61 "cargo test tool_retry_survives_timeout",
62 true,
63 )
64 .await?;
65 state
66 .record_decision(
67 ActorRef::user("yuanhao"),
68 NodeId::new("decision_promote_retry_timeout"),
69 patch_id.clone(),
70 true,
71 "Regression test passed",
72 )
73 .await?;
74 state
75 .update_patch_status(
76 patch_id.clone(),
77 PatchStatus::Promoted,
78 Some("Promoted as commit def456".to_string()),
79 )
80 .await?;
81
82 let lineage = state.lineage(NodeId::new(patch_id.0)).await;
83 println!("{}", lineage.to_markdown());
84 println!(
85 "changed_files={}",
86 json!(changed.iter().map(|file| &file.path).collect::<Vec<_>>())
87 );
88 Ok(())
89}examples/goal_lineage.rs (line 98)
8async fn main() -> Result<(), Box<dyn std::error::Error>> {
9 let actor = ActorRef::agent("yoyo-evolve");
10 let state = YoAgentState::load(MemoryEventStore::new()).await?;
11
12 let goal = Goal {
13 status: GoalStatus::InProgress,
14 ..Goal::new(
15 GoalId::new("goal_retry_reliability"),
16 "Make retry behavior reliable",
17 "Retry attempts should survive timeout cancellation.",
18 actor.clone(),
19 )
20 };
21 state.record_goal(goal).await?;
22
23 let task = Task {
24 id: TaskId::new("task_retry_timeout"),
25 title: "Fix timeout retry state".to_string(),
26 summary: "Investigate and patch retry state loss.".to_string(),
27 status: TaskStatus::InProgress,
28 goal: Some(GoalId::new("goal_retry_reliability")),
29 created_by: actor.clone(),
30 metadata: json!({}),
31 };
32 state.record_task(task).await?;
33
34 let failure = NodeId::new("failure_retry_timeout");
35 state
36 .record_failure(
37 actor.clone(),
38 failure.clone(),
39 "retry timeout loses state",
40 "The next attempt starts from zero after cancellation.",
41 )
42 .await?;
43 state
44 .link(
45 actor.clone(),
46 failure.clone(),
47 yoagent_state::REL_BLOCKS,
48 NodeId::new("goal_retry_reliability"),
49 )
50 .await?;
51
52 let patch_id = PatchId::new("patch_retry_state");
53 let mut patch = StatePatch::new(
54 patch_id.clone(),
55 "Persist retry state",
56 "Keep attempt count outside the cancelled future.",
57 actor.clone(),
58 );
59 patch.evidence.push(failure);
60 patch.expected_effects.push(ExpectedEffect::TestPasses {
61 name: "tool_retry_survives_timeout".to_string(),
62 });
63 patch.artifacts.push(ArtifactRef::new(
64 "git.diff",
65 "file://.yoyo/artifacts/patch_retry_state.diff",
66 ));
67 state.propose_patch(patch).await?;
68 state
69 .link(
70 actor.clone(),
71 NodeId::new(patch_id.0.clone()),
72 yoagent_state::REL_ADVANCES,
73 NodeId::new("goal_retry_reliability"),
74 )
75 .await?;
76 state
77 .record_eval_result(
78 actor,
79 NodeId::new("eval_retry_timeout"),
80 patch_id.clone(),
81 "cargo test tool_retry_survives_timeout",
82 true,
83 )
84 .await?;
85 state
86 .update_patch_status(
87 patch_id,
88 PatchStatus::Promoted,
89 Some("eval passed".to_string()),
90 )
91 .await?;
92
93 print!(
94 "{}",
95 state
96 .lineage(NodeId::new("goal_retry_reliability"))
97 .await
98 .to_markdown()
99 );
100 Ok(())
101}Trait Implementations§
Source§impl<'de> Deserialize<'de> for Lineage
impl<'de> Deserialize<'de> for Lineage
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>,
Deserialize this value from the given Serde deserializer. Read more
impl StructuralPartialEq for Lineage
Auto Trait Implementations§
impl Freeze for Lineage
impl RefUnwindSafe for Lineage
impl Send for Lineage
impl Sync for Lineage
impl Unpin for Lineage
impl UnsafeUnpin for Lineage
impl UnwindSafe for Lineage
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
Mutably borrows from an owned value. Read more