anchor.diff:      end, JobNodes),
       State#state{job_nodes = JobNodes2}.
   
  +maybe_finished_voting(#state{job_nodes = JobNodes} = State) ->
  +    case count_nodes_in_state([new], State) of
  +        0 ->
  +            NumNodes = dict:size(JobNodes),
  +            case count_nodes_in_state([ready], State) of
  +                NumNodes -> start_running(State);
  +                _ -> finish_job(quorum_failed, State)
  +            end;
  +        _ -> {next_state, voting, State}
  +    end.
  +
   maybe_finished_running(State) ->
       case count_nodes_in_state([ready, running], State) of
           0 -> finish_job(complete, State);
  
positive.code:             new -> OldNodeState#pushy_job_node{status = faulty};
              ready -> OldNodeState#pushy_job_node{status = faulty};
              running -> OldNodeState#pushy_job_node{status = aborted}; % TODO better status?
              _ -> OldNodeState
          end
      end, JobNodes),
  
negative.code:     Job2 = Job#pushy_job{status = voting},
      State2 = State#state{job = Job2},
      send_command_to_all(<<"job_command">>, State2),
      {next_state, StateName, State3} = maybe_finished_voting(State2),
      {ok, StateName, State3}.
  
  start_running(#state{job = Job} = State) ->
      lager:info("Job ~p -> running", [Job#pushy_job.id]),
      Job2 = Job#pushy_job{status = running},
      State2 = State#state{job = Job2},
      send_command_to_all(<<"job_execute">>, State2),
      maybe_finished_running(State2).
  
  finish_job(Reason, #state{job = Job} = State) ->
      lager:info("Job ~p -> ~p", [Job#pushy_job.id, Reason]),
  