taskplane 0.23.8 → 0.23.10
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.
|
@@ -14,8 +14,21 @@ import { fileURLToPath } from "node:url";
|
|
|
14
14
|
import { dirname, join } from "node:path";
|
|
15
15
|
|
|
16
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
17
|
+
|
|
18
|
+
// TP-115: Purge jiti cache for taskplane modules before loading.
|
|
19
|
+
// Pi's main process caches compiled .ts → .mjs at $TEMP/jiti/.
|
|
20
|
+
// The engine-worker fork must compile fresh from current source files,
|
|
21
|
+
// not use stale cached versions from Pi's startup.
|
|
22
|
+
import { readdirSync, unlinkSync } from "node:fs";
|
|
23
|
+
import { tmpdir } from "node:os";
|
|
24
|
+
try {
|
|
25
|
+
const cacheDir = join(tmpdir(), "jiti");
|
|
26
|
+
for (const f of readdirSync(cacheDir)) {
|
|
27
|
+
if (f.startsWith("taskplane-") && f.endsWith(".mjs")) {
|
|
28
|
+
try { unlinkSync(join(cacheDir, f)); } catch {}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} catch { /* cache dir may not exist */ }
|
|
32
|
+
|
|
33
|
+
const jiti = createJiti(import.meta.url);
|
|
21
34
|
await jiti.import(join(__dirname, "engine-worker.ts"));
|
|
@@ -2268,7 +2268,7 @@ export async function executeOrchBatch(
|
|
|
2268
2268
|
const w = snap.worker || {};
|
|
2269
2269
|
const r = snap.reviewer || {};
|
|
2270
2270
|
// Key by session name (match lane record) for per-task lookup
|
|
2271
|
-
const laneRec = batchState.lanes.find((l: { laneNumber: number }) => l.laneNumber === snap.laneNumber);
|
|
2271
|
+
const laneRec = (batchState.lanes || []).find((l: { laneNumber: number }) => l.laneNumber === snap.laneNumber);
|
|
2272
2272
|
const key = laneRec?.tmuxSessionName || `lane-${snap.laneNumber}`;
|
|
2273
2273
|
laneTokens.set(key, {
|
|
2274
2274
|
input: (w.inputTokens || 0) + (r.inputTokens || 0),
|
|
@@ -2282,6 +2282,7 @@ export async function executeOrchBatch(
|
|
|
2282
2282
|
}
|
|
2283
2283
|
} catch { /* runtime dir may not exist */ }
|
|
2284
2284
|
|
|
2285
|
+
|
|
2285
2286
|
// Legacy fallback: lane-state-*.json sidecars (only if V2 found nothing)
|
|
2286
2287
|
if (laneTokens.size === 0) {
|
|
2287
2288
|
try {
|
|
@@ -2320,7 +2321,11 @@ export async function executeOrchBatch(
|
|
|
2320
2321
|
const durationMs = (to.startTime && to.endTime) ? (to.endTime - to.startTime) : 0;
|
|
2321
2322
|
|
|
2322
2323
|
// Get tokens for this lane (cumulative — shared across tasks in same lane)
|
|
2323
|
-
|
|
2324
|
+
// TP-115: V2 sessionName includes role suffix (-worker/-reviewer) but
|
|
2325
|
+
// laneTokens is keyed by tmuxSessionName (no suffix). Try both.
|
|
2326
|
+
const tokens = laneTokens.get(to.sessionName)
|
|
2327
|
+
|| laneTokens.get(to.sessionName?.replace(/-(?:worker|reviewer)$/, ""))
|
|
2328
|
+
|| { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, costUsd: 0 };
|
|
2324
2329
|
|
|
2325
2330
|
return {
|
|
2326
2331
|
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
|
}
|