Skip to content

Commit 49f27a0

Browse files
authored
fix: check lane branch for .DONE after grace period expires (#274)
When a tmux session exits without the poll detecting .DONE on the filesystem, the engine now checks the lane git branch via 'git show <branch>:<path>/.DONE' before declaring failure. This handles the race condition where the worker completes all work, commits .DONE to the lane branch, and exits — but the worktree filesystem is stale or the poll timing barely misses the file. Previously this was the #1 cause of false task failures in production batches (seen in TP-065, TP-067, TP-072, TP-075, and user reports).
1 parent 4501105 commit 49f27a0

1 file changed

Lines changed: 30 additions & 2 deletions

File tree

extensions/taskplane/execution.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,9 +1069,37 @@ export async function pollUntilTaskComplete(
10691069
}
10701070
}
10711071

1072-
// Grace period expired without .DONE → task failed (TP-070: async)
1072+
// Grace period expired — last resort: check the lane BRANCH for .DONE.
1073+
// The worker may have committed .DONE before the session exited, but
1074+
// the worktree filesystem doesn't reflect it (stale checkout, race).
1075+
// This handles the common case where the worker completes all work,
1076+
// commits .DONE, and then the session exits before the poll detects it.
1077+
{
1078+
const relDonePath = donePath.startsWith(lane.worktreePath)
1079+
? donePath.slice(lane.worktreePath.length).replace(/^[\\/]+/, "").replace(/\\/g, "/")
1080+
: null;
1081+
if (relDonePath) {
1082+
const gitResult = runGit(
1083+
["show", `${lane.branch}:${relDonePath}`],
1084+
lane.worktreePath,
1085+
);
1086+
if (gitResult.ok) {
1087+
execLog(laneId, task.taskId, ".DONE found on lane branch (not in worktree) — task succeeded", {
1088+
session: sessionName,
1089+
branch: lane.branch,
1090+
});
1091+
return {
1092+
status: "succeeded",
1093+
exitReason: ".DONE committed to lane branch (found via git show after grace period)",
1094+
doneFileFound: true,
1095+
};
1096+
}
1097+
}
1098+
}
1099+
1100+
// Truly failed — no .DONE on filesystem or branch
10731101
const logTail = await readLaneLogTailAsync(laneLogPath);
1074-
execLog(laneId, task.taskId, "grace period expired without .DONE — task failed", {
1102+
execLog(laneId, task.taskId, "grace period expired, no .DONE on filesystem or branch — task failed", {
10751103
session: sessionName,
10761104
logPath: laneLogPath,
10771105
});

0 commit comments

Comments
 (0)