hive-forge dependency: surface a converged-despite-error case instead of swallowing it

This commit is contained in:
damocles 2026-08-16 18:48:39 +02:00
commit eefd971bd8

View file

@ -118,16 +118,25 @@ fn apply_and_verify(
.iter() .iter()
.filter_map(|d| d.get("number").and_then(Value::as_i64)) .filter_map(|d| d.get("number").and_then(Value::as_i64))
.collect(); .collect();
let real_failures: Vec<String> = call_errors let mut real_failures = Vec::new();
.into_iter() for (dep, e) in call_errors {
.filter(|(dep, _)| { let still_present = present.contains(&index(dep).unwrap_or(-1));
let still_present = present.contains(&index(*dep).unwrap_or(-1)); // Converged iff present after an add, absent after a remove.
// Converged iff present after an add, absent after a remove. if still_present == adding {
// A real failure is anything that didn't converge. // The write landed despite the error, but the error itself is
still_present != adding // still real signal: it means something *after* the write
}) // failed server-side (a timeline entry, a notification, a
.map(|(dep, e)| format!("#{dep}: {e:#}")) // cycle check — we don't know which). Converging proves the
.collect(); // effect is present, not that the operation fully succeeded,
// so don't let a clean exit make that anomaly unobservable.
eprintln!(
"hive-forge: warning: dependency on #{dep} converged despite a reported \
error (server-side issue after the write, not a real failure): {e:#}"
);
} else {
real_failures.push(format!("#{dep}: {e:#}"));
}
}
if !real_failures.is_empty() { if !real_failures.is_empty() {
let verb = if adding { "add" } else { "remove" }; let verb = if adding { "add" } else { "remove" };
bail!( bail!(