diff --git a/hive-forge/src/verbs/mod.rs b/hive-forge/src/verbs/mod.rs index ec1d1d42..38050701 100644 --- a/hive-forge/src/verbs/mod.rs +++ b/hive-forge/src/verbs/mod.rs @@ -274,7 +274,11 @@ fn reviewed_older_head(reviewed_sha: Option<&str>, head_sha: Option<&str>) -> bo let (Some(head), Some(reviewed)) = (head_sha, reviewed_sha) else { return false; }; - !reviewed.is_empty() && reviewed != head + // Both emptiness checks matter, and for the same reason: a blank string + // is a value the forge sent, not a sha it has. Treating one as real would + // make every review compare unequal and mark the whole PR stale — the + // direction this whole function exists to avoid. + !head.is_empty() && !reviewed.is_empty() && reviewed != head } /// Latest non-comment review per reviewer on a PR. Reviews come @@ -395,6 +399,10 @@ mod tests { assert!(!reviewed_older_head(None, Some("f4c47088"))); assert!(!reviewed_older_head(Some("81292f14"), None)); assert!(!reviewed_older_head(Some(""), Some("f4c47088"))); + // Absent and blank have to behave the same on BOTH sides — a blank + // head that counted as real would mark every review on the PR stale. + assert!(!reviewed_older_head(Some("81292f14"), Some(""))); + assert!(!reviewed_older_head(Some(""), Some(""))); } #[test]