docs: private void determineStartActionIfNecessary(Map<Integer, HostCriteria> hostCriteria) {
          // already made a determination
          if (m_probedDetermination.isDone()) {
              return;
          }
          final int ksafety = getkFactor() + 1;
  
          int bare = 0; // node has no recoverable artifacts (Command Logs, Snapshots)
          int unmeshed = 0;
          int operational = 0;
          int haveTerminus = 0;
          int hostCount = getHostCount();
          int missingHostCount = getmissingHostCount();
  
          // both paused and safemode need to be specified on only one node to
          // make them a cluster attribute. These are overridden if there are
          // any nodes in operational state
          boolean paused = isPaused();
          boolean safemode = isSafeMode();
  
          final NavigableSet<String> terminusNonces = new TreeSet<>();
  
          for (HostCriteria c: hostCriteria.values()) {
              if (c.getNodeState().operational()) {
                  operational += 1;
                  // pause state from operational nodes overrides yours
                  // prefer host count from operational nodes
                  if (operational == 1) {
                      paused = c.isPaused();
                      hostCount = c.getHostCount();
                  }
              }
              unmeshed += c.getNodeState().unmeshed() ? 1 : 0;
              bare += c.isBare() ? 1 : 0;
              if (c.isPaused() && operational == 0) {
                  paused = c.isPaused();
              }
              safemode = safemode || c.isSafeMode();
              if (c.getTerminusNonce() != null) {
                  terminusNonces.add(c.getTerminusNonce());
                  ++haveTerminus;
              }
          }
          int expectedHostCount = hostCount - missingHostCount;
          // not enough host criteria to make a determination
          if (hostCriteria.size() < expectedHostCount && operational == 0) {
              m_networkLog.debug("have yet to receive all the required host criteria");
              return;
          }
          // handle add (i.e. join) cases too
          if (hostCount < getHostCount() && hostCriteria.size() <= expectedHostCount) {
              m_networkLog.debug("have yet to receive all the required host criteria");
              return;
          }
  
          m_networkLog.debug("Received all the required host criteria");
  
          safemode = safemode && operational == 0 && bare < ksafety; // kfactor + 1
  
          if (m_networkLog.isDebugEnabled()) {
              m_networkLog.debug("We have "
                      + operational + " operational nodes, "
                      + bare + " bare nodes, and "
                      + unmeshed + " unmeshed nodes");
              m_networkLog.debug("Propagated cluster attribute are paused: "
                      + paused + ", and safemode: " + safemode);
          }
  
          if (terminusNonces.size() > 1) {
              org.voltdb.VoltDB.crashLocalVoltDB("Detected multiple startup snapshots, cannot "
                      + "proceed with cluster startup. Snapshot IDs " + terminusNonces);
          }
  
          String terminusNonce = terminusNonces.pollFirst();
          if (operational == 0 && haveTerminus <= (hostCount - ksafety)) {
              terminusNonce = null;
          }
  
          if (getStartAction() != StartAction.PROBE) {
              m_probedDetermination.set(new Determination(
                      getStartAction(), getHostCount(), paused, terminusNonce));
              return;
          }
  
          StartAction determination = isBare() ?
                    StartAction.CREATE
                  : StartAction.RECOVER;
  
          if (operational > 0 && operational < hostCount) { // rejoin
              determination = StartAction.LIVE_REJOIN;
          } else if (operational > 0 && operational == hostCount) { // join
              if (isAddAllowed()) {
                  hostCount = hostCount + ksafety; // kfactor + 1
                  determination = StartAction.JOIN;
              } else {
                  org.voltdb.VoltDB.crashLocalVoltDB("Node is not allowed to rejoin an already complete cluster");
                  return;
              }
          } else if (operational == 0 && bare == unmeshed) {
              determination = StartAction.CREATE;
          } else if (operational == 0 && bare < ksafety /* kfactor + 1 */) {
              determination = safemode ? StartAction.SAFE_RECOVER : StartAction.RECOVER;
          } else if (operational == 0 && bare >= ksafety  /* kfactor + 1 */) {
              org.voltdb.VoltDB.crashLocalVoltDB("Cluster has incomplete command logs: "
                      + bare + " nodes have no command logs, while "
                      + (unmeshed - bare) + " nodes have them");
              return;
          }
  
          final Determination dtrm = new Determination(determination, hostCount, paused, terminusNonce);
          if (m_networkLog.isDebugEnabled()) {
              m_networkLog.debug("made the following " + dtrm);
          }
          m_probedDetermination.set(dtrm);
      }