docs: function _invokeTask(taskCollection, loopsSet, alreadyDoneSet, task)
  {
      const debug = false;
  
      if (debug) debugLog(`invokeTask: ${util.inspect(task)}`);
      if (debug) debugLog(`invokeTask: name: ${task.name()}`);
  
      const prereqs = task.prerequisites();
  
      if (loopsSet.has(task.name()))
      {
          // do not use raiseError - this will stuff up mocha testing of this feature
          throw new Error(`circular dependency - task:${task.name()} has already been seen`);
      }
      else
      {
          loopsSet.add(task.name());
          if (prereqs.length > 0)
          {
              if (debug) debugLog(`invokeTasks prereqs 1 length:${prereqs.length}`);
              prereqs.forEach((el) =>
              {
                  if (debug) debugLog(`invokeTasks prereqs ${el}`);
                  const t = taskCollection.getByName(el);
  
                  if (t === undefined)
                  {
                      ERROR.raiseError(`unknown task ${el} is prerequisite of ${task.name()}`);
                  }
                  else
                  {
                      if (debug) debugLog(`invokeTask: prereqs ${t.name()}`);
                      _invokeTask(taskCollection, loopsSet, alreadyDoneSet, t);
                  }
              });
          }
          if (!alreadyDoneSet.has(task.name()))
          {
              let result;
              try
              {
                  /**
                   * task actions indicate failure by either 
                   *  -    return a non-zero
                   *  -   throw an error
                   *  consequently success is indicated by
                   *      -   a return of zero
                   *      -   a return if undefined -- dont want to force action functions to return a value 
                   */
                  result = (task.action())();
                  if( result === 0 || result === undefined)
                  {
                      console.log(chalk.white.bold(`${task.name()} - complete [`)+chalk.bold.green(`OK`)+chalk.white.bold(`]`));
                  }
                  else
                  {
                      console.log(chalk.white.bold(`${task.name()} - `) + chalk.bold.red(`failed[${result}]`));  
                      process.exit(1);                  
                  }
                  alreadyDoneSet.add(task.name());
              }
              catch(e)
              {
                  console.log(chalk.white.bold(`${task.name()} - `) + chalk.bold.red(`failed`));                    
                  console.log(chalk.reset(e.stack));
                  process.exit(1); // sledge hammer
                  throw e;    
              }
          }
          loopsSet.delete(task.name());
      }
  }