anchor.diff:  
   -type node_name() :: binary().
   -type node_state() :: binary().
  +-type fsm_states() :: 'up' | 'down'.
   -type logging_level() :: 'verbose' | 'normal'.
  --type status_atom() :: 'idle' | 'ready' | 'restarting' | 'running'.
  --type status_binary() :: binary(). % <<"idle">> | <<"ready">> | <<"restarting">> | <<"running">>.
  +-type status_atom() :: 'up' | 'down'.
  +-type status_binary() :: binary(). % <<"up">> | <<"down">>
   -type gproc_error() :: ok | {error, no_node}.
   
  --record(eavg, {acc = 0 :: integer(),
  -               avg = 0 :: float(),
  -               n = 0   :: integer(),
  -               tick_interval :: integer(),
  -               tref   :: reference()
  -              }).
  -
  --record(state, {dead_interval    :: integer(),
  -                name             :: binary(),
  -                
  -
  -                heartbeat_rate   :: #eavg{},
  -                logging = normal :: logging_level(),
  -                observers = []
  +-type eavg() :: any().
  +
  +-record(state, {name                  :: binary(),
  +                heartbeat_interval    :: integer(),
  +                logging = normal      :: logging_level(),
  +                current_status = down :: status_atom(),
  +                observers = [],
  +                tref,
  +                heartbeat_rate   :: eavg()
                  }).
  -
  --spec eavg_init(integer(), integer()) -> #eavg{}.
  -eavg_init(N, I) ->
  -    TRef = erlang:start_timer(I, self(), update_avg),
  -    #eavg{acc=0, avg=0, n=N, tick_interval=I, tref=TRef}.
  -
  --spec eavg_tick(#eavg{}) -> #eavg{}.
  -eavg_tick(#eavg{acc=Acc, avg=Avg, n=N, tick_interval=I}=EAvg) ->
  -    ?debugVal(EAvg),
  -    NAvg = (Avg * (N-1) + Acc)/N,
  -    TRef = erlang:start_timer(I, self(), update_avg),
  -    EAvg#eavg{acc=0, avg=NAvg, tref=TRef}.
  -
  -eavg_inc(#eavg{acc=Acc}=EAvg, Count) ->
  -    ?debugVal(EAvg),
  -    ?debugVal(Count),
  -    EAvg#eavg{acc=Acc+Count}.
  -
  -eavg_value(#eavg{avg=Avg}) ->
  -    Avg.
   
   %%%
   %%% External API
   %%%
  --spec start_link(node_name(),HeartbeatInterval::integer(),DeadIntervalCount::integer()) ->
  +-spec start_link(node_name(), HeartbeatInterval::integer(), Window::integer(),
  +                UThresh::real(), DThresh::real) ->
                           'ignore' | {'error',_} | {'ok',pid()}.
   start_link(Name, HeartbeatInterval, DeadIntervalCount) ->
       gen_fsm:start_link(?MODULE, [Name, HeartbeatInterval, DeadIntervalCount], []).
   
  --spec heartbeat({'heartbeat',node_name(),node_state()}) -> gproc_error().
  -heartbeat({heartbeat, NodeName, NodeState}) ->
  +-spec heartbeat(node_name(), node_state()) -> 'ok'.
  +heartbeat(NodeName, NodeStatus) ->
       case catch gproc:send({n,l,NodeName},
  -            {heartbeat, NodeName, status_to_atom(NodeState)}) of
  -        {'EXIT', _} -> ?NO_NODE;
  +            {heartbeat, NodeName, status_to_atom(NodeStatus)}) of
  +        {'EXIT', _} ->
  +            % TODO this fails to take into account a failed initialize/gproc registration
  +            pushy_node_state_sup:new(NodeName),
  +            heartbeat(NodeName, NodeStatus);
           _ -> ok
       end.
   
  
positive.code:             gen_fsm:send_all_state_event(Pid, {Action, self()})
      end.
  
  
  init([Name, HeartbeatInterval, DeadIntervalCount]) ->
      {ok, initializing,
       #state{dead_interval=HeartbeatInterval * DeadIntervalCount,
              name=Name,
              heartbeat_rate=eavg_init(DeadIntervalCount, HeartbeatInterval)
             },
       0}.
  
  initializing(timeout, #state{name=Name}=State) ->
      case gproc:reg({n, l, Name}) of
          true ->
              {next_state, down, save_status(?SAVE_MODE, down, State)};
          false ->
              lager:error("Failed to register:~p for ~p", [Name,self()]),
              {stop, shutdown, State}
      end.
  
  
  %%%
  %%% State machine internals
  %%%
  up(current_state, _From, State) ->
      {reply, up, up, State}.
  
  crashed(current_state, _From, State) ->
      {reply, crashed, crashed, State}.
  
  restarting(current_state, _From, State) ->
      {reply, restarting, restarting, State}.
  
  %%
  %% These events are handled the same everywhere
  %%
  handle_event({start_watching, Who}, StateName, #state{observers=Observers}=State) ->
      State1 = case lists:member(Who, Observers) of
          false ->
  
negative.code:     end.
  
  notify_status_change(Status, #state{name=Name,observers=Observers}) ->
      lager:info("Status change for ~s : ~s", [Name, Status]),
      [ Observer ! { node_heartbeat_event, Name, Status } || Observer <- Observers ].
  
  