taskplane 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -674,14 +674,72 @@ export async function pollUntilTaskComplete(
674
674
  }
675
675
  }
676
676
 
677
+
678
+ // ── Post-Task Commit ─────────────────────────────────────────────────
679
+
680
+ /**
681
+ * Commit any uncommitted task artifacts to the lane branch after task completion.
682
+ *
683
+ * The task-runner creates `.DONE` and updates `STATUS.md` via `writeFileSync`,
684
+ * but these changes are never committed to git by the task-runner or the worker.
685
+ * Without this commit, these files are lost when the worktree is reset or removed,
686
+ * and they don't appear in the merge to the base branch.
687
+ *
688
+ * Best-effort: failures are logged but don't fail the task (the work is already done).
689
+ *
690
+ * @param lane - Allocated lane containing the worktree path
691
+ * @param task - The task that just completed
692
+ * @param laneId - Lane identifier for logging
693
+ */
694
+ function commitTaskArtifacts(
695
+ lane: AllocatedLane,
696
+ task: AllocatedTask,
697
+ laneId: string,
698
+ ): void {
699
+ const worktreePath = lane.worktreePath;
700
+
701
+ // Check if there are any uncommitted changes in the worktree
702
+ const statusResult = runGit(["status", "--porcelain"], worktreePath);
703
+ if (!statusResult.ok || !statusResult.stdout.trim()) {
704
+ // Nothing to commit (worker already committed everything, or git error)
705
+ return;
706
+ }
707
+
708
+ // Stage all changes in the worktree
709
+ const addResult = runGit(["add", "-A"], worktreePath);
710
+ if (!addResult.ok) {
711
+ execLog(laneId, task.taskId, `post-task stage failed (non-fatal): ${addResult.stderr.slice(0, 200)}`);
712
+ return;
713
+ }
714
+
715
+ // Commit with task ID for traceability
716
+ const commitResult = runGit(
717
+ ["commit", "-m", `checkpoint: ${task.taskId} task artifacts (.DONE, STATUS.md)`],
718
+ worktreePath,
719
+ );
720
+ if (!commitResult.ok) {
721
+ // "nothing to commit" is not an error — worker may have already committed
722
+ if (!commitResult.stderr.includes("nothing to commit")) {
723
+ execLog(laneId, task.taskId, `post-task commit failed (non-fatal): ${commitResult.stderr.slice(0, 200)}`);
724
+ }
725
+ return;
726
+ }
727
+
728
+ execLog(laneId, task.taskId, `committed task artifacts to lane branch`, {
729
+ commit: commitResult.stdout.trim().split("\n")[0],
730
+ });
731
+ }
732
+
733
+
677
734
  /**
678
735
  * Execute all tasks in a lane sequentially.
679
736
  *
680
737
  * For each task in the lane (in order):
681
738
  * 1. Spawn a TMUX session with TASK_AUTOSTART pointing to the task's PROMPT.md
682
739
  * 2. Poll until the task completes (or fails)
683
- * 3. Record the outcome
684
- * 4. If the task failed, skip remaining tasks in the lane
740
+ * 3. Commit any uncommitted task artifacts (.DONE, STATUS.md) to the lane branch
741
+ * 4. Record the outcome
742
+ * 5. If the task failed, skip remaining tasks in the lane
685
743
  *
686
744
  * The lane reuses the same worktree and TMUX session name across tasks.
687
745
  * Each new task gets a fresh TMUX session (the previous one has exited).
@@ -760,6 +818,13 @@ export async function executeLane(
760
818
  doneFileFound: pollResult.doneFileFound,
761
819
  };
762
820
 
821
+ // After task succeeds, commit any uncommitted artifacts (.DONE, final
822
+ // STATUS.md update) to the lane branch so they survive the merge.
823
+ // The task-runner writes .DONE via writeFileSync but never commits it.
824
+ if (pollResult.status === "succeeded") {
825
+ commitTaskArtifacts(lane, task, laneId);
826
+ }
827
+
763
828
  // If task failed or was paused, skip remaining tasks
764
829
  if (pollResult.status === "failed" || pollResult.status === "stalled") {
765
830
  shouldSkipRemaining = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskplane",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
5
5
  "keywords": [
6
6
  "pi-package",