code: function validateNoMissingNames(ast) {
      var errors = [];
      var names = {};
      if (ast.locals) {
        names = Object.keys(ast.locals).reduce(function (accum, k) { // start with locals
          accum[k] = true;
          return accum;
        }, names);
      }
      ast.inParams.reduce(function (accum, p) {  // add input params
        accum[p] = true;
        return accum;
      }, names);
      ast.tasks.reduce(function (accum, t) { // add task outputs
        return t.out.reduce(function (innerAccum, p) {
          innerAccum[p] = true;
          return innerAccum;
        }, accum);
      }, names);
  
      // now we have all possible provided vars, check task inputs are accounted for
      ast.tasks.reduce(function (accum, t) {  // for all tasks
        return t.a.reduce(function (innerAccum, p) { // for all in params, except property
          if (!isLiteralOrProp(p) && !names[p]) innerAccum.push(sprintf(MISSING_INPUTS, p)); // add error if missing
          return innerAccum;
        }, accum);
      }, errors);
  
      // now check the final task outputs
      ast.outTask.a.reduce(function (accum, p) { // for final task out params
        if (!isLiteralOrProp(p) && !names[p]) accum.push(sprintf(MISSING_INPUTS, p)); // add error if missing
        return accum;
      }, errors);
      return errors;
    }
docs: validate there are no missing or mispelled param names in any task inputs
  or the final task output
  
  @return array of errors, or empty array if none