taskplane 0.24.23 → 0.24.25
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.
|
@@ -2908,6 +2908,45 @@ export async function executeOrchBatch(
|
|
|
2908
2908
|
return hasSucceeded && hasHardFailure;
|
|
2909
2909
|
});
|
|
2910
2910
|
|
|
2911
|
+
// ── Safety net: auto-commit uncommitted artifacts before merge ──
|
|
2912
|
+
// Workers should commit at step boundaries, but may leave uncommitted
|
|
2913
|
+
// files (especially for level-0 / fast tasks). Check each merge-candidate
|
|
2914
|
+
// lane worktree and auto-commit any remaining changes so they're included
|
|
2915
|
+
// in the merge. Skips lanes with only failed/stalled tasks (no merge).
|
|
2916
|
+
for (const lane of waveResult.allocatedLanes) {
|
|
2917
|
+
if (!lane.worktreePath || !existsSync(lane.worktreePath)) continue;
|
|
2918
|
+
// Only check lanes that have at least one succeeded task (merge candidates)
|
|
2919
|
+
const laneOutcome = laneOutcomeByNumber.get(lane.laneNumber);
|
|
2920
|
+
if (!laneOutcome) continue;
|
|
2921
|
+
const hasSucceeded = laneOutcome.tasks.some(t => t.status === "succeeded");
|
|
2922
|
+
if (!hasSucceeded) continue;
|
|
2923
|
+
try {
|
|
2924
|
+
const addResult = runGit(["add", "-A"], lane.worktreePath);
|
|
2925
|
+
if (!addResult.ok) {
|
|
2926
|
+
execLog("merge", batchState.batchId, `safety-net: git add failed in ${lane.laneId}`, { stderr: addResult.stderr });
|
|
2927
|
+
continue;
|
|
2928
|
+
}
|
|
2929
|
+
const statusResult = runGit(["status", "--porcelain"], lane.worktreePath);
|
|
2930
|
+
if (!statusResult.ok || !statusResult.stdout?.trim()) continue;
|
|
2931
|
+
const taskIds = lane.tasks.map(t => t.taskId).join(", ");
|
|
2932
|
+
const commitResult = runGit(
|
|
2933
|
+
["commit", "-m", `safety-net: uncommitted artifacts for ${taskIds}`],
|
|
2934
|
+
lane.worktreePath,
|
|
2935
|
+
);
|
|
2936
|
+
if (commitResult.ok) {
|
|
2937
|
+
execLog("merge", batchState.batchId, `safety-net: auto-committed uncommitted files in ${lane.laneId}`, {
|
|
2938
|
+
worktree: lane.worktreePath,
|
|
2939
|
+
taskIds,
|
|
2940
|
+
files: statusResult.stdout.trim(),
|
|
2941
|
+
});
|
|
2942
|
+
} else {
|
|
2943
|
+
execLog("merge", batchState.batchId, `safety-net: commit failed in ${lane.laneId}`, { stderr: commitResult.stderr });
|
|
2944
|
+
}
|
|
2945
|
+
} catch (err: any) {
|
|
2946
|
+
execLog("merge", batchState.batchId, `safety-net: unexpected error in ${lane.laneId}`, { error: err?.message });
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
|
|
2911
2950
|
if (succeededSegmentTaskIdsForMerge.length > 0) {
|
|
2912
2951
|
const mergeableLaneCount = waveResult.allocatedLanes.filter(lane => {
|
|
2913
2952
|
const outcome = laneOutcomeByNumber.get(lane.laneNumber);
|
|
@@ -611,18 +611,9 @@ export async function spawnMergeAgentV2(
|
|
|
611
611
|
packet: null,
|
|
612
612
|
env: {
|
|
613
613
|
ORCH_BATCH_ID: bid,
|
|
614
|
-
// Isolate merge agent from operator's global preferences to prevent
|
|
615
|
-
// verification test contamination (e.g., stale reviewerModel pref
|
|
616
|
-
// overriding schema defaults in deep-equal assertions).
|
|
617
|
-
PI_CODING_AGENT_DIR: join(sidecarRoot, "runtime", bid, "merge-agent-env"),
|
|
618
614
|
},
|
|
619
615
|
};
|
|
620
616
|
|
|
621
|
-
// Ensure isolated agent dir exists with empty preferences
|
|
622
|
-
const isolatedAgentDir = join(sidecarRoot, "runtime", bid, "merge-agent-env", "taskplane");
|
|
623
|
-
mkdirSync(isolatedAgentDir, { recursive: true });
|
|
624
|
-
try { writeFileSync(join(isolatedAgentDir, "preferences.json"), "{}\n", { flag: "wx" }); } catch { /* already exists */ }
|
|
625
|
-
|
|
626
617
|
const { promise, kill } = spawnAgent(opts);
|
|
627
618
|
|
|
628
619
|
// Store the kill handle for external cleanup (pause/abort).
|