taskplane 0.5.3 → 0.5.4
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.
|
@@ -413,21 +413,26 @@ export function resolveCanonicalTaskPaths(
|
|
|
413
413
|
taskFolder: string,
|
|
414
414
|
worktreePath: string,
|
|
415
415
|
repoRoot: string,
|
|
416
|
+
isWorkspaceMode?: boolean,
|
|
416
417
|
): ResolvedTaskPaths {
|
|
417
418
|
const repoRootNorm = resolve(repoRoot).replace(/\\/g, "/");
|
|
418
419
|
const folderNorm = resolve(taskFolder).replace(/\\/g, "/");
|
|
419
420
|
|
|
420
421
|
let resolvedFolder: string;
|
|
421
422
|
|
|
422
|
-
if (
|
|
423
|
-
//
|
|
423
|
+
if (isWorkspaceMode) {
|
|
424
|
+
// Workspace mode: task folder may live in a different repo than
|
|
425
|
+
// the lane's worktree. Always use the absolute canonical path —
|
|
426
|
+
// .DONE and STATUS.md are written by workers to the original
|
|
427
|
+
// task folder (via absolute TASK_AUTOSTART path), not to the worktree.
|
|
428
|
+
resolvedFolder = resolve(taskFolder);
|
|
429
|
+
} else if (folderNorm.startsWith(repoRootNorm + "/")) {
|
|
430
|
+
// Repo mode: task folder is inside the repo root.
|
|
424
431
|
// Translate to equivalent path in the worktree.
|
|
425
432
|
const relativePath = folderNorm.slice(repoRootNorm.length + 1);
|
|
426
433
|
resolvedFolder = join(worktreePath, relativePath);
|
|
427
434
|
} else {
|
|
428
|
-
//
|
|
429
|
-
// Use the absolute path directly — task state lives in the
|
|
430
|
-
// canonical task folder, not mirrored in any worktree.
|
|
435
|
+
// Fallback: use absolute path directly.
|
|
431
436
|
resolvedFolder = resolve(taskFolder);
|
|
432
437
|
}
|
|
433
438
|
|
|
@@ -484,8 +489,9 @@ export function resolveTaskDonePath(
|
|
|
484
489
|
taskFolder: string,
|
|
485
490
|
worktreePath: string,
|
|
486
491
|
repoRoot: string,
|
|
492
|
+
isWorkspaceMode?: boolean,
|
|
487
493
|
): string {
|
|
488
|
-
return resolveCanonicalTaskPaths(taskFolder, worktreePath, repoRoot).donePath;
|
|
494
|
+
return resolveCanonicalTaskPaths(taskFolder, worktreePath, repoRoot, isWorkspaceMode).donePath;
|
|
489
495
|
}
|
|
490
496
|
|
|
491
497
|
/**
|
|
@@ -613,10 +619,11 @@ export async function pollUntilTaskComplete(
|
|
|
613
619
|
config: OrchestratorConfig,
|
|
614
620
|
repoRoot: string,
|
|
615
621
|
pauseSignal: { paused: boolean },
|
|
622
|
+
isWorkspaceMode?: boolean,
|
|
616
623
|
): Promise<{ status: LaneTaskStatus; exitReason: string; doneFileFound: boolean }> {
|
|
617
624
|
const sessionName = lane.tmuxSessionName;
|
|
618
625
|
const laneId = lane.laneId;
|
|
619
|
-
const resolved = resolveCanonicalTaskPaths(task.task.taskFolder, lane.worktreePath, repoRoot);
|
|
626
|
+
const resolved = resolveCanonicalTaskPaths(task.task.taskFolder, lane.worktreePath, repoRoot, isWorkspaceMode);
|
|
620
627
|
const donePath = resolved.donePath;
|
|
621
628
|
const statusPath = resolved.statusPath;
|
|
622
629
|
const laneLogPath = resolveLaneLogPath(lane, task);
|
|
@@ -832,6 +839,7 @@ export async function executeLane(
|
|
|
832
839
|
repoRoot: string,
|
|
833
840
|
pauseSignal: { paused: boolean },
|
|
834
841
|
workspaceRoot?: string,
|
|
842
|
+
isWorkspaceMode?: boolean,
|
|
835
843
|
): Promise<LaneExecutionResult> {
|
|
836
844
|
const laneId = lane.laneId;
|
|
837
845
|
const laneStartTime = Date.now();
|
|
@@ -877,6 +885,7 @@ export async function executeLane(
|
|
|
877
885
|
config,
|
|
878
886
|
repoRoot,
|
|
879
887
|
pauseSignal,
|
|
888
|
+
isWorkspaceMode,
|
|
880
889
|
);
|
|
881
890
|
|
|
882
891
|
taskOutcome = {
|
|
@@ -1003,9 +1012,10 @@ export function parseWorktreeStatusMd(
|
|
|
1003
1012
|
taskFolder: string,
|
|
1004
1013
|
worktreePath: string,
|
|
1005
1014
|
repoRoot: string,
|
|
1015
|
+
isWorkspaceMode?: boolean,
|
|
1006
1016
|
): { parsed: ParsedWorktreeStatus | null; error: string | null } {
|
|
1007
1017
|
// Use canonical resolver for consistent path translation
|
|
1008
|
-
const resolved = resolveCanonicalTaskPaths(taskFolder, worktreePath, repoRoot);
|
|
1018
|
+
const resolved = resolveCanonicalTaskPaths(taskFolder, worktreePath, repoRoot, isWorkspaceMode);
|
|
1009
1019
|
const statusPath = resolved.statusPath;
|
|
1010
1020
|
|
|
1011
1021
|
if (!existsSync(statusPath)) {
|
|
@@ -1323,6 +1333,7 @@ export async function monitorLanes(
|
|
|
1323
1333
|
pauseSignal: { paused: boolean },
|
|
1324
1334
|
waveNumber: number = 1,
|
|
1325
1335
|
onUpdate?: MonitorUpdateCallback,
|
|
1336
|
+
isWorkspaceMode?: boolean,
|
|
1326
1337
|
): Promise<MonitorState> {
|
|
1327
1338
|
const pollIntervalMs = (config.monitoring.poll_interval || 5) * 1000;
|
|
1328
1339
|
const stallTimeoutMs = (config.failure.stall_timeout || 30) * 60_000;
|
|
@@ -1412,8 +1423,8 @@ export async function monitorLanes(
|
|
|
1412
1423
|
currentTaskId = task.taskId;
|
|
1413
1424
|
|
|
1414
1425
|
const tracker = getOrCreateTracker(task.taskId, now);
|
|
1415
|
-
const donePath = resolveTaskDonePath(task.task.taskFolder, lane.worktreePath, repoRoot);
|
|
1416
|
-
const statusResult = parseWorktreeStatusMd(task.task.taskFolder, lane.worktreePath, repoRoot);
|
|
1426
|
+
const donePath = resolveTaskDonePath(task.task.taskFolder, lane.worktreePath, repoRoot, isWorkspaceMode);
|
|
1427
|
+
const statusResult = parseWorktreeStatusMd(task.task.taskFolder, lane.worktreePath, repoRoot, isWorkspaceMode);
|
|
1417
1428
|
|
|
1418
1429
|
const snapshot = resolveTaskMonitorState(
|
|
1419
1430
|
task.taskId,
|
|
@@ -1819,8 +1830,9 @@ export async function executeWave(
|
|
|
1819
1830
|
// In workspace mode, pass the workspace root so lane sessions can find .pi/ config.
|
|
1820
1831
|
// configPath is .pi/taskplane-workspace.yaml → parent of parent is workspace root.
|
|
1821
1832
|
const wsRoot = workspaceConfig ? dirname(dirname(workspaceConfig.configPath)) : undefined;
|
|
1833
|
+
const isWsMode = !!workspaceConfig;
|
|
1822
1834
|
const lanePromises = lanes.map(lane =>
|
|
1823
|
-
executeLane(lane, config, repoRoot, wavePauseSignal, wsRoot),
|
|
1835
|
+
executeLane(lane, config, repoRoot, wavePauseSignal, wsRoot, isWsMode),
|
|
1824
1836
|
);
|
|
1825
1837
|
|
|
1826
1838
|
// Start monitoring as a sibling async loop
|
|
@@ -1832,6 +1844,7 @@ export async function executeWave(
|
|
|
1832
1844
|
wavePauseSignal,
|
|
1833
1845
|
waveIndex,
|
|
1834
1846
|
onMonitorUpdate,
|
|
1847
|
+
isWsMode,
|
|
1835
1848
|
);
|
|
1836
1849
|
|
|
1837
1850
|
// ── Stage 4: Wait for all lanes + apply policy ───────────────
|