Merge branch 'stable-3.1' into stable-3.2

* stable-3.1: (38 commits)
  docker: make sure to cleanup containers before force exit
  fixup! Add TaskTree definitions more directly
  fixup! refactor predicate cache into its own class
  fixup! Add support for tasks-factory and names-factory keywords
  fixup! Support outputting elapsed evaluation time on tasks
  fixup! Revert "Revert "plugin:task Adds support for names-factory of type change""
  Add a Container.toString() to help when debugging.
  Harden inputs to basename
  Add Zuul postflight publish job
  Pass around Task parent instead of its fields
  Fix to alter change context for TaskChangeFactories
  Add tasks-factories static properties tests
  Add a names-factory STATIC Properties test
  Add ensures to the task tests setups
  Split the task preload properties test out
  Split the task preload optional test out
  Split the append preloaded subtasks test out
  Split the task override preload pass/fail tests out
  Split the task preload hints tests out
  Split the task preload preload test out
  ...

Change-Id: I68fefcfe1a0f96fee6d0bcea18060852291f973d
diff --git a/.zuul.yaml b/.zuul.yaml
index 1f7a7ca..ac08784 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -7,6 +7,15 @@
         bazelisk_test_targets: "plugins/task/lint_test plugins/task/..."
         
 - project:
+    description: |
+      Build the plugin in check, and also build and publish it after
+      every merged commit.
     check:
       jobs:
         - plugins-task-build
+    post:
+      jobs:
+        - plugins-task-build
+        - gerrit-plugin-publish:
+            dependencies:
+              - plugins-task-build
diff --git a/BUILD b/BUILD
index eaf6ce3..56452dc 100644
--- a/BUILD
+++ b/BUILD
@@ -49,7 +49,7 @@
     size = "medium",
     srcs = ["test/docker/run.sh"],
     args = ["--task-plugin-jar", "$(location :task)"],
-    data = [plugin_name] + glob(["test/**"]),
+    data = [plugin_name] + glob(["test/**"]) + glob(["src/main/resources/Documentation/*"]),
     local = True,
 )
 
diff --git a/src/main/java/com/google/gerrit/common/Container.java b/src/main/java/com/google/gerrit/common/Container.java
index eb0a0f6..6e11534 100644
--- a/src/main/java/com/google/gerrit/common/Container.java
+++ b/src/main/java/com/google/gerrit/common/Container.java
@@ -55,4 +55,21 @@
     }
     return Objects.hash(values);
   }
+
+  @Override
+  public String toString() {
+    List<String> fieldStrings = new ArrayList<>();
+    try {
+      for (Field field : getClass().getDeclaredFields()) {
+        field.setAccessible(true);
+        fieldStrings.add(field.getName() + ": " + Objects.toString(field.get(this)));
+      }
+    } catch (IllegalArgumentException | IllegalAccessException e) {
+    }
+    String fields = String.join(", ", fieldStrings);
+    if (!"".equals(fields)) {
+      fields = "{" + fields + "}";
+    }
+    return getClass().toString() + fields;
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java b/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
index 3177ba9..11786e6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Modules.java
@@ -59,7 +59,7 @@
     public boolean onlyInvalid = false;
 
     @Option(name = "--evaluation-time", usage = "Include elapsed evaluation time on each task")
-    boolean evaluationTime = false;
+    public boolean evaluationTime = false;
 
     @Option(
         name = "--preview",
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
index 93923e1..7896417 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/PredicateCache.java
@@ -59,7 +59,7 @@
     if ("true".equalsIgnoreCase(query)) {
       return true;
     }
-    return cqb.parse(query).asMatchable().match(c);
+    return getPredicate(query).asMatchable().match(c);
   }
 
   protected Predicate<ChangeData> getPredicate(String query) throws QueryParseException {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
index b8bf285..028762c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
@@ -32,30 +32,42 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-/** Use to expand properties like ${_name} for a Task Definition. */
+/** Use to expand properties like ${_name} in the text of various definitions. */
 public class Properties {
-  public Properties(ChangeData changeData, Task definition, Map<String, String> parentProperties)
-      throws StorageException {
-    Map<String, String> expanded = new HashMap<>(parentProperties);
-    expanded.putAll(getInternalProperties(definition, changeData));
-    Map<String, String> unexpanded = definition.properties;
-    unexpanded.putAll(definition.exported);
-    new RecursiveExpander(expanded).expand(unexpanded);
+  /** Use to expand properties specifically for Tasks. */
+  public static class Task extends Expander {
+    public static final Task EMPTY_PARENT = new Task();
 
-    definition.properties = expanded;
-    for (String property : definition.exported.keySet()) {
-      definition.exported.put(property, expanded.get(property));
+    public Task() {
+      super(Collections.emptyMap());
     }
 
-    new Expander(expanded).expandFieldValues(definition, Collections.emptySet());
+    public Task(ChangeData changeData, TaskConfig.Task definition, Task parentProperties)
+        throws StorageException {
+      super(parentProperties.forDescendants());
+      valueByName.putAll(getInternalProperties(definition, changeData));
+      new RecursiveExpander(valueByName).expand(definition.getAllProperties());
+
+      definition.setExpandedProperties(valueByName);
+
+      expandFieldValues(definition, Collections.emptySet());
+    }
+
+    protected Map<String, String> forDescendants() {
+      return new HashMap<>(valueByName);
+    }
   }
 
-  public Properties(NamesFactory namesFactory, Map<String, String> properties) {
-    new Expander(properties).expandFieldValues(namesFactory, Sets.newHashSet(TaskConfig.KEY_TYPE));
+  /** Use to expand properties specifically for NamesFactories. */
+  public static class NamesFactory extends Expander {
+    public NamesFactory(TaskConfig.NamesFactory namesFactory, Task properties) {
+      super(properties.valueByName);
+      expandFieldValues(namesFactory, Sets.newHashSet(TaskConfig.KEY_TYPE));
+    }
   }
 
-  protected static Map<String, String> getInternalProperties(Task definition, ChangeData changeData)
-      throws StorageException {
+  protected static Map<String, String> getInternalProperties(
+      TaskConfig.Task definition, ChangeData changeData) throws StorageException {
     Map<String, String> properties = new HashMap<>();
 
     properties.put("_name", definition.name);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
index 77adee2..5e987ca 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
@@ -14,6 +14,7 @@
 
 package com.googlesource.gerrit.plugins.task;
 
+import com.google.common.primitives.Primitives;
 import com.google.gerrit.common.Container;
 import com.google.gerrit.entities.BranchNameKey;
 import com.google.gerrit.server.git.meta.AbstractVersionedMetaData;
@@ -43,7 +44,7 @@
     }
   }
 
-  private class Section extends Container {
+  protected class Section extends Container {
     public TaskConfig config;
 
     public Section() {
@@ -57,7 +58,6 @@
     public String fail;
     public String failHint;
     public String inProgress;
-    public String name;
     public String pass;
     public String preloadTask;
     public Map<String, String> properties;
@@ -78,7 +78,6 @@
       fail = getString(s, KEY_FAIL, null);
       failHint = getString(s, KEY_FAIL_HINT, null);
       inProgress = getString(s, KEY_IN_PROGRESS, null);
-      name = s.subSection;
       pass = getString(s, KEY_PASS, null);
       preloadTask = getString(s, KEY_PRELOAD_TASK, null);
       properties = getProperties(s, KEY_PROPERTIES_PREFIX);
@@ -90,15 +89,41 @@
     }
 
     protected TaskBase(TaskBase base) {
-      for (Field field : TaskBase.class.getDeclaredFields()) {
+      copyDeclaredFields(TaskBase.class, base);
+    }
+
+    protected <T> void copyDeclaredFields(Class<T> cls, T from) {
+      for (Field field : cls.getDeclaredFields()) {
         try {
           field.setAccessible(true);
-          field.set(this, field.get(base));
+          Class<?> fieldCls = field.getType();
+          Object val = field.get(from);
+          if (field.getType().isPrimitive()
+              || Primitives.isWrapperType(fieldCls)
+              || (val instanceof String)
+              || val == null) {
+            field.set(this, val);
+          } else if (val instanceof List) {
+            List<?> list = List.class.cast(val);
+            field.set(this, new ArrayList<>(list));
+          } else if (val instanceof Map) {
+            Map<?, ?> map = Map.class.cast(val);
+            field.set(this, new HashMap<>(map));
+          } else if (field.getName().equals("this$0")) { // Don't copy internal final field
+          } else {
+            throw new RuntimeException(
+                "Don't know how to deep copy " + fieldValueToString(field, val));
+          }
         } catch (IllegalAccessException e) {
-          throw new RuntimeException(e);
+          throw new RuntimeException(
+              "Cannot access field to copy it " + fieldValueToString(field, "unknown"));
         }
       }
     }
+
+    protected String fieldValueToString(Field field, Object val) {
+      return "field:" + field.getName() + " value:" + val + " type:" + field.getType();
+    }
   }
 
   public class Task extends TaskBase {
@@ -106,12 +131,26 @@
 
     public Task(SubSection s, boolean isVisible, boolean isTrusted) {
       super(s, isVisible, isTrusted);
-      name = getString(s, KEY_NAME, s.subSection);
+      name = s.subSection;
     }
 
     protected Task(TaskBase base) {
       super(base);
     }
+
+    protected Map<String, String> getAllProperties() {
+      Map<String, String> all = new HashMap<>(properties);
+      all.putAll(exported);
+      return all;
+    }
+
+    protected void setExpandedProperties(Map<String, String> expanded) {
+      properties.clear();
+      properties.putAll(expanded);
+      for (String property : exported.keySet()) {
+        exported.put(property, properties.get(property));
+      }
+    }
   }
 
   public class TasksFactory extends TaskBase {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
index 461d14e..9c4b476 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
@@ -40,12 +40,11 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
+import java.util.function.BiFunction;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 
 /**
@@ -94,11 +93,19 @@
     return root.getRootNodes();
   }
 
+  public Node createNodeOrNull(NodeList parent, Task definition) {
+    try {
+      return new Node(parent, definition);
+    } catch (Exception e) {
+      return null;
+    }
+  }
+
   protected class NodeList {
+    protected NodeList parent = null;
     protected LinkedList<String> path = new LinkedList<>();
     protected List<Node> nodes;
     protected Set<String> names = new HashSet<>();
-    protected Map<String, String> properties;
 
     protected void addSubDefinitions(List<Task> defs) {
       for (Task def : defs) {
@@ -107,28 +114,29 @@
     }
 
     protected void addSubDefinition(Task def) {
+      addSubDefinition(def, (d, c) -> createNodeOrNull(d, c));
+    }
+
+    protected void addSubDefinition(Task def, BiFunction<NodeList, Task, Node> nodeConstructor) {
       Node node = null;
       if (def != null && !path.contains(def.name) && names.add(def.name)) {
         // path check above detects looping definitions
         // names check above detects duplicate subtasks
-        try {
-          node = new Node(def, path, properties);
-        } catch (Exception e) {
-        } // bad definition, handled with null
+        node = nodeConstructor.apply(this, def);
       }
       nodes.add(node);
     }
 
     public ChangeData getChangeData() {
-      return TaskTree.this.changeData;
+      return parent == null ? TaskTree.this.changeData : parent.getChangeData();
+    }
+
+    protected Properties.Task getProperties() {
+      return Properties.Task.EMPTY_PARENT;
     }
   }
 
   protected class Root extends NodeList {
-    protected Root() {
-      properties = new HashMap<String, String>();
-    }
-
     public List<Node> getRootNodes() throws ConfigInvalidException, IOException {
       if (nodes == null) {
         nodes = new ArrayList<>();
@@ -144,15 +152,15 @@
 
   public class Node extends NodeList {
     public final Task task;
+    protected final Properties.Task properties;
 
-    public Node(Task definition, List<String> path, Map<String, String> parentProperties)
-        throws ConfigInvalidException, StorageException {
+    public Node(NodeList parent, Task definition) throws ConfigInvalidException, StorageException {
+      this.parent = parent;
       this.task = definition;
-      this.path.addAll(path);
+      this.path.addAll(parent.path);
       this.path.add(definition.name);
       Preloader.preload(definition);
-      new Properties(getChangeData(), definition, parentProperties);
-      properties = definition.properties;
+      properties = new Properties.Task(getChangeData(), definition, parent.getProperties());
     }
 
     public List<Node> getSubNodes() {
@@ -209,13 +217,12 @@
     }
 
     protected void addSubTasksFactoryDefinitions() throws StorageException {
-      List<Task> taskList = new ArrayList<>();
       for (String taskFactoryName : task.subTasksFactories) {
         TasksFactory tasksFactory = task.config.getTasksFactory(taskFactoryName);
         if (tasksFactory != null) {
           NamesFactory namesFactory = task.config.getNamesFactory(tasksFactory.namesFactory);
           if (namesFactory != null && namesFactory.type != null) {
-            new Properties(namesFactory, task.properties);
+            new Properties.NamesFactory(namesFactory, getProperties());
             switch (NamesFactoryType.getNamesFactoryType(namesFactory.type)) {
               case STATIC:
                 addStaticTypeTasksDefinitions(tasksFactory, namesFactory);
@@ -247,7 +254,9 @@
                   .query(changeQueryBuilderProvider.get().parse(namesFactory.changes))
                   .entities();
           for (ChangeData changeData : changeDataList) {
-            addSubDefinition(task.config.createTask(tasksFactory, changeData.getId().toString()));
+            addSubDefinition(
+                task.config.createTask(tasksFactory, changeData.getId().toString()),
+                new ChangeNodeFactory(changeData)::createChangeNodeOrNull);
           }
           return;
         }
@@ -270,6 +279,11 @@
           .getTasks();
     }
 
+    @Override
+    protected Properties.Task getProperties() {
+      return properties;
+    }
+
     protected String resolveTaskFileName(String file) throws ConfigInvalidException {
       if (file == null) {
         throw new ConfigInvalidException("External file not defined");
@@ -295,4 +309,30 @@
       return BranchNameKey.create(allUsers.get(), RefNames.refsUsers(acct));
     }
   }
+
+  public class ChangeNodeFactory {
+    public class ChangeNode extends Node {
+      public ChangeNode(NodeList parent, Task definition) throws ConfigInvalidException {
+        super(parent, definition);
+      }
+
+      public ChangeData getChangeData() {
+        return ChangeNodeFactory.this.changeData;
+      }
+    }
+
+    protected ChangeData changeData;
+
+    public ChangeNodeFactory(ChangeData changeData) {
+      this.changeData = changeData;
+    }
+
+    public ChangeNode createChangeNodeOrNull(NodeList parent, Task definition) {
+      try {
+        return new ChangeNode(parent, definition);
+      } catch (Exception e) {
+        return null;
+      }
+    }
+  }
 }
diff --git a/src/main/resources/Documentation/task.md b/src/main/resources/Documentation/task.md
index 8c1309e..fa5e834 100644
--- a/src/main/resources/Documentation/task.md
+++ b/src/main/resources/Documentation/task.md
@@ -430,13 +430,18 @@
     set-<property-name> = <property-value>
 ```
 
-Subtasks inherit all custom properties from their parents. A task is invalid
-if it attempts to override an already set property.
+Subtasks inherit all custom properties from their parents, however
+subtasks may override inherrited properties and give them new values.
 
 Example:
 ```
     [task "foo-project"]
         set-project-name = foo
+        subtask = sub-project
+        subtask = common-to-many-projects
+
+    [task "sub-project"]
+        set-project-name = sub-foo # Overrides value from 'foo-project'
         subtask = common-to-many-projects
 
     [task "common-to-many-projects"]
@@ -530,5 +535,8 @@
 
 Examples
 --------
-See [task_states](task_states.html) for a comprehensive list of examples
+See [task_states](test/task_states.html) for a comprehensive list of examples
 of task configs and their states.
+
+See what the results will look when [previewing](test/preview.html) a change
+to those states.
diff --git a/src/main/resources/Documentation/task_states.md b/src/main/resources/Documentation/task_states.md
deleted file mode 100644
index 8b0c705..0000000
--- a/src/main/resources/Documentation/task_states.md
+++ /dev/null
@@ -1,1189 +0,0 @@
-@PLUGIN@ States
-===============
-
-Below are sample config files which illustrate many examples of how task
-states are affected by their own criteria and their subtasks' states.
-
-`task.config` file in project `All-Project` on ref `refs/meta/config`.
-
-```
-[root "Root N/A"]
-  applicable = is:closed # Assumes test query is "is:open"
-
-[root "Root APPLICABLE"]
-  applicable = is:open # Assumes test query is "is:open"
-  pass = True
-  subtask = Subtask APPLICABLE
-
-[root "Root PASS"]
-  pass = True
-
-[root "Root FAIL"]
-  fail = True
-
-[root "Root straight PASS"]
-  applicable = is:open
-  pass = is:open
-
-[root "Root straight FAIL"]
-  applicable = is:open
-  fail = is:open
-  pass = is:open
-
-[root "Root PASS-fail"]
-  applicable = is:open
-  fail = NOT is:open
-
-[root "Root pass-FAIL"]
-  applicable = is:open
-  fail = is:open
-
-[root "Root PASS-waiting-fail"]
-  applicable = is:open
-  fail = NOT is:open
-  subtask = Subtask PASS
-
-[root "Root pass-WAITING-fail"]
-  applicable = is:open
-  fail = NOT is:open
-  subtask = Subtask FAIL
-
-[root "Root pass-waiting-FAIL"]
-  applicable = is:open
-  fail = is:open
-  subtask = Subtask PASS
-
-[root "Root grouping PASS (subtask PASS)"]
-  subtask = Subtask PASS
-
-[root "Root grouping WAITING (subtask READY)"]
-  subtask = Subtask READY
-
-[root "Root grouping WAITING (subtask FAIL)"]
-  subtask = Subtask FAIL
-
-[root "Root grouping NA (subtask NA)"]
-  applicable = is:open # Assumes Subtask NA has "applicable = NOT is:open"
-  subtask = Subtask NA
-
-[root "Root READY (subtask PASS)"]
-  applicable = is:open
-  pass = NOT is:open
-  subtask = Subtask PASS
-  ready-hint = You must now run the ready task
-
-[root "Root WAITING (subtask READY)"]
-  applicable = is:open
-  pass = is:open
-  subtask = Subtask READY
-
-[root "Root WAITING (subtask FAIL)"]
-  applicable = is:open
-  pass = is:open
-  subtask = Subtask FAIL
-
-[root "Root IN PROGRESS"]
-   applicable = is:open
-   in-progress = is:open
-   pass = NOT is:open
-
-[root "Root NOT IN PROGRESS"]
-   applicable = is:open
-   in-progress = NOT is:open
-   pass = NOT is:open
-
-[root "Root Optional subtasks"]
-   subtask = OPTIONAL MISSING |
-   subtask = Subtask Optional |
-
-[root "Subtasks File"]
-  subtasks-file = common.config
-
-[root "Subtasks File (Missing)"]
-  subtasks-file = common.config
-  subtasks-file = missing
-
-[root "Subtasks External"]
-  subtasks-external = user special
-
-[root "Subtasks External (Missing)"]
-  subtasks-external = user special
-  subtasks-external = missing
-
-[root "Subtasks External (User Missing)"]
-  subtasks-external = user special
-  subtasks-external = user missing
-
-[root "Subtasks External (File Missing)"]
-  subtasks-external = user special
-  subtasks-external = file missing
-
-[root "Root tasks-factory"]
-  subtasks-factory = tasks-factory static
-  subtasks-factory = tasks-factory change
-
-[root "Root tasks-factory static (empty name)"]
-  subtasks-factory = tasks-factory static (empty name)
-# Grouping task since it has no pass criteria, not output since it has no subtasks
-
-[root "Root tasks-factory static (empty name PASS)"]
-  pass = True
-  subtasks-factory = tasks-factory static (empty name)
-
-[root "Root Properties"]
-  set-root-property = root-value
-  export-root = ${_name}
-  fail = True
-  fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
-  subtask = Subtask Properties
-
-[root "Root Preload"]
-   preload-task = Subtask FAIL
-   subtask = Subtask Preload
-
-[root "Root INVALID Preload"]
-  preload-task = missing
-
-[root "INVALIDS"]
-  subtasks-file = invalids.config
-
-[root "Root NA Pass"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  pass = True
-
-[root "Root NA Fail"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  fail = True
-
-[root "NA INVALIDS"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  subtasks-file = invalids.config
-
-[tasks-factory "tasks-factory static"]
-  names-factory = names-factory static list
-  fail = True
-
-[tasks-factory "tasks-factory static (empty name)"]
-  names-factory = names-factory static (empty name list)
-  fail = True
-
-[tasks-factory "tasks-factory change"]
-  names-factory = names-factory change list
-  fail = True
-
-[task "Subtask APPLICABLE"]
-  applicable = is:open
-  pass = True
-
-[task "Subtask FAIL"]
-  applicable = is:open
-  fail = is:open
-  pass = is:open
-
-[task "Subtask READY"]
-  applicable = is:open
-  pass = NOT is:open
-  subtask = Subtask PASS
-
-[task "Subtask PASS"]
-  applicable = is:open
-  pass = is:open
-
-[task "Subtask Optional"]
-   subtask = Subtask PASS |
-   subtask = OPTIONAL MISSING | Subtask FAIL
-   subtask = OPTIONAL MISSING | OPTIONAL MISSING |
-   subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
-
-[task "Subtask NA"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-
-[task "Subtask Properties"]
-  export-subtask = ${_name}
-  subtask = Subtask Properties Hints
-  subtask = Chained ${_name}
-  subtask = Subtask Properties Reset
-  subtasks-factory = TaskFactory Properties Hints
-
-[task "Subtask Properties Hints"]
-  set-first-property = first-value
-  set-second-property = ${first-property} second-extra ${third-property}
-  set-third-property = third-value
-  fail = True
-  fail-hint = Name(${_name}) root-property(${root-property}) first-property(${first-property}) second-property(${second-property}) root(${root})
-
-[task "Chained Subtask Properties"]
-  pass = True
-
-[task "Subtask Properties Reset"]
-  pass = True
-  set-first-property = reset-first-value
-  fail-hint = first-property(${first-property})
-
-[tasks-factory "TaskFactory Properties Hints"]
-  names-factory = NamesFactory Properties
-  fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
-  fail = True
-
-[names-factory "NamesFactory Properties"]
-  type = change
-  changes = change:_change1_number OR change:${_change_number} project:${_change_project} branch:${_change_branch}
-
-[task "Subtask Preload"]
-  preload-task = Subtask READY
-  subtask = Subtask Preload Preload
-  subtask = Subtask Preload Hints PASS
-  subtask = Subtask Preload Hints FAIL
-  subtask = Subtask Preload Override Pass
-  subtask = Subtask Preload Override Fail
-  subtask = Subtask Preload Extend Subtasks
-  subtask = Subtask Preload Optional
-  subtask = Subtask Preload Properties
-
-[task "Subtask Preload Preload"]
-  preload-task = Subtask Preload with Preload
-
-[task "Subtask Preload with Preload"]
-  preload-task = Subtask PASS
-
-[task "Subtask Preload Hints PASS"]
-  preload-task = Subtask Hints
-  pass = False
-
-[task "Subtask Preload Hints FAIL"]
-  preload-task = Subtask Hints
-  fail = True
-
-[task "Subtask Preload Override Pass"]
-  preload-task = Subtask PASS
-  pass = False
-
-[task "Subtask Preload Override Fail"]
-  preload-task = Subtask FAIL
-  fail = False
-
-[task "Subtask Preload Extend Subtasks"]
-  preload-task = Subtask READY
-  subtask = Subtask APPLICABLE
-
-[task "Subtask Preload Optional"]
-  preload-task = Missing | Subtask PASS
-
-[task "Subtask Preload Properties"]
-  preload-task = Subtask Properties Hints
-  set-fourth-property = fourth-value
-  fail-hint = second-property(${second-property}) fourth-property(${fourth-property})
-
-[task "Subtask Hints"] # meant to be preloaded, not a test case in itself
-  ready-hint = Task is ready
-  fail-hint = Task failed
-
-[external "user special"]
-  user = testuser
-  file = special.config
-
-[external "user missing"]
-  user = missing
-  file = special.config
-
-[external "file missing"]
-  user = testuser
-  file = missing
-
-[names-factory "names-factory static list"]
-  name = my a task
-  name = my b task
-  name = my c task
-  name = my d task Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
-  type = static
-
-[names-factory "names-factory static (empty name list)"]
-  type = static
-
-[names-factory "names-factory change list"]
-  changes = change:_change1_number OR change:_change2_number
-  type = change
-
-```
-
-`task/common.config` file in project `All-Projects` on ref `refs/meta/config`.
-
-```
-[task "file task/common.config PASS"]
-  applicable = is:open
-  pass = is:open
-
-[task "file task/common.config FAIL"]
-  applicable = is:open
-  fail = is:open
-```
-
-`task/invalids.config` file in project `All-Projects` on ref `refs/meta/config`.
-
-```
-[task "No PASS criteria"]
-  fail-hint = Invalid without Pass criteria and without subtasks
-
-[task "WAITING (subtask INVALID)"]
-  pass = is:open
-  subtask = Subtask INVALID
-
-[task "WAITING (subtask duplicate)"]
-  subtask = Subtask INVALID
-  subtask = Subtask INVALID
-
-[task "WAITING (subtask missing)"]
-  pass = is:open
-  subtask = MISSING # security bug: subtask name appears in output
-
-[task "Grouping WAITING (subtask INVALID)"]
-  subtask = Subtask INVALID
-
-[task "Grouping WAITING (subtask missing)"]
-  subtask = MISSING  # security bug: subtask name appears in output
-
-[task "Subtask INVALID"]
-  fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
-
-[task "Subtask Optional"]
-   subtask = MISSING | MISSING
-
-[task "NA Bad PASS query"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  fail = True
-  pass = has:bad
-
-[task "NA Bad FAIL query"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  pass = True
-  fail = has:bad
-
-[task "NA Bad INPROGRESS query"]
-  applicable = NOT is:open # Assumes test query is "is:open"
-  fail = True
-  in-progress = has:bad
-
-[task "Looping"]
-  subtask = Looping
-
-[task "Looping Properties"]
-  set-A = ${B}
-  set-B = ${A}
-  fail = True
-
-[task "task (tasks-factory missing)"]
-  subtasks-factory = missing
-
-[task "task (names-factory type missing)"]
-  subtasks-factory = tasks-factory (names-factory type missing)
-
-[task "task (names-factory type INVALID)"]
-  subtasks-factory = tasks-factory (names-factory type INVALID)
-
-[task "task (names-factory duplicate)"]
-  subtasks-factory = tasks-factory (names-factory duplicate)
-
-[task "task (names-factory changes type missing)"]
-  subtasks-factory = tasks-factory change (names-factory type missing)
-
-[task "task (names-factory changes missing)"]
-  subtasks-factory = tasks-factory change (names-factory changes missing)
-
-[task "task (names-factory changes invalid)"]
-  subtasks-factory = tasks-factory change (names-factory changes invalid)
-
-[task "task (tasks-factory changes loop)"]
-  subtasks-factory = tasks-factory change loop
-
-[tasks-factory "tasks-factory (names-factory type missing)"]
-  names-factory = names-factory (type missing)
-  fail = True
-
-[tasks-factory "tasks-factory (names-factory type INVALID)"]
-  names-factory = name-factory (type INVALID)
-
-[tasks-factory "tasks-factory (names-factory duplicate)"]
-  names-factory = names-factory duplicate
-  fail = True
-
-[tasks-factory "tasks-factory change (names-factory type missing)"]
-  names-factory = names-factory change list (type missing)
-  fail = True
-
-[tasks-factory "tasks-factory change (names-factory changes missing)"]
-  names-factory = names-factory change list (changes missing)
-  fail = True
-
-[tasks-factory "tasks-factory change (names-factory changes invalid)"]
-  names-factory = names-factory change list (changes invalid)
-  fail = True
-
-[tasks-factory "tasks-factory change loop"]
-  names-factory = names-factory change constant
-  subtask = task (tasks-factory changes loop)
-  fail = true
-
-[names-factory "names-factory (type missing)"]
-  name = no type test
-
-[names-factory "names-factory change list (type missing)"]
-  changes = change:_change1_number OR change:_change2_number
-
-[names-factory "names-factory (type INVALID)"]
-  name = invalid type test
-  type = invalid
-
-[names-factory "names-factory duplicate"]
-  name = duplicate
-  name = duplicate
-  type = static
-
-[names-factory "names-factory change list (changes missing)"]
-  type = change
-
-[names-factory "names-factory change list (changes invalid)"]
-  change = change:invalidChange
-  type = change
-
-[names-factory "names-factory change constant"]
-  changes = change:_change1_number OR change:_change2_number
-  type = change
-
-```
-
-`task/special.config` file in project `All-Users` on ref `refs/users/self`.
-
-```
-[task "userfile task/special.config PASS"]
-  applicable = is:open
-  pass = is:open
-
-[task "userfile task/special.config FAIL"]
-  applicable = is:open
-  fail = is:open
-```
-
-The expected output for the above task config looks like:
-
-```
- $  ssh -x -p 29418 review-example gerrit query is:open \
-     --task--applicable --format json|head -1 |json_pp
-{
-   ...,
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "hasPass" : true,
-               "name" : "Root APPLICABLE",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask APPLICABLE",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root PASS",
-               "status" : "PASS"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root straight PASS",
-               "status" : "PASS"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root straight FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root PASS-fail",
-               "status" : "PASS"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root pass-FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root PASS-waiting-fail",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root pass-WAITING-fail",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root pass-waiting-FAIL",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root grouping PASS (subtask PASS)",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "hint" : "You must now run the ready task",
-               "name" : "Root READY (subtask PASS)",
-               "status" : "READY",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "inProgress" : true,
-               "name" : "Root IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "hasPass" : true,
-               "inProgress" : false,
-               "name" : "Root NOT IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root Optional subtasks",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask READY",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks File",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks File (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (File Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Root tasks-factory",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "my a task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "my b task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "my c task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "my d task Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "_change1_number",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "_change2_number",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root tasks-factory static (empty name PASS)",
-               "status" : "PASS"
-            },
-            {
-               "exported" : {
-                  "root" : "Root Properties"
-               },
-               "hasPass" : true,
-               "hint" : "Name(Root Properties) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-               "name" : "Root Properties",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "exported" : {
-                        "subtask" : "Subtask Properties"
-                     },
-                     "hasPass" : false,
-                     "name" : "Subtask Properties",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
-                           "name" : "Subtask Properties Hints",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Chained Subtask Properties",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Properties Reset",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Name(_change3_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change3_number",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Name(_change1_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change1_number",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "hasPass" : true,
-               "name" : "Root Preload",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "hasPass" : true,
-                     "name" : "Subtask Preload",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Preload",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Task is ready",
-                           "name" : "Subtask Preload Hints PASS",
-                           "status" : "READY"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "Task failed",
-                           "name" : "Subtask Preload Hints FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Pass",
-                           "status" : "READY"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Fail",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Extend Subtasks",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              },
-                              {
-                                 "hasPass" : true,
-                                 "name" : "Subtask APPLICABLE",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Optional",
-                           "status" : "PASS"
-                        },
-                        {
-                           "hasPass" : true,
-                           "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
-                           "name" : "Subtask Preload Properties",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
-   ...
-```
diff --git a/src/main/resources/Documentation/test/preview.md b/src/main/resources/Documentation/test/preview.md
new file mode 100644
index 0000000..e53b7d8
--- /dev/null
+++ b/src/main/resources/Documentation/test/preview.md
@@ -0,0 +1,603 @@
+[root "INVALIDS Preview"]
+  subtasks-file = invalids.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "INVALIDS Preview",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root PASS Preview"]
+  pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS Preview",
+   "status" : "PASS"
+}
+
+[root "Root READY (subtask PASS) Preview"]
+  applicable = is:open
+  pass = NOT is:open
+  subtask = Subtask PASS Preview
+  ready-hint = You must now run the ready task
+
+[task "Subtask PASS Preview"]
+  applicable = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "hint" : "You must now run the ready task",
+   "name" : "Root READY (subtask PASS) Preview",
+   "status" : "READY",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS Preview",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Subtasks External Preview"]
+  subtasks-external = user special Preview
+
+[external "user special Preview"]
+  user = testuser
+  file = special.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External Preview",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root NA Pass Preview"]
+  applicable = NOT is:open
+  pass = True
+
+{
+   "applicable" : false,
+   "hasPass" : true,
+   "name" : "Root NA Pass Preview",
+   "status" : "PASS"
+}
+
+[root "NA INVALIDS Preview"]
+  applicable = NOT is:open
+  subtasks-file = invalids.config
+
+{
+   "applicable" : false,
+   "hasPass" : false,
+   "name" : "NA INVALIDS Preview",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: !invalid
+         "status" : "INVALID"   # Only Test Suite: invalid
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
diff --git a/src/main/resources/Documentation/test/task_states.md b/src/main/resources/Documentation/test/task_states.md
new file mode 100644
index 0000000..ea09541
--- /dev/null
+++ b/src/main/resources/Documentation/test/task_states.md
@@ -0,0 +1,2093 @@
+@PLUGIN@ States
+===============
+
+Below are sample config files which illustrate many examples of how task
+states are affected by their own criteria and their subtasks' states.
+To better help visualize the output that each `root` example leads to,
+the json output for the root definition (and any definitions that it
+refers to) will be placed inline right after the root. Naturally, this
+json is not a part of the config, however it is part of the expected
+output for task config when running the following:
+
+```
+ $  ssh -x -p 29418 review-example gerrit query is:open \
+     --task--all --format json|head -1 |json_pp
+```
+
+The config below is expected to be in the `task.config` file in project
+`All-Projects` on ref `refs/meta/config`.
+
+```
+[root "Root N/A"]
+  applicable = is:closed # Assumes test query is "is:open"
+
+{
+   "applicable" : false,
+   "hasPass" : false,
+   "name" : "Root N/A",
+   "status" : "INVALID"
+}
+
+[root "Root APPLICABLE"]
+  applicable = is:open # Assumes test query is "is:open"
+  pass = True
+  subtask = Subtask APPLICABLE
+
+[task "Subtask APPLICABLE"]
+  applicable = is:open
+  pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root APPLICABLE",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask APPLICABLE",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root PASS"]
+  pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS",
+   "status" : "PASS"
+}
+
+[root "Root FAIL"]
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root FAIL",
+   "status" : "FAIL"
+}
+
+[root "Root straight PASS"]
+  applicable = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root straight PASS",
+   "status" : "PASS"
+}
+
+[root "Root straight FAIL"]
+  applicable = is:open
+  fail = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root straight FAIL",
+   "status" : "FAIL"
+}
+
+[root "Root PASS-fail"]
+  applicable = is:open
+  fail = NOT is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS-fail",
+   "status" : "PASS"
+}
+
+[root "Root pass-FAIL"]
+  applicable = is:open
+  fail = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root pass-FAIL",
+   "status" : "FAIL"
+}
+
+[root "Root PASS-waiting-fail"]
+  applicable = is:open
+  fail = NOT is:open
+  subtask = Subtask PASS
+
+[task "Subtask PASS"]
+  applicable = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root PASS-waiting-fail",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root pass-WAITING-fail"]
+  applicable = is:open
+  fail = NOT is:open
+  subtask = Subtask FAIL
+
+[task "Subtask FAIL"]
+  applicable = is:open
+  fail = is:open
+  pass = is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root pass-WAITING-fail",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root pass-waiting-FAIL"]
+  applicable = is:open
+  fail = is:open
+  subtask = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root pass-waiting-FAIL",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root grouping PASS (subtask PASS)"]
+  subtask = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping PASS (subtask PASS)",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root grouping WAITING (subtask READY)"]
+  subtask = Subtask READY
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping WAITING (subtask READY)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask READY",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root grouping WAITING (subtask FAIL)"]
+  subtask = Subtask FAIL
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping WAITING (subtask FAIL)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root grouping NA (subtask NA)"]
+  applicable = is:open # Assumes Subtask NA has "applicable = NOT is:open"
+  subtask = Subtask NA
+
+[task "Subtask NA"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root grouping NA (subtask NA)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : false,
+         "hasPass" : false,
+         "name" : "Subtask NA",
+         "status" : "INVALID"
+      }
+   ]
+}
+
+[root "Root READY (subtask PASS)"]
+  applicable = is:open
+  pass = NOT is:open
+  subtask = Subtask PASS
+  ready-hint = You must now run the ready task
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "hint" : "You must now run the ready task",
+   "name" : "Root READY (subtask PASS)",
+   "status" : "READY",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask PASS",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root WAITING (subtask READY)"]
+  applicable = is:open
+  pass = is:open
+  subtask = Subtask READY
+
+[task "Subtask READY"]
+  applicable = is:open
+  pass = NOT is:open
+  subtask = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root WAITING (subtask READY)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask READY",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root WAITING (subtask FAIL)"]
+  applicable = is:open
+  pass = is:open
+  subtask = Subtask FAIL
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root WAITING (subtask FAIL)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root IN PROGRESS"]
+   applicable = is:open
+   in-progress = is:open
+   pass = NOT is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "inProgress" : true,
+   "name" : "Root IN PROGRESS",
+   "status" : "READY"
+}
+
+[root "Root NOT IN PROGRESS"]
+   applicable = is:open
+   in-progress = NOT is:open
+   pass = NOT is:open
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "inProgress" : false,
+   "name" : "Root NOT IN PROGRESS",
+   "status" : "READY"
+}
+
+[root "Root OPTIONAL MISSING"]
+   subtask = OPTIONAL MISSING |
+   pass = True
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root OPTIONAL MISSING",
+   "status" : "PASS"
+}
+
+[root "Root Optional subtask EXISTS"]
+   subtask = Subtask Optional EXISTS |
+
+[task "Subtask Optional EXISTS"]
+   subtask = Subtask PASS |
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask EXISTS",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional EXISTS",
+         "status" : "PASS",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Optional subtask MISSING then EXISTS"]
+   subtask = Subtask Optional MISSING then EXISTS |
+
+[task "Subtask Optional MISSING then EXISTS"]
+   subtask = OPTIONAL MISSING | Subtask FAIL
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask MISSING then EXISTS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional MISSING then EXISTS",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask FAIL",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Optional subtask MISSING then MISSING"]
+   subtask = Subtask Optional MISSING then MISSING |
+
+[task "Subtask Optional MISSING then MISSING"]
+   subtask = OPTIONAL MISSING | OPTIONAL MISSING |
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask MISSING then MISSING",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional MISSING then MISSING"
+      }
+   ]
+}
+
+[root "Root Optional subtask MISSING then MISSING then EXISTS"]
+   subtask = Subtask Optional MISSING then MISSING then EXISTS |
+
+[task "Subtask Optional MISSING then MISSING then EXISTS"]
+   subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Optional subtask MISSING then MISSING then EXISTS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional MISSING then MISSING then EXISTS",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask READY",
+               "status" : "READY",
+               "subTasks" : [
+                  {
+                     "applicable" : true,
+                     "hasPass" : true,
+                     "name" : "Subtask PASS",
+                     "status" : "PASS"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+[root "Subtasks File"]
+  subtasks-file = common.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks File",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Subtasks File (Missing)"]
+  subtasks-file = common.config
+  subtasks-file = missing
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks File (Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "file task/common.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Subtasks External"]
+  subtasks-external = user special
+
+[external "user special"]
+  user = testuser
+  file = special.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Subtasks External (Missing)"]
+  subtasks-external = user special
+  subtasks-external = missing
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External (Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      }
+   ]
+}
+
+[root "Subtasks External (User Missing)"]
+  subtasks-external = user special
+  subtasks-external = user missing
+
+[external "user missing"]
+  user = missing
+  file = special.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External (User Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      }
+   ]
+}
+
+[root "Subtasks External (File Missing)"]
+  subtasks-external = user special
+  subtasks-external = file missing
+
+[external "file missing"]
+  user = testuser
+  file = missing
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Subtasks External (File Missing)",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config PASS",
+         "status" : "PASS"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "userfile task/special.config FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root tasks-factory STATIC"]
+  subtasks-factory = tasks-factory static
+
+[tasks-factory "tasks-factory static"]
+  names-factory = names-factory static list
+  fail = True
+
+[names-factory "names-factory static list"]
+  type = static
+  name = my a task
+  name = my b task
+  name = my c task
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root tasks-factory STATIC",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "my a task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "my b task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "my c task",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root tasks-factory CHANGE"]
+  subtasks-factory = tasks-factory change
+
+[tasks-factory "tasks-factory change"]
+  names-factory = names-factory change list
+  fail = True
+
+[names-factory "names-factory change list"]
+  changes = change:_change1_number OR change:_change2_number
+  type = change
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root tasks-factory CHANGE",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change1_number",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change2_number",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root tasks-factory static (empty name)"]
+  subtasks-factory = tasks-factory static (empty name)
+  # Grouping task since it has no pass criteria, not output since it has no subtasks
+
+[tasks-factory "tasks-factory static (empty name)"]
+  names-factory = names-factory static (empty name list)
+  fail = True
+
+[names-factory "names-factory static (empty name list)"]
+  type = static
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root tasks-factory static (empty name)"
+}
+
+[root "Root tasks-factory static (empty name PASS)"]
+  pass = True
+  subtasks-factory = tasks-factory static (empty name)
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root tasks-factory static (empty name PASS)",
+   "status" : "PASS"
+}
+
+[root "Root Properties"]
+  set-root-property = root-value
+  subtask = Subtask Properties
+
+[task "Subtask Properties"]
+  subtask = Subtask Properties Hints
+
+[task "Subtask Properties Hints"]
+  set-first-property = first-value
+  set-second-property = ${first-property} second-extra ${third-property}
+  set-third-property = third-value
+  fail = True
+  fail-hint = root-property(${root-property}) first-property(${first-property}) second-property(${second-property})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Properties",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value)",
+               "name" : "Subtask Properties Hints",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+
+[root "Root Properties Reset By Subtask"]
+  set-root-to-reset-by-subtask = reset-my-root-value
+  subtask = Subtask Properties Reset
+
+[task "Subtask Properties Reset"]
+  fail = True
+  set-root-to-reset-by-subtask = reset-by-subtask-root-value
+  fail-hint = root-to-reset-by-subtask:(${root-to-reset-by-subtask})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties Reset By Subtask",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "root-to-reset-by-subtask:(reset-by-subtask-root-value)",
+         "name" : "Subtask Properties Reset",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties Exports"]
+  export-root-exported = ${_name}
+  subtask = Subtask Properties Exports
+  fail = True
+  fail-hint = root-exported(${root-exported})
+
+[task "Subtask Properties Exports"]
+  export-subtask-exported = ${_name}
+  fail = True
+  fail-hint = root-exported(${root-exported}) subtask-exported(${subtask-exported})
+
+{
+   "applicable" : true,
+   "exported" : {
+      "root-exported" : "Root Properties Exports"
+   },
+   "hasPass" : true,
+   "hint" : "root-exported(Root Properties Exports)",
+   "name" : "Root Properties Exports",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "exported" : {
+            "subtask-exported" : "Subtask Properties Exports"
+         },
+         "hasPass" : true,
+         "hint" : "root-exported(Root Properties Exports) subtask-exported(Subtask Properties Exports)",
+         "name" : "Subtask Properties Exports",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Internal Properties"]
+  export-root = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  set-root-internals = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  fail = True
+  fail-hint = Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  subtask = Subtask Internal Properties
+
+[task "Subtask Internal Properties"]
+  fail = True
+  fail-hint = root-internals(${root-internals}) Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+
+{
+   "applicable" : true,
+   "exported" : {
+      "root" : "Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)"
+   },
+   "hasPass" : true,
+   "hint" : "Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+   "name" : "Root Internal Properties",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "root-internals(Name(Root Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)) Name(Subtask Internal Properties) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "Subtask Internal Properties",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Subtask Via Property"]
+  set-subtask = Subtask
+  subtask = ${subtask} Via Property
+
+[task "Subtask Via Property"]
+  subtask = Second ${_name}
+
+[task "Second Subtask Via Property"]
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Subtask Via Property",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Via Property",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Second Subtask Via Property",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Properties tasks-factory STATIC"]
+  subtasks-factory = tasks-factory STATIC Properties
+
+[tasks-factory "tasks-factory STATIC Properties"]
+  set-welcome-message = Welcome to the jungle
+  names-factory = names-factory static list
+  fail-hint = ${welcome-message} Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties tasks-factory STATIC",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the jungle Name(my a task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "my a task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the jungle Name(my b task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "my b task",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the jungle Name(my c task) Change Number(_change_number) Change Id(_change_id) Change Project(_change_project) Change Branch(_change_branch) Change Status(_change_status) Change Topic(_change_topic)",
+         "name" : "my c task",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties tasks-factory CHANGE"]
+  subtasks-factory = tasks-factory CHANGE Properties
+
+[tasks-factory "tasks-factory CHANGE Properties"]
+  set-welcome-message = Welcome to the pleasuredome
+  names-factory = names-factory a change
+  fail-hint = ${welcome-message} Name(${_name}) Change Number(${_change_number}) Change Id(${_change_id}) Change Project(${_change_project}) Change Branch(${_change_branch}) Change Status(${_change_status}) Change Topic(${_change_topic})
+  fail = True
+
+[names-factory "names-factory a change"]
+  type = change
+  changes = change:_change1_number OR change:_change2_number
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties tasks-factory CHANGE",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the pleasuredome Name(_change1_number) Change Number(_change1_number) Change Id(_change1_id) Change Project(_change1_project) Change Branch(_change1_branch) Change Status(_change1_status) Change Topic(_change1_topic)",
+         "name" : "_change1_number",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Welcome to the pleasuredome Name(_change2_number) Change Number(_change2_number) Change Id(_change2_id) Change Project(_change2_project) Change Branch(_change2_branch) Change Status(_change2_status) Change Topic(_change2_topic)",
+         "name" : "_change2_number",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties names-factory STATIC"]
+  subtasks-factory = tasks-factory Properties names-factory STATIC
+
+[tasks-factory "tasks-factory Properties names-factory STATIC"]
+  names-factory = Properties names-factory STATIC
+  fail = True
+
+[names-factory "Properties names-factory STATIC"]
+  type = static
+  name = Change Number(${_change_number})
+  name = Change Id(${_change_id})
+  name = Change Project(${_change_project})
+  name = Change Branch(${_change_branch})
+  name = Change Status(${_change_status})
+  name = Change Topic(${_change_topic})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties names-factory STATIC",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Number(_change_number)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Id(_change_id)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Project(_change_project)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Branch(_change_branch)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Status(_change_status)",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Change Topic(_change_topic)",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties names-factory CHANGE"]
+  subtasks-factory = tasks-factory Properties names-factory CHANGE
+
+[tasks-factory "tasks-factory Properties names-factory CHANGE"]
+  names-factory = Properties names-factory CHANGE
+  fail = True
+
+[names-factory "Properties names-factory CHANGE"]
+  type = change
+  changes = change:_change1_number OR change:${_change_number} project:${_change_project} branch:${_change_branch}
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties names-factory CHANGE",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change_number",
+         "status" : "FAIL"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "_change1_number",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Properties Expansion"]
+  applicable = status:open
+  subtask = Subtask Property Expansion fail-hint
+
+[task "Subtask Property Expansion fail-hint"]
+  subtasks-factory = tasks-factory Property Expansion fail-hint
+
+[tasks-factory "tasks-factory Property Expansion fail-hint"]
+  set-first-property = first-property ${_name}
+  fail-hint = ${first-property}
+  fail = true
+  names-factory = names-factory static list
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Properties Expansion",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Property Expansion fail-hint",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "first-property my a task",
+               "name" : "my a task",
+               "status" : "FAIL"
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "first-property my b task",
+               "name" : "my b task",
+               "status" : "FAIL"
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "hint" : "first-property my c task",
+               "name" : "my c task",
+               "status" : "FAIL"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Preload"]
+   preload-task = Subtask FAIL
+   subtask = Subtask Preload
+
+[task "Subtask Preload"]
+  preload-task = Subtask READY
+
+{
+   "applicable" : true,
+   "hasPass" : true,
+   "name" : "Root Preload",
+   "status" : "FAIL",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Preload",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Preload Preload"]
+  subtask = Subtask Preload Preload
+
+[task "Subtask Preload Preload"]
+  preload-task = Subtask Preload with Preload
+
+[task "Subtask Preload with Preload"]
+  preload-task = Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Preload",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Preload Preload",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root Preload Hints PASS"]
+  subtask = Subtask Preload Hints PASS
+
+[task "Subtask Preload Hints PASS"]
+  preload-task = Subtask Hints
+  pass = False
+
+[task "Subtask Hints"] # meant to be preloaded, not a test case in itself
+  ready-hint = Task is ready
+  fail-hint = Task failed
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Hints PASS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Task is ready",
+         "name" : "Subtask Preload Hints PASS",
+         "status" : "READY"
+      }
+   ]
+}
+
+[root "Root Preload Hints FAIL"]
+  subtask = Subtask Preload Hints FAIL
+
+[task "Subtask Preload Hints FAIL"]
+  preload-task = Subtask Hints
+  fail = True
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Hints FAIL",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "Task failed",
+         "name" : "Subtask Preload Hints FAIL",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root Override Preload Pass"]
+  subtask = Subtask Override Preload Pass
+
+[task "Subtask Override Preload Pass"]
+  preload-task = Subtask PASS
+  pass = False
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Override Preload Pass",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Override Preload Pass",
+         "status" : "READY"
+      }
+   ]
+}
+
+[root "Root Override Preload Fail"]
+  subtask = Subtask Override Preload Fail
+
+[task "Subtask Override Preload Fail"]
+  preload-task = Subtask FAIL
+  fail = False
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Override Preload Fail",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Override Preload Fail",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root Append Preloaded Subtasks"]
+  subtask = Subtask Append Preloaded Subtasks
+
+[task "Subtask Append Preloaded Subtasks"]
+  preload-task = Subtask READY
+  subtask = Subtask APPLICABLE
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Append Preloaded Subtasks",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Append Preloaded Subtasks",
+         "status" : "READY",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask PASS",
+               "status" : "PASS"
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "Subtask APPLICABLE",
+               "status" : "PASS"
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root Preload Optional"]
+  subtask = Subtask Preload Optional
+[task "Subtask Preload Optional"]
+  preload-task = Missing | Subtask PASS
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Optional",
+   "status" : "PASS",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "Subtask Preload Optional",
+         "status" : "PASS"
+      }
+   ]
+}
+
+[root "Root Preload Properties"]
+  subtask = Subtask Preload Properties
+
+[task "Subtask Preload Properties"]
+  preload-task = Subtask Properties Hints
+  set-fourth-property = fourth-value
+  fail-hint = second-property(${second-property}) fourth-property(${fourth-property})
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "Root Preload Properties",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
+         "name" : "Subtask Preload Properties",
+         "status" : "FAIL"
+      }
+   ]
+}
+
+[root "Root INVALID Preload"]
+  preload-task = missing
+
+{
+   "name" : "UNKNOWN",
+   "status" : "INVALID"
+}
+
+[root "INVALIDS"]
+  subtasks-file = invalids.config
+
+{
+   "applicable" : true,
+   "hasPass" : false,
+   "name" : "INVALIDS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+[root "Root NA Pass"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  pass = True
+
+{
+   "applicable" : false,
+   "hasPass" : true,
+   "name" : "Root NA Pass",
+   "status" : "PASS"
+}
+
+[root "Root NA Fail"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  fail = True
+
+{
+   "applicable" : false,
+   "hasPass" : true,
+   "name" : "Root NA Fail",
+   "status" : "FAIL"
+}
+
+[root "NA INVALIDS"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  subtasks-file = invalids.config
+
+{
+   "applicable" : false,
+   "hasPass" : false,
+   "name" : "NA INVALIDS",
+   "status" : "WAITING",
+   "subTasks" : [
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "No PASS criteria",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "WAITING (subtask duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : true,
+         "name" : "WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : false,
+               "name" : "Subtask INVALID",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Grouping WAITING (subtask missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask INVALID",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Subtask Optional",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad PASS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad FAIL query",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : false,
+         "hasPass" : true,
+         "name" : "NA Bad INPROGRESS query",
+         "status" : "FAIL"      # Only Test Suite: all
+         "status" : "INVALID"   # Only Test Suite: !all
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "Looping",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "name" : "UNKNOWN",
+         "status" : "INVALID"
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory type INVALID)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory duplicate)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "duplicate",
+               "status" : "FAIL"
+            },
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes type missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes missing)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (names-factory changes invalid)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "name" : "UNKNOWN",
+               "status" : "INVALID"
+            }
+         ]
+      },
+      {
+         "applicable" : true,
+         "hasPass" : false,
+         "name" : "task (tasks-factory changes loop)",
+         "status" : "WAITING",
+         "subTasks" : [
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change1_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            },
+            {
+               "applicable" : true,
+               "hasPass" : true,
+               "name" : "_change2_number",
+               "status" : "FAIL",
+               "subTasks" : [
+                  {
+                     "name" : "UNKNOWN",
+                     "status" : "INVALID"
+                  }
+               ]
+            }
+         ]
+      }
+   ]
+}
+
+```
+
+`task/common.config` file in project `All-Projects` on ref `refs/meta/config`.
+
+```
+[task "file task/common.config PASS"]
+  applicable = is:open
+  pass = is:open
+
+[task "file task/common.config FAIL"]
+  applicable = is:open
+  fail = is:open
+```
+
+`task/invalids.config` file in project `All-Projects` on ref `refs/meta/config`.
+
+```
+[task "No PASS criteria"]
+  fail-hint = Invalid without Pass criteria and without subtasks
+
+[task "WAITING (subtask INVALID)"]
+  pass = is:open
+  subtask = Subtask INVALID
+
+[task "WAITING (subtask duplicate)"]
+  subtask = Subtask INVALID
+  subtask = Subtask INVALID
+
+[task "WAITING (subtask missing)"]
+  pass = is:open
+  subtask = MISSING # security bug: subtask name appears in output
+
+[task "Grouping WAITING (subtask INVALID)"]
+  subtask = Subtask INVALID
+
+[task "Grouping WAITING (subtask missing)"]
+  subtask = MISSING # security bug: subtask name appears in output
+
+[task "Subtask INVALID"]
+  fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
+
+[task "Subtask Optional"]
+   subtask = MISSING | MISSING
+
+[task "NA Bad PASS query"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  fail = True
+  pass = has:bad
+
+[task "NA Bad FAIL query"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  pass = True
+  fail = has:bad
+
+[task "NA Bad INPROGRESS query"]
+  applicable = NOT is:open # Assumes test query is "is:open"
+  fail = True
+  in-progress = has:bad
+
+[task "Looping"]
+  subtask = Looping
+
+[task "Looping Properties"]
+  set-A = ${B}
+  set-B = ${A}
+  fail = True
+
+[task "task (tasks-factory missing)"]
+  subtasks-factory = missing
+
+[task "task (names-factory type missing)"]
+  subtasks-factory = tasks-factory (names-factory type missing)
+
+[task "task (names-factory type INVALID)"]
+  subtasks-factory = tasks-factory (names-factory type INVALID)
+
+[task "task (names-factory duplicate)"]
+  subtasks-factory = tasks-factory (names-factory duplicate)
+
+[task "task (names-factory changes type missing)"]
+  subtasks-factory = tasks-factory change (names-factory type missing)
+
+[task "task (names-factory changes missing)"]
+  subtasks-factory = tasks-factory change (names-factory changes missing)
+
+[task "task (names-factory changes invalid)"]
+  subtasks-factory = tasks-factory change (names-factory changes invalid)
+
+[task "task (tasks-factory changes loop)"]
+  subtasks-factory = tasks-factory change loop
+
+[tasks-factory "tasks-factory (names-factory type missing)"]
+  names-factory = names-factory (type missing)
+  fail = True
+
+[tasks-factory "tasks-factory (names-factory type INVALID)"]
+  names-factory = name-factory (type INVALID)
+
+[tasks-factory "tasks-factory (names-factory duplicate)"]
+  names-factory = names-factory duplicate
+  fail = True
+
+[tasks-factory "tasks-factory change (names-factory type missing)"]
+  names-factory = names-factory change list (type missing)
+  fail = True
+
+[tasks-factory "tasks-factory change (names-factory changes missing)"]
+  names-factory = names-factory change list (changes missing)
+  fail = True
+
+[tasks-factory "tasks-factory change (names-factory changes invalid)"]
+  names-factory = names-factory change list (changes invalid)
+  fail = True
+
+[tasks-factory "tasks-factory change loop"]
+  names-factory = names-factory change constant
+  subtask = task (tasks-factory changes loop)
+  fail = True
+
+[names-factory "names-factory (type missing)"]
+  name = no type test
+
+[names-factory "names-factory change list (type missing)"]
+  changes = change:_change1_number OR change:_change2_number
+
+[names-factory "names-factory (type INVALID)"]
+  name = invalid type test
+  type = invalid
+
+[names-factory "names-factory duplicate"]
+  name = duplicate
+  name = duplicate
+  type = static
+
+[names-factory "names-factory change list (changes missing)"]
+  type = change
+
+[names-factory "names-factory change list (changes invalid)"]
+  change = change:invalidChange
+  type = change
+
+[names-factory "names-factory change constant"]
+  changes = change:_change1_number OR change:_change2_number
+  type = change
+
+```
+
+`task/special.config` file in project `All-Users` on ref `refs/users/self`.
+
+```
+[task "userfile task/special.config PASS"]
+  applicable = is:open
+  pass = is:open
+
+[task "userfile task/special.config FAIL"]
+  applicable = is:open
+  fail = is:open
+```
diff --git a/test/all b/test/all
deleted file mode 100644
index 4832bba..0000000
--- a/test/all
+++ /dev/null
@@ -1,1134 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "Root N/A",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root APPLICABLE",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask APPLICABLE",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root straight PASS",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root straight FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS-fail",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root pass-FAIL",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS-waiting-fail",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root pass-WAITING-fail",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root pass-waiting-FAIL",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping PASS (subtask PASS)",
-               "status" : "PASS",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping NA (subtask NA)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : false,
-                     "hasPass" : false,
-                     "name" : "Subtask NA",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "hint" : "You must now run the ready task",
-               "name" : "Root READY (subtask PASS)",
-               "status" : "READY",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask READY)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask READY",
-                     "status" : "READY",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root WAITING (subtask FAIL)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "inProgress" : true,
-               "name" : "Root IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "inProgress" : false,
-               "name" : "Root NOT IN PROGRESS",
-               "status" : "READY"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root Optional subtasks",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask READY",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "applicable" : true,
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks File",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks File (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "file task/common.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (File Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root tasks-factory",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my a task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my b task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my c task",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "my d task Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "_change1_number",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "_change2_number",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root tasks-factory static (empty name)"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root tasks-factory static (empty name PASS)",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "exported" : {
-                  "root" : "Root Properties"
-               },
-               "hasPass" : true,
-               "hint" : "Name(Root Properties) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-               "name" : "Root Properties",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "exported" : {
-                        "subtask" : "Subtask Properties"
-                     },
-                     "hasPass" : false,
-                     "name" : "Subtask Properties",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
-                           "name" : "Subtask Properties Hints",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Chained Subtask Properties",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Properties Reset",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Name(_change3_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change3_number",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Name(_change1_number) Change Number(_change3_number) Change Id(_change3_id) Change Project(_change3_project) Change Branch(_change3_branch) Change Status(_change3_status) Change Topic(_change3_topic)",
-                           "name" : "_change1_number",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root Preload",
-               "status" : "FAIL",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask Preload",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask PASS",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Preload",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Task is ready",
-                           "name" : "Subtask Preload Hints PASS",
-                           "status" : "READY"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "Task failed",
-                           "name" : "Subtask Preload Hints FAIL",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Pass",
-                           "status" : "READY"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Override Fail",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Extend Subtasks",
-                           "status" : "READY",
-                           "subTasks" : [
-                              {
-                                 "applicable" : true,
-                                 "hasPass" : true,
-                                 "name" : "Subtask PASS",
-                                 "status" : "PASS"
-                              },
-                              {
-                                 "applicable" : true,
-                                 "hasPass" : true,
-                                 "name" : "Subtask APPLICABLE",
-                                 "status" : "PASS"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "Subtask Preload Optional",
-                           "status" : "PASS"
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "hint" : "second-property(first-value second-extra third-value) fourth-property(fourth-value)",
-                           "name" : "Subtask Preload Properties",
-                           "status" : "FAIL"
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : true,
-               "name" : "Root NA Pass",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : false,
-               "hasPass" : true,
-               "name" : "Root NA Fail",
-               "status" : "FAIL"
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/check_task_statuses.sh b/test/check_task_statuses.sh
index beff75a..5b7e161 100755
--- a/test/check_task_statuses.sh
+++ b/test/check_task_statuses.sh
@@ -1,4 +1,18 @@
-#!/bin/bash
+#!/usr/bin/env bash
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
 
 # Usage:
 # All-Projects.git - must have 'Push' rights on refs/meta/config
@@ -15,6 +29,120 @@
     fi
 }
 
+# output must match expected to pass
+result_out() { # test expected actual
+    local name=$1 expected=$2 actual=$3
+
+    [ "$expected" = "$actual" ]
+    result "$name" "$(diff <(echo "$expected") <(echo "$actual"))"
+}
+
+result_root() { # group root expected_file actual_file
+    local name="$1 - $(echo "$2" | sed -es'/Root //')"
+    result_out "$name" "$(get_root "$2" < "$3")" "$(get_root "$2" < "$4")"
+}
+
+# -------- Git Config
+
+config() { git config -f "$CONFIG" "$@" ; } # [args]...
+config_section_keys() { # section > keys ...
+    # handlers.handler-filter filter.sh -> handler-filter
+    config -l --name-only |\
+        grep "^$1\." | \
+        sed -es"/^$1\.//;s/\..*$//" |\
+        awk '$0 != prev ; {prev = $0}'
+}
+
+# -------- Pre JSON --------
+#
+# pre_json is a "templated json" used in the test docs to express test results. It looks
+# like json but has some extra comments to express when a certain output should be used.
+# These comments look like: "# Only Test Suite: <suite>"
+#
+
+remove_suite() { # suite < pre_json > json
+    grep -v "# Only Test Suite: $1" | \
+    sed -e's/# Only Test Suite:.*$//; s/ *$//'
+}
+
+remove_not_suite() { remove_suite !"$1" ; } # suite < pre_json > json
+
+# -------- Test Doc Format --------
+#
+# Test Doc Format has intermixed git config task definitions with json roots. This
+# makes it easy to define tests close to their outputs. Be aware that all of the
+# config will get consolidated into a single file, so non root config will be shared
+# amongst all the roots.
+#
+
+# Sample Test Doc for 2 roots:
+#
+# [root "Root PASS"]
+#   pass = True
+#
+# {
+#    "applicable" : true,
+#    "hasPass" : true,
+#    "name" : "Root PASS",
+#    "status" : "PASS"
+# }
+#
+# [root "Root FAIL"]
+#   fail = True
+#
+# {
+#    <other root>
+# }
+
+# Strip the json from Test Doc formatted text. For the sample above, the output would be:
+#
+# [root "Root PASS"]
+#   pass = True
+#
+# [root "Root FAIL"]
+#   fail = True
+# ...
+#
+testdoc_2_cfg() { awk '/^\{/,/^$/ { next } ; 1' ; } # testdoc_format > task_config
+
+# Strip the git config from Test Doc formatted text. For the sample above, the output would be:
+#
+# { "plugins" : [
+#     { "name" : "task",
+#       "roots" : [
+#         {
+#           "applicable" : true,
+#           "hasPass" : true,
+#           "name" : "Root PASS",
+#           "status" : "PASS"
+#        },
+#        {
+#           <other root>
+#        },
+#    ...
+# }
+testdoc_2_pjson() { # < testdoc_format > pjson_task_roots
+    awk 'BEGIN { print "{ \"plugins\" : [ { \"name\" : \"task\", \"roots\" : [" }; \
+         /^\{/  { open=1 }; \
+         open && end { print "}," ; end=0 }; \
+         /^\}/  { open=0 ; end=1 }; \
+         open; \
+         END   { print "}]}]}" }'
+}
+
+# ---- JSON PARSING ----
+
+json_pp() { # < json > json
+    python -c "import sys, json; \
+            print json.dumps(json.loads(sys.stdin.read()), indent=3, \
+            separators=(',', ' : '), sort_keys=True)"
+}
+
+json_val_by() { # json index|'key' > value
+    echo "$1" | python -c "import json,sys;print json.load(sys.stdin)[$2]"
+}
+json_val_by_key() { json_val_by "$1" "'$2'" ; }  # json key > value
+
 # --------
 gssh() { ssh -x -p "$PORT" "$SERVER" gerrit "$@" ; } # cmd [args]...
 
@@ -24,27 +152,55 @@
 
 commit_message() { printf "$1 \n\nChange-Id: $2" ; } # message change-id > commit_msg
 
+err() { echo "ERROR: $1" >&2 ; exit 1 ; }
+
 # Run a test setup command quietly, exit on failure
-q_setup() { # cmd [args...]
-  local out ; out=$("$@" 2>&1) || { echo "$out" ; exit ; }
+q_setup() { local out ; out=$("$@" 2>&1) || err "$out" ; } # cmd [args...]
+
+ensure() { "$@" || err "$1 results are not valid" ; } # cmd [args]... < data > data
+
+set_change() { # change_json
+    { CHANGE=("$(json_val_by_key "$1" number)" \
+        "$(json_val_by_key "$1" id)" \
+        "$(json_val_by_key "$1" project)" \
+        "refs/heads/$(json_val_by_key "$1" branch)" \
+        "$(json_val_by_key "$1" status)" \
+        "$(json_val_by_key "$1" topic)") ; } 2> /dev/null
 }
 
-replace_change_properties() { # file change_token change_number change_id project branch status topic
+# change_token change_number change_id project branch status topic < templated_txt > change_txt
+replace_change_properties() {
+    sed -e "s|_change$1_number|$2|g" \
+        -e "s|_change$1_id|$3|g" \
+        -e "s|_change$1_project|$4|g" \
+        -e "s|_change$1_branch|$5|g" \
+        -e "s|_change$1_status|$6|g" \
+        -e "s|_change$1_topic|$7|g"
+}
 
-    sed -i -e "s/_change$2_number/$3/g" \
-              -e "s/_change$2_id/$4/g" \
-              -e "s/_change$2_project/$5/g" \
-              -e "s/_change$2_branch/$6/g" \
-              -e "s/_change$2_status/$7/g" \
-              -e "s/_change$2_topic/$8/g" "$1"
+replace_default_changes() {
+    replace_change_properties "1" "${CHANGE1[@]}" | replace_change_properties "2" "${CHANGE2[@]}"
 }
 
 replace_user() { # < text_with_testuser > text_with_$USER
     sed -e"s/testuser/$USER/"
 }
 
+strip_non_applicable() { ensure "$MYDIR"/strip_non_applicable.py ; } # < json > json
+strip_non_invalid() { ensure "$MYDIR"/strip_non_invalid.py ; } # < json > json
+
+get_root() { # root < task_plugin_ouptut > root_json
+    python -c "if True: # NOP to start indent
+        import sys, json
+
+        roots=json.loads(sys.stdin.read())['plugins'][0]['roots']
+        for root in roots:
+            if 'name' in root.keys() and root['name']=='$1':
+                print json.dumps(root, indent=3, separators=(',', ' : '), sort_keys=True)"
+}
+
 example() { # example_num
-    awk '/```/{Q++;E=(Q+1)/2};E=='"$1" < "$DOC_STATES" | grep -v '```' | replace_user
+    echo "$DOC_STATES" | awk '/```/{Q++;E=(Q+1)/2};E=='"$1" | grep -v '```' | replace_user
 }
 
 get_change_num() { # < gerrit_push_response > changenum
@@ -95,31 +251,42 @@
     )
 }
 
-query() { # query
-    gssh query "$@" \
-        --format json | head -1 | python -c "import sys, json; \
-        print json.dumps(json.loads(sys.stdin.read()), indent=3, \
-        separators=(',', ' : '), sort_keys=True)"
+query_plugins() { # query
+    gssh query "$@" --format json | head -1 | python -c "import sys, json; \
+        plugins={}; plugins['plugins']=json.loads(sys.stdin.read())['plugins']; \
+        print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)"
 }
 
-query_plugins() { query "$@" | awk '$0=="   \"plugins\" : [",$0=="   ],"' ; }
-
 test_tasks() { # name expected_file task_args...
     local name=$1 expected=$2 ; shift 2
-    local output=$STATUSES.$name
+    local output=$STATUSES.$name out root
 
     query_plugins "$@" > "$output"
-    out=$(diff "$expected" "$output")
-    result "$name" "$out"
+    echo "$ROOTS" | while read root ; do
+        result_root "$name" "$root" "$expected" "$output"
+    done
+    out=$(diff "$expected" "$output" | head -15)
+    [ -z "$out" ]
+    result "$name - Full Test Suite" "$out"
+}
+
+test_generated() { # name task_args...
+    local name=$1 ; shift
+    test_tasks "$name" "$EXPECTED.$name" "$@"
 }
 
 test_file() { # name task_args...
     local name=$1 ; shift
-    test_tasks "$name" "$MYDIR/$name" "$@"
+    local expected=$MYDIR/$name output=$STATUSES.$name
+
+    query "$@" | awk '$0=="   \"plugins\" : [",$0=="   ],"' > "$output"
+    out=$(diff "$expected" "$output")
+    result "$name" "$out"
 }
 
-MYDIR=$(dirname "$0")
-DOCS=$MYDIR/.././src/main/resources/Documentation
+readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
+MYDIR=$(dirname -- "$(readlink -f -- "$0")")
+DOCS=$MYDIR/.././src/main/resources/Documentation/test
 OUT=$MYDIR/../target/tests
 
 ALL=$OUT/All-Projects
@@ -128,7 +295,7 @@
 USERS=$OUT/All-Users
 USER_TASKS=$USERS/task
 
-DOC_STATES=$DOCS/task_states.md
+DOC_PREVIEW=$DOCS/preview.md
 EXPECTED=$OUT/expected
 STATUSES=$OUT/statuses
 
@@ -151,54 +318,72 @@
 REF_ALL=refs/meta/config
 REF_USERS=refs/users/self
 
-RESULT=0
+CONFIG=$ROOT_CFG
 
-mkdir -p "$OUT"
+mkdir -p "$OUT" "$ALL_TASKS" "$USER_TASKS"
+
 q_setup setup_repo "$ALL" "$REMOTE_ALL" "$REF_ALL"
 q_setup setup_repo "$USERS" "$REMOTE_USERS" "$REF_USERS" --initial-commit
 q_setup setup_repo "$OUT/$PROJECT" "$REMOTE_TEST" "$BRANCH"
 
-mkdir -p "$ALL_TASKS" "$USER_TASKS"
+changes=$(gssh query "status:open limit:2" --format json)
+set_change "$(echo "$changes" | awk 'NR==1')" ; CHANGE1=("${CHANGE[@]}")
+set_change "$(echo "$changes" | awk 'NR==2')" ; CHANGE2=("${CHANGE[@]}")
+DOC_STATES=$(replace_default_changes < "$DOCS/task_states.md")
 
-CHANGES=($(gssh query "status:open limit:2" | grep 'number:' | awk '{print $2}'))
-replace_change_properties "$DOC_STATES" "1" "${CHANGES[0]}"
-replace_change_properties "$DOC_STATES" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/all" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/all" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/preview" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/preview" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/preview.invalid" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/preview.invalid" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/invalid" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/invalid" "2" "${CHANGES[1]}"
-replace_change_properties "$MYDIR/invalid-applicable" "1" "${CHANGES[0]}"
-replace_change_properties "$MYDIR/invalid-applicable" "2" "${CHANGES[1]}"
+example 2 | replace_user | testdoc_2_cfg > "$ROOT_CFG"
+example 3 > "$COMMON_CFG"
+example 4 > "$INVALIDS_CFG"
+example 5 > "$USER_SPECIAL_CFG"
 
-example 1 |sed -e"s/current-user/$USER/" > "$ROOT_CFG"
-example 2 > "$COMMON_CFG"
-example 3 > "$INVALIDS_CFG"
-example 4 > "$USER_SPECIAL_CFG"
+ROOTS=$(config_section_keys "root") || err "Invalid ROOTS"
 
 q_setup update_repo "$ALL" "$REMOTE_ALL" "$REF_ALL"
 q_setup update_repo "$USERS" "$REMOTE_USERS" "$REF_USERS"
 
-example 5 |tail -n +5| awk 'NR>1{print P};{P=$0}' > "$EXPECTED"
-
 change3_id=$(gen_change_id)
 change3_number=$(create_repo_change "$OUT/$PROJECT" "$REMOTE_TEST" "$BRANCH" "$change3_id")
-replace_change_properties "$EXPECTED" "3" "$change3_number" "$change3_id" "$PROJECT" "refs\/heads\/$BRANCH" "NEW" ""
-replace_change_properties "$MYDIR/all" "3" "$change3_number" "$change3_id" "$PROJECT" "refs\/heads\/$BRANCH" "NEW" ""
 
-query="change:$change3_number status:open"
-test_tasks statuses "$EXPECTED" --task--applicable "$query"
-test_file all --task--all "$query"
+all_pjson=$(example 2 | testdoc_2_pjson | \
+    replace_change_properties \
+        "" \
+        "$change3_number" \
+        "$change3_id" \
+        "$PROJECT" \
+        "refs\/heads\/$BRANCH" \
+        "NEW" \
+        "")
 
-replace_user < "$MYDIR"/root.change > "$ROOT_CFG"
+no_all_json=$(echo "$all_pjson" | remove_suite all)
+
+echo "$no_all_json" | strip_non_applicable | \
+    grep -v "\"applicable\" :" > "$EXPECTED".applicable
+
+echo "$all_pjson" | remove_not_suite all | ensure json_pp > "$EXPECTED".all
+
+echo "$no_all_json" | strip_non_invalid > "$EXPECTED".invalid
+
+strip_non_invalid < "$EXPECTED".applicable > "$EXPECTED".invalid-applicable
+
+
+preview_pjson=$(testdoc_2_pjson < "$DOC_PREVIEW" | replace_default_changes)
+echo "$preview_pjson" | remove_suite invalid | ensure json_pp > "$EXPECTED".preview
+echo "$preview_pjson" | remove_not_suite invalid | strip_non_invalid > "$EXPECTED".preview-invalid
+
+testdoc_2_cfg < "$DOC_PREVIEW" | replace_user > "$ROOT_CFG"
 cnum=$(create_repo_change "$ALL" "$REMOTE_ALL" "$REF_ALL")
-test_file preview --task--preview "$cnum,1" --task--all "$query"
-test_file preview.invalid --task--preview "$cnum,1" --task--invalid "$query"
+PREVIEW_ROOTS=$(config_section_keys "root")
 
-test_file invalid --task--invalid "$query"
-test_file invalid-applicable --task--applicable --task--invalid "$query"
 
+RESULT=0
+query="change:$change3_number status:open"
+test_generated applicable --task--applicable "$query"
+test_generated all --task--all "$query"
+
+test_generated invalid --task--invalid "$query"
+test_generated invalid-applicable --task--applicable --task--invalid "$query"
+
+ROOTS=$PREVIEW_ROOTS
+test_generated preview --task--preview "$cnum,1" --task--all "$query"
+test_generated preview-invalid --task--preview "$cnum,1" --task--invalid "$query"
 exit $RESULT
diff --git a/test/docker/run.sh b/test/docker/run.sh
index 9c1f5d9..a57780b 100755
--- a/test/docker/run.sh
+++ b/test/docker/run.sh
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 
-readlink --canonicalize / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
+readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
 MYDIR=$(dirname -- "$(readlink -f -- "$0")")
 ARTIFACTS=$MYDIR/gerrit/artifacts
 
@@ -85,8 +85,7 @@
     usage "$MISSING, did you forget --task-plugin-jar?"
 fi
 [ -n "$GERRIT_WAR" ] && cp -f "$GERRIT_WAR" "$ARTIFACTS/gerrit.war"
-progress "Building docker images" build_images
-run_task_plugin_tests ; RESULT=$?
-cleanup
-
-exit "$RESULT"
+( trap cleanup EXIT SIGTERM
+    progress "Building docker images" build_images
+    run_task_plugin_tests
+)
diff --git a/test/docker/run_tests/wait-for-it.sh b/test/docker/run_tests/wait-for-it.sh
index d7b6e3c..17436f2 100755
--- a/test/docker/run_tests/wait-for-it.sh
+++ b/test/docker/run_tests/wait-for-it.sh
@@ -2,7 +2,7 @@
 # https://github.com/vishnubob/wait-for-it/blob/master/wait-for-it.sh
 #   Use this script to test if a given TCP host/port are available
 
-cmdname=$(basename $0)
+cmdname=$(basename -- "$0")
 
 echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi }
 
diff --git a/test/invalid b/test/invalid
deleted file mode 100644
index 5b5bc32..0000000
--- a/test/invalid
+++ /dev/null
@@ -1,559 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "Root N/A",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Root grouping NA (subtask NA)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : false,
-                     "hasPass" : false,
-                     "name" : "Subtask NA",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/invalid-applicable b/test/invalid-applicable
deleted file mode 100644
index 369ac47..0000000
--- a/test/invalid-applicable
+++ /dev/null
@@ -1,244 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "hasPass" : false,
-               "name" : "Subtasks External (User Missing)",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  }
-               ]
-            },
-            {
-               "name" : "UNKNOWN",
-               "status" : "INVALID"
-            },
-            {
-               "hasPass" : false,
-               "name" : "INVALIDS",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/preview b/test/preview
deleted file mode 100644
index 235eaca..0000000
--- a/test/preview
+++ /dev/null
@@ -1,570 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "name" : "Root PASS Preview",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : true,
-               "hasPass" : true,
-               "hint" : "You must now run the ready task",
-               "name" : "Root READY (subtask PASS) Preview",
-               "status" : "READY",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "Subtask PASS Preview",
-                     "status" : "PASS"
-                  }
-               ]
-            },
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "Subtasks External Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config PASS",
-                     "status" : "PASS"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "userfile task/special.config FAIL",
-                     "status" : "FAIL"
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : true,
-               "name" : "Root NA Pass Preview",
-               "status" : "PASS"
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "FAIL"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "duplicate",
-                           "status" : "FAIL"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/preview.invalid b/test/preview.invalid
deleted file mode 100644
index 3f0c844..0000000
--- a/test/preview.invalid
+++ /dev/null
@@ -1,511 +0,0 @@
-   "plugins" : [
-      {
-         "name" : "task",
-         "roots" : [
-            {
-               "applicable" : true,
-               "hasPass" : false,
-               "name" : "INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            },
-            {
-               "applicable" : false,
-               "hasPass" : false,
-               "name" : "NA INVALIDS Preview",
-               "status" : "WAITING",
-               "subTasks" : [
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "No PASS criteria",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "WAITING (subtask duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        },
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : true,
-                     "name" : "WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : false,
-                           "name" : "Subtask INVALID",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Grouping WAITING (subtask missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask INVALID",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Subtask Optional",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad PASS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad FAIL query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : false,
-                     "hasPass" : true,
-                     "name" : "NA Bad INPROGRESS query",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "Looping",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "name" : "UNKNOWN",
-                     "status" : "INVALID"
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory type INVALID)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory duplicate)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes type missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes missing)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (names-factory changes invalid)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "name" : "UNKNOWN",
-                           "status" : "INVALID"
-                        }
-                     ]
-                  },
-                  {
-                     "applicable" : true,
-                     "hasPass" : false,
-                     "name" : "task (tasks-factory changes loop)",
-                     "status" : "WAITING",
-                     "subTasks" : [
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change1_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        },
-                        {
-                           "applicable" : true,
-                           "hasPass" : true,
-                           "name" : "_change2_number",
-                           "status" : "FAIL",
-                           "subTasks" : [
-                              {
-                                 "name" : "UNKNOWN",
-                                 "status" : "INVALID"
-                              }
-                           ]
-                        }
-                     ]
-                  }
-               ]
-            }
-         ]
-      }
-   ],
diff --git a/test/root.change b/test/root.change
deleted file mode 100644
index 99dea09..0000000
--- a/test/root.change
+++ /dev/null
@@ -1,30 +0,0 @@
-[root "INVALIDS Preview"]
-  subtasks-file = invalids.config
-
-[root "Root PASS Preview"]
-  pass = True
-
-[root "Root READY (subtask PASS) Preview"]
-  applicable = is:open
-  pass = NOT is:open
-  subtask = Subtask PASS Preview
-  ready-hint = You must now run the ready task
-
-[root "Subtasks External Preview"]
-  subtasks-external = user special Preview
-
-[root "Root NA Pass Preview"]
-  applicable = NOT is:open
-  pass = True
-
-[root "NA INVALIDS Preview"]
-  applicable = NOT is:open
-  subtasks-file = invalids.config
-
-[task "Subtask PASS Preview"]
-  applicable = is:open
-  pass = is:open
-
-[external "user special Preview"]
-  user = testuser
-  file = special.config
diff --git a/test/strip_non_applicable.py b/test/strip_non_applicable.py
new file mode 100755
index 0000000..1ff097a
--- /dev/null
+++ b/test/strip_non_applicable.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import json
+
+APPLICABLE='applicable'
+HASPASS='hasPass'
+STATUS='status'
+SUBTASKS='subTasks'
+
+def del_non_applicable(tasks):
+    i=0
+    while i < len(tasks):
+        nexti = i + 1
+
+        task=tasks[i]
+        if APPLICABLE in task.keys() and task[APPLICABLE] == False:
+            del tasks[i]
+            nexti = i
+        else:
+            subtasks=[]
+            if SUBTASKS in task.keys():
+                subtasks=task[SUBTASKS]
+                del_non_applicable(subtasks)
+            if SUBTASKS in task.keys() and len(subtasks) == 0:
+                del task[SUBTASKS]
+            if not SUBTASKS in task.keys():
+                if HASPASS in task.keys() and task[HASPASS] == False:
+                    status=''
+                    if STATUS in task.keys():
+                        status = task[STATUS]
+                    if status != 'INVALID':
+                        del tasks[i]
+                        nexti = i
+
+        i = nexti
+
+plugins=json.loads(sys.stdin.read())
+roots=plugins['plugins'][0]['roots']
+del_non_applicable(roots)
+print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)
diff --git a/test/strip_non_invalid.py b/test/strip_non_invalid.py
new file mode 100755
index 0000000..dafae15
--- /dev/null
+++ b/test/strip_non_invalid.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import json
+
+STATUS='status'
+SUBTASKS='subTasks'
+
+def keep_invalid(tasks):
+    i=0
+    while i < len(tasks):
+        nexti = i + 1
+
+        task=tasks[i]
+        if SUBTASKS in task.keys():
+            subtasks=task[SUBTASKS]
+            keep_invalid(subtasks)
+            if len(subtasks) == 0:
+                del task[SUBTASKS]
+
+        status=''
+        if STATUS in task.keys():
+            status = task[STATUS]
+        if status != 'INVALID' and not SUBTASKS in task.keys():
+            del tasks[i]
+            nexti = i
+
+        i = nexti
+
+plugins=json.loads(sys.stdin.read())
+roots=plugins['plugins'][0]['roots']
+keep_invalid(roots)
+print json.dumps(plugins, indent=3, separators=(',', ' : '), sort_keys=True)