pub fn convergence_pass(end: StageEnd) -> PassResultExpand description
What: How the loop reads a pass’s ending. Why: A proposal asks for another pass; a pass that could not decide blocks the fix; a completed or stopped pass proposes nothing, so the content is stable.
In TS you’d write (pseudocode):
const convergencePass = (end) => end === 'proposed' ? 'proposed' : end === 'failed' || isUnavailable(end) ? 'failed' : 'stable';