fix(adversary): fail closed on PIPELINE-FAULT evidence regardless of status; pin bail-chain and validator shape

This commit is contained in:
Dark-Alex-17 committed 2026-09-14 10:50:34 -06:00
1 parent 66b30bb06a
commit 1cf42fffa2
5 files changed
+162 -10

No files matched your search

+34
View File
@@ -818,4 +818,38 @@ mod tests {
"{captured}"
);
}
/// Without a fallback the node bails, and that bail must wrap the same
/// full chain the state_updates text carries.
#[tokio::test]
async fn bail_without_fallback_carries_full_error_chain() {
let mut u = HashMap::new();
u.insert("captured".into(), "{{output}}".into());
let mut node = node_with(Some(u));
node.prompt = "{{nope}}".into();
node.fallback = None;
let mut state = manager_with(&[]);
let mut ctx = RequestContext::new(Arc::new(AppState::test_default()), WorkingMode::Cmd);
ctx.agent = Some(Agent::test_new(AgentConfig::default()));
let abort = create_abort_signal();
let err = LlmNodeExecutor::execute("think", &node, &mut state, &mut ctx, &abort)
.await
.expect_err("no fallback means the failure bails");
let chain = format!("{err:#}");
assert!(
chain.contains(
"LLM node failed and no fallback declared: LLM call failed: Failed to interpolate llm node prompt: Template interpolation failed: 'nope' not found in state"
),
"{chain}"
);
let captured = state
.state()
.get("captured")
.and_then(Value::as_str)
.expect("state_updates still run before the bail")
.to_string();
assert!(captured.starts_with("LLM node failed: "), "{captured}");
}
}
+28
View File
@@ -3016,6 +3016,34 @@ mod tests {
);
}
#[test]
fn map_branch_llm_fallback_to_branch_local_script_passes() {
let map = map_node_basic("m", "br", Some("end"));
let branch = llm_node("br", Some("recover"), None);
let recover = script_node("recover", "Cargo.toml", None);
let graph = graph_with(
vec![
("m", map),
("br", branch),
("recover", recover),
("end", end_node("end")),
],
"m",
);
let result = validator().validate(&graph);
assert!(result.errors.is_empty(), "{:?}", result.errors);
assert!(
!result
.warnings
.iter()
.any(|w| w.node_id.as_deref() == Some("m")),
"a branch-local script fallback raises nothing on the map: {:?}",
result.warnings
);
}
#[test]
fn map_branch_deep_approval_node_errors_on_the_map() {
let map = map_node_basic("m", "br", Some("end"));