docs: private static void processLeftTuples(LeftTupleNode node, InternalWorkingMemory wm, boolean insert, Rule rule) {
          // *** if you make a fix here, it most likely needs to be in PhreakActivationIteratorToo ***
  
          // Must iterate up until a node with memory is found, this can be followed to find the LeftTuples
          // which provide the potential peer of the tuple being added or removed
  
          Memory memory = wm.getNodeMemories().peekNodeMemory(node);
          if (memory == null || memory.getSegmentMemory() == null) {
              // segment has never been initialized, which means the rule(s) have never been linked and thus no Tuples to fix
              return;
          }
          SegmentMemory sm = memory.getSegmentMemory();
  
          while (NodeTypeEnums.LeftInputAdapterNode != node.getType()) {
  
              if (NodeTypeEnums.isBetaNode(node)) {
                  BetaMemory    bm;
                  if (NodeTypeEnums.AccumulateNode == node.getType()) {
                      AccumulateMemory am = (AccumulateMemory) memory;
                      bm = am.getBetaMemory();
                      FastIterator it = bm.getLeftTupleMemory().fullFastIterator();
                      Tuple        lt = BetaNode.getFirstTuple(bm.getLeftTupleMemory(), it);
                      for (; lt != null; lt = (LeftTuple) it.next(lt)) {
                          AccumulateContext accctx = (AccumulateContext) lt.getContextObject();
                          visitChild(accctx.getResultLeftTuple(), insert, wm, rule);
                      }
                  } else if (NodeTypeEnums.ExistsNode == node.getType()) {
                      bm = (BetaMemory) wm.getNodeMemory((MemoryFactory) node);
                      FastIterator it = bm.getRightTupleMemory().fullFastIterator(); // done off the RightTupleMemory, as exists only have unblocked tuples on the left side
                      RightTuple   rt = (RightTuple) BetaNode.getFirstTuple(bm.getRightTupleMemory(), it);
                      for (; rt != null; rt = (RightTuple) it.next(rt)) {
                          for (LeftTuple lt = rt.getBlocked(); lt != null; lt = lt.getBlockedNext()) {
                              visitChild(wm, insert, rule, it, lt);
                          }
                      }
                  } else {
                      bm = (BetaMemory) wm.getNodeMemory((MemoryFactory) node);
                      FastIterator it = bm.getLeftTupleMemory().fullFastIterator();
                      Tuple        lt = BetaNode.getFirstTuple(bm.getLeftTupleMemory(), it);
                      visitChild(wm, insert, rule, it, lt);
                  }
                  return;
              } else if (NodeTypeEnums.FromNode == node.getType()) {
                  FromMemory   fm  = (FromMemory) wm.getNodeMemory((MemoryFactory) node);
                  TupleMemory  ltm = fm.getBetaMemory().getLeftTupleMemory();
                  FastIterator it  = ltm.fullFastIterator();
                  for (LeftTuple lt = (LeftTuple) ltm.getFirst(null); lt != null; lt = (LeftTuple) it.next(lt)) {
                      visitChild(lt, insert, wm, rule);
                  }
                  return;
              }
              if (sm.getRootNode() == node) {
                  sm = wm.getNodeMemory((MemoryFactory<Memory>) node.getLeftTupleSource()).getSegmentMemory();
              }
              node = node.getLeftTupleSource();
          }
  
          // No beta or from nodes, so must retrieve LeftTuples from the LiaNode.
          // This is done by scanning all the LeftTuples referenced from the FactHandles in the ObjectTypeNode
          LeftInputAdapterNode lian = (LeftInputAdapterNode) node;
  
          ObjectSource os = lian.getObjectSource();
          while (os.getType() != NodeTypeEnums.ObjectTypeNode) {
              os = os.getParentObjectSource();
          }
          ObjectTypeNode             otn  = (ObjectTypeNode) os;
          final ObjectTypeNodeMemory omem = wm.getNodeMemory(otn);
          if (omem == null) {
              // no OTN memory yet, i.e. no inserted matching objects, so no Tuples to process
              return;
          }
  
          Iterator<InternalFactHandle> it = omem.iterator();
          while (it.hasNext()) {
              InternalFactHandle fh = it.next();
              fh.forEachLeftTuple( lt -> {
                  LeftTuple nextLt = lt.getHandleNext();
  
                  // Each lt is for a different lian, skip any lian not associated with the rule. Need to use lt parent (souce) not child to check the lian.
                  if (lt.getTupleSource().isAssociatedWith(rule)) {
                      visitChild(lt, insert, wm, rule);
  
                      if (lt.getHandlePrevious() != null) {
                          lt.getHandlePrevious().setHandleNext( nextLt );
                          if (nextLt != null) {
                              nextLt.setHandlePrevious( lt.getHandlePrevious() );
                          }
                      }
                  }
              });
          }
      }