anchor.diff:      {noreply, S}.
   
   -spec handle_cast({update_nodes, [host()]}, state()) -> gs_noreply();
  +                 ({inputs, [task_output()]}, state()) -> gs_noreply();
                    ({stage_done, stage_name()}, state()) -> gs_noreply();
                    ({submit_tasks, submit_mode(), [task_id()]}, state()) ->
                            gs_noreply();
  
positive.code:                 schedule         :: task_schedule(),
                  next_taskid = 0  :: task_id(),
                  next_runid  = 0  :: task_run_id(),
                  % cluster membership: [host()]
                  hosts      = gb_sets:empty()  :: gb_set(),
                  % input | task_id() -> task_info().
  
negative.code:     do_kill_job(Reason, S),
      {stop, Reason, S}.
  
  -spec handle_info(term(), state()) -> gs_noreply() | gs_stop(tuple()).
  handle_info({'EXIT', Pid, Reason}, #state{input_pid = Pid} = S) ->
      {stop, {"input_processor exited", Reason}, S#state{input_pid = none}};
  handle_info(_M, S) ->
      {noreply, S}.
  
  -spec terminate(term(), state()) -> ok.
  terminate(normal, _S) ->
      lager:warning("job_coord terminating normally!"),
      ok;
  terminate(Reason, #state{jobinfo = #jobinfo{jobname = JobName}}) ->
      lager:warning("job coordinator for ~s dies: ~p", [JobName, Reason]).
  
  