Index: /trunk/ippTasks/diff.pro
===================================================================
--- /trunk/ippTasks/diff.pro	(revision 25508)
+++ /trunk/ippTasks/diff.pro	(revision 25509)
@@ -14,4 +14,5 @@
 ### Database lists
 $diffSkycell_DB = 0
+$diffAdvance_DB = 0
 #$diffCleanup_DB = 0
 
@@ -36,4 +37,7 @@
     active true
   end
+  task diff.advance
+    active true
+  end
 end
 
@@ -44,4 +48,7 @@
   end
   task diff.skycell.run
+    active false
+  end
+  task diff.advance
     active false
   end
@@ -198,4 +205,56 @@
   end
 end
+
+
+# Advance exposures which have completed
+task	       diff.advance
+  host         local
+
+  periods      -poll $LOADPOLL
+#  periods      -exec $LOADEXEC
+  periods      -exec 30
+  periods      -timeout 60
+  npending     1
+
+  stdout NULL
+  stderr $LOGDIR/diff.advance.log
+
+  task.exec
+    if ($LABEL:n == 0) break
+    $run = difftool -advance -limit 10
+    if ($DB:n == 0)
+      option DEFAULT
+    else
+      # save the DB name for the exit tasks
+      option $DB:$diffAdvance_DB
+      $run = $run -dbname $DB:$diffAdvance_DB
+      $diffAdvance_DB ++
+      if ($diffAdvance_DB >= $DB:n) set diffAdvance_DB = 0
+    end
+    add_poll_args run
+    add_poll_labels run
+    command $run
+  end
+
+  # success
+  task.exit    0
+  end
+
+  # locked list
+  task.exit    default
+    showcommand failure
+  end
+
+  task.exit    crash
+    showcommand crash
+  end
+
+  # operation times out?
+  task.exit    timeout
+    showcommand timeout
+  end
+end
+
+
 
 # # select images ready for diff analysis
Index: /trunk/ippTools/src/difftool.c
===================================================================
--- /trunk/ippTools/src/difftool.c	(revision 25508)
+++ /trunk/ippTools/src/difftool.c	(revision 25509)
@@ -37,4 +37,5 @@
 static bool todiffskyfileMode(pxConfig *config);
 static bool adddiffskyfileMode(pxConfig *config);
+static bool advanceMode(pxConfig *config);
 static bool diffskyfileMode(pxConfig *config);
 static bool revertdiffskyfileMode(pxConfig *config);
@@ -50,5 +51,4 @@
 
 static bool setdiffRunState(pxConfig *config, psS64 diff_id, const char *state, psS64 magicked);
-static bool diffRunComplete(pxConfig *config);
 
 # define MODECASE(caseName, func) \
@@ -76,8 +76,9 @@
         MODECASE(DIFFTOOL_MODE_TODIFFSKYFILE,         todiffskyfileMode);
         MODECASE(DIFFTOOL_MODE_ADDDIFFSKYFILE,        adddiffskyfileMode);
+        MODECASE(DIFFTOOL_MODE_ADVANCE,               advanceMode);
         MODECASE(DIFFTOOL_MODE_DIFFSKYFILE,           diffskyfileMode);
         MODECASE(DIFFTOOL_MODE_REVERTDIFFSKYFILE,     revertdiffskyfileMode);
         MODECASE(DIFFTOOL_MODE_DEFINEPOPRUN,          definepoprunMode);
-        MODECASE(DIFFTOOL_MODE_DEFINEWARPSTACK,         definewarpstackMode);
+        MODECASE(DIFFTOOL_MODE_DEFINEWARPSTACK,       definewarpstackMode);
         MODECASE(DIFFTOOL_MODE_DEFINEWARPWARP,        definewarpwarpMode);
         MODECASE(DIFFTOOL_MODE_PENDINGCLEANUPRUN,     pendingcleanuprunMode);
@@ -555,12 +556,4 @@
     }
 
-    if (!diffRunComplete(config)) {
-        if (!psDBRollback(config->dbh)) {
-            psError(PS_ERR_UNKNOWN, false, "database error");
-        }
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-
     // point of no return
     if (!psDBCommit(config->dbh)) {
@@ -569,4 +562,91 @@
     }
 
+
+    return true;
+}
+
+static bool advanceMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_S64(config->args, where,  "-diff_id", "diffRun.diff_id", "==");
+    PXOPT_COPY_STR(config->args, where, "-label", "diffRun.label", "==");
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    // look for completed diffRuns
+    psString query = pxDataGet("difftool_completed_runs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!psDBTransaction(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        if (!psDBRollback(config->dbh)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+        }
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("difftool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    for (long i = 0; i < psArrayLength(output); i++) {
+        psMetadata *row = output->data[i];
+
+        psS64 diff_id = psMetadataLookupS64(NULL, row, "diff_id");
+        psS64 magicked = psMetadataLookupS64(NULL, row, "magicked");
+
+        // set diffRun.state to 'full'
+        if (!setdiffRunState(config, diff_id, "full", magicked)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to change diffRun.state for diff_id: %" PRId64,
+                diff_id);
+            psFree(output);
+            if (!psDBRollback(config->dbh)) {
+                psError(PS_ERR_UNKNOWN, false, "database error");
+            }
+            return false;
+        }
+    }
+    psFree(output);
+
+    if (!psDBCommit(config->dbh)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
 
     return true;
@@ -1810,49 +1890,4 @@
 }
 
-static bool diffRunComplete(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    // look for completed diffRuns
-    psString query = pxDataGet("difftool_completed_runs.sql");
-    if (!query) {
-        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
-        return false;
-    }
-
-    if (!p_psDBRunQuery(config->dbh, query)) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        psFree(query);
-        return false;
-    }
-    psFree(query);
-
-    psArray *output = p_psDBFetchResult(config->dbh);
-    if (!output) {
-        psError(PS_ERR_UNKNOWN, false, "database error");
-        return false;
-    }
-    if (!psArrayLength(output)) {
-        psTrace("difftool", PS_LOG_INFO, "no rows found");
-        psFree(output);
-        return true;
-    }
-    for (long i = 0; i < psArrayLength(output); i++) {
-        psMetadata *row = output->data[i];
-
-        psS64 diff_id = psMetadataLookupS64(NULL, row, "diff_id");
-        psS64 magicked = psMetadataLookupS64(NULL, row, "magicked");
-
-        // set diffRun.state to 'stop'
-        if (!setdiffRunState(config, diff_id, "full", magicked)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to change diffRun.state for diff_id: %" PRId64,
-                diff_id);
-            psFree(output);
-            return false;
-        }
-    }
-
-    return true;
-}
 
 bool exportrunMode(pxConfig *config)
Index: /trunk/ippTools/src/difftool.h
===================================================================
--- /trunk/ippTools/src/difftool.h	(revision 25508)
+++ /trunk/ippTools/src/difftool.h	(revision 25509)
@@ -31,4 +31,5 @@
     DIFFTOOL_MODE_TODIFFSKYFILE,
     DIFFTOOL_MODE_ADDDIFFSKYFILE,
+    DIFFTOOL_MODE_ADVANCE,
     DIFFTOOL_MODE_DIFFSKYFILE,
     DIFFTOOL_MODE_REVERTDIFFSKYFILE,
Index: /trunk/ippTools/src/difftoolConfig.c
===================================================================
--- /trunk/ippTools/src/difftoolConfig.c	(revision 25508)
+++ /trunk/ippTools/src/difftoolConfig.c	(revision 25509)
@@ -114,4 +114,9 @@
     psMetadataAddF32(adddiffskyfileArgs, PS_LIST_TAIL, "-good_frac",  0, "define %% of good pixels", NAN);
     psMetadataAddBool(adddiffskyfileArgs, PS_LIST_TAIL, "-magicked",  0, "define magicked state", false);
+
+    // -advance
+    psMetadata *advanceArgs = psMetadataAlloc();
+    psMetadataAddS64(advanceArgs, PS_LIST_TAIL, "-diff_id", 0, "select by diff ID", 0);
+    psMetadataAddStr(advanceArgs, PS_LIST_TAIL, "-label", 0, "select by label", NULL);
 
     // -diffskyfile
@@ -267,4 +272,5 @@
     PXOPT_ADD_MODE("-todiffskyfile",    "", DIFFTOOL_MODE_TODIFFSKYFILE,     todiffskyfileArgs);
     PXOPT_ADD_MODE("-adddiffskyfile",   "", DIFFTOOL_MODE_ADDDIFFSKYFILE,    adddiffskyfileArgs);
+    PXOPT_ADD_MODE("-advance",          "", DIFFTOOL_MODE_ADVANCE,           advanceArgs);
     PXOPT_ADD_MODE("-diffskyfile",      "", DIFFTOOL_MODE_DIFFSKYFILE,       diffskyfileArgs);
     PXOPT_ADD_MODE("-revertdiffskyfile","", DIFFTOOL_MODE_REVERTDIFFSKYFILE, revertdiffskyfileArgs);
