taskplane 0.2.1 → 0.2.3

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.
@@ -34,6 +34,7 @@ import { deleteBranchBestEffort, forceCleanupWorktree, formatPreflightResults, l
34
34
  * @param onNotify - Callback for user-facing messages
35
35
  * @param onMonitorUpdate - Optional callback for dashboard updates
36
36
  * @param workspaceConfig - Workspace configuration for repo routing (null = repo mode)
37
+ * @param workspaceRoot - Workspace root for resolving task area paths (defaults to cwd)
37
38
  */
38
39
  export async function executeOrchBatch(
39
40
  args: string,
@@ -44,6 +45,7 @@ export async function executeOrchBatch(
44
45
  onNotify: (message: string, level: "info" | "warning" | "error") => void,
45
46
  onMonitorUpdate?: MonitorUpdateCallback,
46
47
  workspaceConfig?: WorkspaceConfig | null,
48
+ workspaceRoot?: string,
47
49
  ): Promise<void> {
48
50
  const repoRoot = cwd;
49
51
 
@@ -94,8 +96,10 @@ export async function executeOrchBatch(
94
96
  return;
95
97
  }
96
98
 
97
- // Discovery
98
- const discovery = runDiscovery(args, runnerConfig.task_areas, cwd, {
99
+ // Discovery — task area paths in task-runner.yaml are workspace-relative.
100
+ // In repo mode workspaceRoot === repoRoot, so this is always correct.
101
+ const discoveryRoot = workspaceRoot ?? cwd;
102
+ const discovery = runDiscovery(args, runnerConfig.task_areas, discoveryRoot, {
99
103
  refreshDependencies: false,
100
104
  dependencySource: orchConfig.dependencies.source,
101
105
  useDependencyCache: orchConfig.dependencies.cache,
@@ -106,6 +106,7 @@ export function buildLaneEnvVars(
106
106
  lane: AllocatedLane,
107
107
  promptPath: string,
108
108
  repoRoot: string,
109
+ workspaceRoot?: string,
109
110
  ): Record<string, string> {
110
111
  // TASK_AUTOSTART needs a path relative to the worktree root.
111
112
  // The promptPath is absolute (from the main repo). We need the
@@ -129,7 +130,7 @@ export function buildLaneEnvVars(
129
130
  }
130
131
  const nodePath = [...new Set(nodePathEntries)].join(pathDelimiter);
131
132
 
132
- return {
133
+ const vars: Record<string, string> = {
133
134
  TASK_AUTOSTART: relativePath,
134
135
  TASK_RUNNER_SPAWN_MODE: "subprocess",
135
136
  TASK_RUNNER_TMUX_PREFIX: lane.tmuxSessionName,
@@ -139,6 +140,15 @@ export function buildLaneEnvVars(
139
140
  // Force xterm-256color so pi can render and start execution.
140
141
  TERM: "xterm-256color",
141
142
  };
143
+
144
+ // In workspace mode, the worktree cwd is inside a repo — not the workspace root.
145
+ // The task-runner needs TASKPLANE_WORKSPACE_ROOT to find .pi/task-runner.yaml
146
+ // and resolve task area paths from the correct base directory.
147
+ if (workspaceRoot && workspaceRoot !== repoRoot) {
148
+ vars.TASKPLANE_WORKSPACE_ROOT = workspaceRoot;
149
+ }
150
+
151
+ return vars;
142
152
  }
143
153
 
144
154
  /**
@@ -438,6 +448,7 @@ export function spawnLaneSession(
438
448
  task: AllocatedTask,
439
449
  config: OrchestratorConfig,
440
450
  repoRoot: string,
451
+ workspaceRoot?: string,
441
452
  ): void {
442
453
  const sessionName = lane.tmuxSessionName;
443
454
  const laneId = lane.laneId;
@@ -460,7 +471,7 @@ export function spawnLaneSession(
460
471
  }
461
472
 
462
473
  // Build env vars
463
- const envVars = buildLaneEnvVars(lane, task.task.promptPath, repoRoot);
474
+ const envVars = buildLaneEnvVars(lane, task.task.promptPath, repoRoot, workspaceRoot);
464
475
 
465
476
  // Prepare per-task lane log path for post-mortem diagnostics
466
477
  const laneLogPath = resolveLaneLogPath(lane, task);
@@ -761,6 +772,7 @@ export async function executeLane(
761
772
  config: OrchestratorConfig,
762
773
  repoRoot: string,
763
774
  pauseSignal: { paused: boolean },
775
+ workspaceRoot?: string,
764
776
  ): Promise<LaneExecutionResult> {
765
777
  const laneId = lane.laneId;
766
778
  const laneStartTime = Date.now();
@@ -797,7 +809,7 @@ export async function executeLane(
797
809
 
798
810
  try {
799
811
  // Spawn TMUX session
800
- spawnLaneSession(lane, task, config, repoRoot);
812
+ spawnLaneSession(lane, task, config, repoRoot, workspaceRoot);
801
813
 
802
814
  // Poll until completion
803
815
  const pollResult = await pollUntilTaskComplete(
@@ -1745,8 +1757,11 @@ export async function executeWave(
1745
1757
  const wavePauseSignal = pauseSignal;
1746
1758
 
1747
1759
  // Start lane execution promises
1760
+ // In workspace mode, pass the workspace root so lane sessions can find .pi/ config.
1761
+ // configPath is .pi/taskplane-workspace.yaml → parent of parent is workspace root.
1762
+ const wsRoot = workspaceConfig ? dirname(dirname(workspaceConfig.configPath)) : undefined;
1748
1763
  const lanePromises = lanes.map(lane =>
1749
- executeLane(lane, config, repoRoot, wavePauseSignal),
1764
+ executeLane(lane, config, repoRoot, wavePauseSignal, wsRoot),
1750
1765
  );
1751
1766
 
1752
1767
  // Start monitoring as a sibling async loop
@@ -207,6 +207,7 @@ export default function (pi: ExtensionAPI) {
207
207
  if (changed) updateOrchWidget(); // Only refresh on actual state change
208
208
  },
209
209
  execCtx!.workspaceConfig,
210
+ execCtx!.workspaceRoot,
210
211
  );
211
212
 
212
213
  // Final widget update after batch completes
@@ -257,9 +258,9 @@ export default function (pi: ExtensionAPI) {
257
258
  if (!preflight.passed) return;
258
259
 
259
260
  // ── Section 2: Discovery ─────────────────────────────────
260
- // Discovery uses repoRoot for consistency with engine.ts and resume.ts
261
- // which both call runDiscovery with their cwd (= repoRoot).
262
- const discovery = runDiscovery(cleanArgs, runnerConfig.task_areas, execCtx!.repoRoot, {
261
+ // Discovery resolves task area paths relative to workspaceRoot (not repoRoot),
262
+ // because task_areas in task-runner.yaml are workspace-relative paths.
263
+ const discovery = runDiscovery(cleanArgs, runnerConfig.task_areas, execCtx!.workspaceRoot, {
263
264
  refreshDependencies: hasRefresh,
264
265
  dependencySource: orchConfig.dependencies.source,
265
266
  useDependencyCache: orchConfig.dependencies.cache,
@@ -608,8 +609,8 @@ export default function (pi: ExtensionAPI) {
608
609
  }
609
610
 
610
611
  // Run discovery (no preflight needed for deps view).
611
- // Uses repoRoot for consistency with engine.ts and resume.ts.
612
- const discovery = runDiscovery(cleanArgs, runnerConfig.task_areas, execCtx!.repoRoot, {
612
+ // Task area paths are workspace-relative, so use workspaceRoot.
613
+ const discovery = runDiscovery(cleanArgs, runnerConfig.task_areas, execCtx!.workspaceRoot, {
613
614
  refreshDependencies: hasRefresh,
614
615
  dependencySource: orchConfig.dependencies.source,
615
616
  useDependencyCache: orchConfig.dependencies.cache,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskplane",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
5
5
  "keywords": [
6
6
  "pi-package",