From eefd971bd838fd32621801609b9fb306c426cc97 Mon Sep 17 00:00:00 2001 From: damocles Date: Sun, 16 Aug 2026 18:48:39 +0200 Subject: [PATCH] hive-forge dependency: surface a converged-despite-error case instead of swallowing it --- hive-forge/src/verbs/dependency.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/hive-forge/src/verbs/dependency.rs b/hive-forge/src/verbs/dependency.rs index 41d94619..6fb4a349 100644 --- a/hive-forge/src/verbs/dependency.rs +++ b/hive-forge/src/verbs/dependency.rs @@ -118,16 +118,25 @@ fn apply_and_verify( .iter() .filter_map(|d| d.get("number").and_then(Value::as_i64)) .collect(); - let real_failures: Vec = call_errors - .into_iter() - .filter(|(dep, _)| { - let still_present = present.contains(&index(*dep).unwrap_or(-1)); - // Converged iff present after an add, absent after a remove. - // A real failure is anything that didn't converge. - still_present != adding - }) - .map(|(dep, e)| format!("#{dep}: {e:#}")) - .collect(); + let mut real_failures = Vec::new(); + for (dep, e) in call_errors { + let still_present = present.contains(&index(dep).unwrap_or(-1)); + // Converged iff present after an add, absent after a remove. + if still_present == adding { + // The write landed despite the error, but the error itself is + // still real signal: it means something *after* the write + // failed server-side (a timeline entry, a notification, a + // cycle check — we don't know which). Converging proves the + // 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() { let verb = if adding { "add" } else { "remove" }; bail!(