anchor.diff:  -type maybe_obj() :: obj() | notfound | timeout. %% TODO: Pretty sure this can also be failed
   
   -type target() :: pid() | ensemble_id().
  +-type maybe_peer_id() :: undefined | peer_id().
   
   -record(state, {id            :: peer_id(),
                   ensemble      :: ensemble_id(),
  
positive.code: -spec sync_failed(pid()) -> ok.
  sync_failed(Pid) when is_pid(Pid) ->
      gen_fsm:send_event(Pid, sync_failed).
  
  %%%===================================================================
  %%% K/V API
  
negative.code: 
  %% API
  -export([start_link/5, start/5]).
  -export([join/2, join/3, update_members/3, get_leader/1]).
  -export([sync_complete/1, sync_failed/1]).
  -export([kget/4, kupdate/6, kput_once/5, kover/5, kmodify/6, kdelete/4,
           ksafe_delete/5, obj_value/2, obj_value/3]).
  -export([probe/2, election/2, prepare/2, leading/2, following/2,
           probe/3, election/3, prepare/3, leading/3, following/3]).
  -export([sync/2,
           sync/3]).
  
  %% Support/debug API
  -export([check_quorum/2, force_state/2]).
  
  -compile({pulse_replace_module,
            [{gen_fsm, pulse_gen_fsm}]}).
  