docs: private Set<String> runBeforeGroupInvoke(final Set<String> skip) {
          HashSet<String> processedEntryKeys = new HashSet<>();
          if (skip != null) {
              processedEntryKeys.addAll(skip);
          }
          List<TaskGroupEntry<TaskItem>> entries = this.entriesSnapshot();
          boolean hasMoreToProcess;
          // Invokes 'beforeGroupInvoke' on a subset of non-processed tasks in the group.
          // Initially processing is pending on all task items.
          do {
              hasMoreToProcess = false;
              for (TaskGroupEntry<TaskItem> entry : entries) {
                  if (!processedEntryKeys.contains(entry.key())) {
                      entry.data().beforeGroupInvoke();
                      processedEntryKeys.add(entry.key());
                  }
              }
              int prevSize = entries.size();
              entries = this.entriesSnapshot();
              if (entries.size() > prevSize) {
                  // If new task dependencies/dependents added in 'beforeGroupInvoke' then
                  // set the flag which indicates another pass is required to 'prepare' new
                  // task items
                  hasMoreToProcess = true;
              }
          } while (hasMoreToProcess);  // Run another pass if new dependencies/dependents were added in this pass
          super.prepareForEnumeration();
          return processedEntryKeys;
      }