taskplane 0.23.7 → 0.23.9

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.
@@ -17,5 +17,5 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
17
17
  // TP-115: Disable jiti filesystem cache to prevent stale compiled code
18
18
  // after npm update. Without this, jiti serves old cached .mjs even when
19
19
  // the .ts source files have been updated by a new package version.
20
- const jiti = createJiti(import.meta.url, { fsCache: false });
20
+ const jiti = createJiti(import.meta.url, { cache: false });
21
21
  await jiti.import(join(__dirname, "engine-worker.ts"));
@@ -2320,7 +2320,11 @@ export async function executeOrchBatch(
2320
2320
  const durationMs = (to.startTime && to.endTime) ? (to.endTime - to.startTime) : 0;
2321
2321
 
2322
2322
  // Get tokens for this lane (cumulative — shared across tasks in same lane)
2323
- const tokens = laneTokens.get(to.sessionName) || { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, costUsd: 0 };
2323
+ // TP-115: V2 sessionName includes role suffix (-worker/-reviewer) but
2324
+ // laneTokens is keyed by tmuxSessionName (no suffix). Try both.
2325
+ const tokens = laneTokens.get(to.sessionName)
2326
+ || laneTokens.get(to.sessionName?.replace(/-(?:worker|reviewer)$/, ""))
2327
+ || { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, costUsd: 0 };
2324
2328
 
2325
2329
  return {
2326
2330
  taskId: to.taskId,
@@ -1,5 +1,3 @@
1
- // DEBUG: module load marker
2
- try { require('fs').writeFileSync('/c/dev/taskplane/.pi/tp-lane-runner-loaded.txt', 'loaded at ' + new Date().toISOString() + ' from ' + __filename); } catch(e) { try { require('fs').writeFileSync('/c/dev/taskplane/.pi/tp-lane-runner-loaded.txt', 'loaded at ' + new Date().toISOString() + ' err: ' + e); } catch {} }
3
1
  /**
4
2
  * Lane Runner — Headless per-lane execution for Runtime V2
5
3
  *
@@ -282,8 +280,6 @@ export async function executeTaskV2(
282
280
  // Context pressure: write wrap-up signal before kill
283
281
  let workerKillReason: "context" | "timer" | null = null;
284
282
 
285
- // DEBUG: verify this code path executes
286
- try { writeFileSync(config.stateRoot + '/.pi/tp-debug-pre-spawn.json', JSON.stringify({ ts: Date.now(), iter: totalIterations, taskId })); } catch { /* */ }
287
283
  const spawned = spawnAgent(hostOpts, undefined, (telemetry) => {
288
284
  // Context pressure check
289
285
  if (telemetry.contextUsage) {
@@ -307,8 +303,6 @@ export async function executeTaskV2(
307
303
 
308
304
  // TP-115: Update lastTelemetry with definitive final values from AgentHostResult
309
305
  lastTelemetry = workerResult;
310
- // DEBUG
311
- try { writeFileSync(config.stateRoot + '/.pi/tp-debug-workerResult.json', JSON.stringify({ iter: totalIterations, cost: workerResult.costUsd, tools: workerResult.toolCalls, input: workerResult.inputTokens, keys: Object.keys(workerResult) }, null, 2)); } catch { /* */ }
312
306
 
313
307
  // Clean up wrap-up signal
314
308
  if (existsSync(wrapUpFile)) try { unlinkSync(wrapUpFile); } catch { /* ignore */ }
@@ -12,6 +12,7 @@ import { resolveOperatorId } from "./naming.ts";
12
12
  import { MERGE_POLL_INTERVAL_MS, MERGE_RESULT_GRACE_MS, MERGE_RESULT_READ_RETRIES, MERGE_RESULT_READ_RETRY_DELAY_MS, MERGE_SPAWN_RETRY_MAX, MERGE_TIMEOUT_MAX_RETRIES, MERGE_TIMEOUT_MS, MERGE_HEALTH_POLL_INTERVAL_MS, MERGE_HEALTH_WARNING_THRESHOLD_MS, MERGE_HEALTH_STUCK_THRESHOLD_MS, MERGE_HEALTH_CAPTURE_LINES, MergeError, VALID_MERGE_STATUSES, buildEngineEventBase } from "./types.ts";
13
13
  import type { AllocatedLane, LaneExecutionResult, MergeLaneResult, MergeResult, MergeResultStatus, MergeWaveResult, OrchestratorConfig, RepoMergeOutcome, TaskRunnerConfig, TransactionRecord, TransactionStatus, VerificationBaselineResult, WaveExecutionResult, WorkspaceConfig, MergeHealthStatus, MergeHealthEventType, MergeSessionSnapshot, MergeSessionHealthState, EngineEvent, OrchBatchPhase } from "./types.ts";
14
14
  import { resolveBaseBranch, resolveRepoRoot } from "./waves.ts";
15
+ import { readManifest, writeManifest, buildRegistrySnapshot, writeRegistrySnapshot } from "./process-registry.ts";
15
16
  import { generateMergeWorktreePath, sleepAsync, sleepSync } from "./worktree.ts";
16
17
  import { getCurrentBranch, runGit } from "./git.ts";
17
18
  import { ORCH_MESSAGES } from "./messages.ts";
@@ -798,7 +799,7 @@ export async function spawnMergeAgentV2(
798
799
  // Store the kill handle for external cleanup (pause/abort).
799
800
  // The promise runs in background — caller uses waitForMergeResult()
800
801
  // to poll for the result file, same contract as the TMUX path.
801
- activeMergeAgents.set(sessionName, { promise, kill });
802
+ activeMergeAgents.set(sessionName, { promise, kill, stateRoot: stateRoot ?? repoRoot, batchId: bid });
802
803
 
803
804
  // Fire-and-forget: the background promise handles exit logging
804
805
  promise.then(result => {
@@ -816,17 +817,30 @@ export async function spawnMergeAgentV2(
816
817
  }
817
818
 
818
819
  /** Active V2 merge agent handles for cleanup/abort. @since TP-108 */
819
- const activeMergeAgents = new Map<string, { promise: Promise<AgentHostResult>; kill: () => void }>();
820
+ const activeMergeAgents = new Map<string, { promise: Promise<AgentHostResult>; kill: () => void; stateRoot?: string; batchId?: string }>();
820
821
 
821
822
  /**
822
823
  * Kill a V2 merge agent if it's still running.
823
824
  * Used by pause/abort/cleanup flows.
824
825
  * @since TP-108
825
826
  */
826
- export function killMergeAgentV2(sessionName: string): boolean {
827
+ export function killMergeAgentV2(sessionName: string, cleanExit?: boolean): boolean {
827
828
  const handle = activeMergeAgents.get(sessionName);
828
829
  if (handle) {
829
830
  handle.kill();
831
+ // TP-115: On clean post-result cleanup, update manifest to "exited"
832
+ // so dashboard shows correct status instead of "killed".
833
+ if (cleanExit && handle.stateRoot && handle.batchId) {
834
+ try {
835
+ const manifest = readManifest(handle.stateRoot, handle.batchId, sessionName as any);
836
+ if (manifest) {
837
+ manifest.status = "exited";
838
+ writeManifest(handle.stateRoot, manifest);
839
+ const snapshot = buildRegistrySnapshot(handle.stateRoot, handle.batchId);
840
+ writeRegistrySnapshot(handle.stateRoot, snapshot);
841
+ }
842
+ } catch { /* best effort */ }
843
+ }
830
844
  activeMergeAgents.delete(sessionName);
831
845
  return true;
832
846
  }
@@ -928,7 +942,7 @@ export async function waitForMergeResult(
928
942
  });
929
943
  // Clean up agent (may still be running post-write)
930
944
  if (isV2) {
931
- killMergeAgentV2(sessionName);
945
+ killMergeAgentV2(sessionName, true);
932
946
  } else if (await tmuxHasSessionAsync(sessionName)) {
933
947
  await tmuxKillSessionAsync(sessionName);
934
948
  }
@@ -967,7 +981,7 @@ export async function waitForMergeResult(
967
981
  });
968
982
  // Clean up agent if still alive
969
983
  if (isV2) {
970
- killMergeAgentV2(sessionName);
984
+ killMergeAgentV2(sessionName, true);
971
985
  } else if (await tmuxHasSessionAsync(sessionName)) {
972
986
  await tmuxKillSessionAsync(sessionName);
973
987
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskplane",
3
- "version": "0.23.7",
3
+ "version": "0.23.9",
4
4
  "description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
5
5
  "keywords": [
6
6
  "pi-package",