docs: public static void addRule(TerminalNode tn, Collection<InternalWorkingMemory> wms, InternalKnowledgeBase kBase) {
          if (log.isTraceEnabled()) {
              log.trace("Adding Rule {}", tn.getRule().getName());
          }
  
          boolean hasProtos = kBase.hasSegmentPrototypes();
          boolean hasWms = !wms.isEmpty();
  
          if (!hasProtos && !hasWms) {
              return;
          }
  
          RuleImpl rule = tn.getRule();
          LeftTupleNode firstSplit = getNetworkSplitPoint(tn);
          PathEndNodes pathEndNodes = getPathEndNodes(kBase, firstSplit, tn, rule, hasProtos, hasWms);
  
          // Insert the facts for the new paths. This will iterate each new path from EndNode to the splitStart - but will not process the splitStart itself (as tha already exist).
          // It does not matter that the prior segments have not yet been processed for splitting, as this will only apply for branches of paths that did not exist before
  
          for (InternalWorkingMemory wm : wms) {
              wm.flushPropagations();
  
              if (NodeTypeEnums.LeftInputAdapterNode == firstSplit.getType() && firstSplit.getAssociationsSize() == 1) {
                  // rule added with no sharing
                  insertLiaFacts(firstSplit, wm);
              } else {
                  PathEndNodeMemories tnms = getPathEndMemories(wm, pathEndNodes);
  
                  if (tnms.subjectPmem == null) {
                      // If the existing PathMemories are not yet initialized there are no Segments or tuples to process
                      continue;
                  }
  
                  Map<PathMemory, SegmentMemory[]> prevSmemsLookup = reInitPathMemories(tnms.otherPmems, null);
  
                  // must collect all visited SegmentMemories, for link notification
                  Set<SegmentMemory> smemsToNotify = handleExistingPaths(tn, prevSmemsLookup, tnms.otherPmems, wm, ExistingPathStrategy.ADD_STRATEGY);
  
                  addNewPaths(wm, smemsToNotify, tnms.subjectPmems);
  
                  processLeftTuples(firstSplit, wm, true, rule);
  
                  notifySegments(smemsToNotify, wm);
              }
          }
  
          if (hasWms) {
              insertFacts( pathEndNodes, wms );
          } else {
              for (PathEndNode node : pathEndNodes.otherEndNodes) {
                  node.resetPathMemSpec( null );
              }
          }
      }