From 9b85653a2dc62007a5ec2ce8cc8b8f1f4c817ef0 Mon Sep 17 00:00:00 2001 From: Fabro Date: Thu, 23 Jul 2026 20:29:19 +0000 Subject: [PATCH] fabro(01KY7Y01REECZ24XXTMBZ3PPV9): simplify_sol (succeeded) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fabro-Run: 01KY7Y01REECZ24XXTMBZ3PPV9 Fabro-Completed: 7 Fabro-Checkpoint: 334aea8fdc267cb8b5d7ba3e67bfb0d6d0341d61 ⚒️ Generated with [Fabro](https://fabro.sh) --- lib/crates/fabro-workflow/src/artifact.rs | 4 +- lib/crates/fabro-workflow/src/context.rs | 17 ++-- .../fabro-workflow/src/lifecycle/fidelity.rs | 87 ++++++++++--------- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/lib/crates/fabro-workflow/src/artifact.rs b/lib/crates/fabro-workflow/src/artifact.rs index bbf7f7ed8..8ea8e38f0 100644 --- a/lib/crates/fabro-workflow/src/artifact.rs +++ b/lib/crates/fabro-workflow/src/artifact.rs @@ -83,8 +83,8 @@ pub fn durable_context_snapshot(context: &Context) -> HashMap { snapshot } -/// Remove runtime-only keys that must never reach durable storage or events. -pub fn strip_transient_keys(values: &mut HashMap) { +/// Remove runtime-only keys that must never reach durable storage. +pub(crate) fn strip_transient_keys(values: &mut HashMap) { for key in context::keys::TRANSIENT_CONTEXT_KEYS { values.remove(*key); } diff --git a/lib/crates/fabro-workflow/src/context.rs b/lib/crates/fabro-workflow/src/context.rs index a890c0e8f..b02a8dc51 100644 --- a/lib/crates/fabro-workflow/src/context.rs +++ b/lib/crates/fabro-workflow/src/context.rs @@ -48,10 +48,8 @@ pub mod keys { pub const PARALLEL_FAN_IN_BEST_OUTCOME: &str = "parallel.fan_in.best_outcome"; pub const PARALLEL_FAN_IN_BEST_HEAD_SHA: &str = "parallel.fan_in.best_head_sha"; - /// Runtime-only keys stripped from durable context projections - /// (checkpoint snapshots and resume normalization). Add new transient - /// keys here so both strip sites stay in sync. - pub const TRANSIENT_CONTEXT_KEYS: &[&str] = + /// Runtime-only keys stripped from durable context projections. + pub(crate) const TRANSIENT_CONTEXT_KEYS: &[&str] = &[CURRENT_PREAMBLE, INTERNAL_PARALLEL_BRANCH_PREAMBLES]; // --- Prefix constants (for filtering and dynamic keys) --- @@ -152,15 +150,12 @@ use crate::event::StageScope; /// One entry of the [`keys::INTERNAL_PARALLEL_BRANCH_PREAMBLES`] stash. /// /// The stash is a JSON array indexed by the parallel node's outgoing-edge -/// order (`Graph::outgoing_edges` preserves declaration order, so producer and -/// consumer align even with duplicate targets). `null` entries mean the branch -/// inherits the fork's preamble. `FidelityLifecycle::before_node` produces the -/// stash; `ParallelHandler::execute` consumes and clears it. +/// order. `null` entries mean the branch inherits the fork's preamble. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] -pub struct ParallelBranchPreamble { - pub fidelity: Fidelity, - pub preamble: String, +pub(crate) struct ParallelBranchPreamble { + pub(crate) fidelity: Fidelity, + pub(crate) preamble: String, } /// Domain-specific typed accessors for workflow context values. diff --git a/lib/crates/fabro-workflow/src/lifecycle/fidelity.rs b/lib/crates/fabro-workflow/src/lifecycle/fidelity.rs index 437550cc1..37d2c7e33 100644 --- a/lib/crates/fabro-workflow/src/lifecycle/fidelity.rs +++ b/lib/crates/fabro-workflow/src/lifecycle/fidelity.rs @@ -74,47 +74,52 @@ impl FidelityLifecycle { resolved_outcomes: &HashMap, completed_nodes: &[String], ) -> Vec { - let mut rendered: HashMap = HashMap::new(); - self.graph - .outgoing_edges(node_id) - .into_iter() - .enumerate() - .map(|(branch_index, edge)| { - let Some(target_node) = self.graph.nodes.get(&edge.to) else { - return serde_json::Value::Null; - }; - let resolution = resolve_parallel_branch_fidelity(edge, target_node, fork_fidelity); - if resolution.requested == Some(keys::Fidelity::Full) { - tracing::warn!( - parallel_node = %node_id, - branch = %edge.to, - branch_index, - effective_fidelity = %keys::Fidelity::Full.degraded(), - "Parallel branch fidelity degraded from full" - ); - } - let Some(branch_fidelity) = resolution.effective else { - return serde_json::Value::Null; - }; - rendered - .entry(branch_fidelity) - .or_insert_with(|| { - let entry = ParallelBranchPreamble { - fidelity: branch_fidelity, - preamble: build_preamble( - branch_fidelity, - resolved_context, - &self.graph, - completed_nodes, - resolved_outcomes, - ), - }; - serde_json::to_value(entry) - .expect("ParallelBranchPreamble serialization cannot fail") - }) - .clone() - }) - .collect() + let edges = self.graph.outgoing_edges(node_id); + let mut preambles: Vec = Vec::with_capacity(edges.len()); + let mut rendered: HashMap = HashMap::new(); + + for (branch_index, edge) in edges.into_iter().enumerate() { + let Some(target_node) = self.graph.nodes.get(&edge.to) else { + preambles.push(serde_json::Value::Null); + continue; + }; + let resolution = resolve_parallel_branch_fidelity(edge, target_node, fork_fidelity); + if resolution.requested == Some(keys::Fidelity::Full) { + tracing::warn!( + parallel_node = %node_id, + branch = %edge.to, + branch_index, + effective_fidelity = %keys::Fidelity::Full.degraded(), + "Parallel branch fidelity degraded from full" + ); + } + let Some(branch_fidelity) = resolution.effective else { + preambles.push(serde_json::Value::Null); + continue; + }; + if let Some(&rendered_index) = rendered.get(&branch_fidelity) { + preambles.push(preambles[rendered_index].clone()); + continue; + } + + let entry = ParallelBranchPreamble { + fidelity: branch_fidelity, + preamble: build_preamble( + branch_fidelity, + resolved_context, + &self.graph, + completed_nodes, + resolved_outcomes, + ), + }; + rendered.insert(branch_fidelity, preambles.len()); + preambles.push( + serde_json::to_value(entry) + .expect("ParallelBranchPreamble serialization cannot fail"), + ); + } + + preambles } }