ban_removal_set_terminates_on_a_cycle (ui/src/components/members.rs) is designed to hang rather than fail if the cycle guard regresses:
(Test hangs rather than fails if this regresses, which is still a loud CI signal.)
It is not a loud signal in practice. On nova I found three orphaned copies of the river_ui test binary running this exact test, each burning ~96% of a core for 8 days (PPID 1 — their cargo parents had long since exited):
PID ELAPSED CMD
3530769 8-07:08:40 .../worktrees/feat-impersonation/target/debug/deps/river_ui-<hash> ban_removal_set_terminates_on_a_cycle
4010245 8-06:08:48 .../worktrees/feat-impersonation/target/debug/deps/river_ui-<hash> ban_removal_set_terminates_on_a_cycle
4091413 8-05:57:10 .../worktrees/feat-impersonation/target/debug/deps/river_ui-<hash> ban_removal_set_terminates_on_a_cycle
I killed them (they were 3/16 cores of permanent load on the dev box). The binaries were built from the feat-impersonation worktree, so I have not confirmed whether ban_removal_set on main also fails to terminate — the branch's version may be the one that regressed. Either way there are two problems:
- A hang is a bad failure mode for this assertion. In CI it burns the job's full timeout; locally it leaves an orphan spinning indefinitely with no output. Neither is loud. Prefer making non-termination detectable: give
ban_removal_set an explicit visited-set (or an iteration cap of members.len()) and assert the walk completes and returns the expected set. A test that can only signal by never finishing cannot distinguish "regressed" from "still running".
- Something apparently did hang, at least on that branch — worth confirming whether the cycle guard on
main is intact.
Suggested fix: add the visited guard to ban_removal_set itself (the UI mirror walks half-applied or hostile state, so it cannot rely on verify having rejected circular invite chains), and keep the test as a normal terminating assertion.
[AI-assisted - Claude]
ban_removal_set_terminates_on_a_cycle(ui/src/components/members.rs) is designed to hang rather than fail if the cycle guard regresses:It is not a loud signal in practice. On nova I found three orphaned copies of the
river_uitest binary running this exact test, each burning ~96% of a core for 8 days (PPID 1 — their cargo parents had long since exited):I killed them (they were 3/16 cores of permanent load on the dev box). The binaries were built from the
feat-impersonationworktree, so I have not confirmed whetherban_removal_setonmainalso fails to terminate — the branch's version may be the one that regressed. Either way there are two problems:ban_removal_setan explicit visited-set (or an iteration cap ofmembers.len()) and assert the walk completes and returns the expected set. A test that can only signal by never finishing cannot distinguish "regressed" from "still running".mainis intact.Suggested fix: add the visited guard to
ban_removal_setitself (the UI mirror walks half-applied or hostile state, so it cannot rely onverifyhaving rejected circular invite chains), and keep the test as a normal terminating assertion.[AI-assisted - Claude]