taskplane 0.23.1 → 0.23.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.
package/dashboard/server.cjs
CHANGED
|
@@ -1015,6 +1015,39 @@ function buildDashboardState() {
|
|
|
1015
1015
|
const runtimeLaneSnapshots = loadRuntimeLaneSnapshots(state.batchId);
|
|
1016
1016
|
const mailboxData = loadMailboxData(state.batchId);
|
|
1017
1017
|
|
|
1018
|
+
// TP-115: Synthesize laneStates from V2 snapshots so the dashboard
|
|
1019
|
+
// pipeline works without legacy lane-state-*.json sidecar files.
|
|
1020
|
+
// V2 snapshots are authoritative when present.
|
|
1021
|
+
if (Object.keys(runtimeLaneSnapshots).length > 0) {
|
|
1022
|
+
for (const [laneNum, snap] of Object.entries(runtimeLaneSnapshots)) {
|
|
1023
|
+
// Find the matching lane record to get the session name key
|
|
1024
|
+
const laneRec = (state.lanes || []).find(l => l.laneNumber === Number(laneNum));
|
|
1025
|
+
const key = laneRec ? laneRec.tmuxSessionName : `lane-${laneNum}`;
|
|
1026
|
+
if (!laneStates[key] || (snap.updatedAt && snap.updatedAt > (laneStates[key].timestamp || 0))) {
|
|
1027
|
+
const w = snap.worker || {};
|
|
1028
|
+
const statusMap = { running: "running", spawning: "running", exited: "done", crashed: "error", killed: "error", timed_out: "error", wrapping_up: "running" };
|
|
1029
|
+
laneStates[key] = {
|
|
1030
|
+
prefix: key,
|
|
1031
|
+
taskId: snap.taskId || null,
|
|
1032
|
+
phase: snap.status === "running" ? "worker-active" : snap.status === "complete" ? "complete" : "idle",
|
|
1033
|
+
workerStatus: statusMap[w.status] || w.status || "idle",
|
|
1034
|
+
workerElapsed: w.elapsedMs || 0,
|
|
1035
|
+
workerContextPct: w.contextPct || 0,
|
|
1036
|
+
workerLastTool: w.lastTool || "",
|
|
1037
|
+
workerToolCount: w.toolCalls || 0,
|
|
1038
|
+
workerInputTokens: w.inputTokens || 0,
|
|
1039
|
+
workerOutputTokens: w.outputTokens || 0,
|
|
1040
|
+
workerCacheReadTokens: w.cacheReadTokens || 0,
|
|
1041
|
+
workerCacheWriteTokens: w.cacheWriteTokens || 0,
|
|
1042
|
+
workerCostUsd: w.costUsd || 0,
|
|
1043
|
+
reviewerStatus: "idle",
|
|
1044
|
+
batchId: snap.batchId || state.batchId,
|
|
1045
|
+
timestamp: snap.updatedAt || Date.now(),
|
|
1046
|
+
};
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1018
1051
|
return {
|
|
1019
1052
|
laneStates,
|
|
1020
1053
|
telemetry,
|
|
@@ -11,8 +11,9 @@ import { userInfo } from "os";
|
|
|
11
11
|
import { DONE_GRACE_MS, EXECUTION_POLL_INTERVAL_MS, ExecutionError, SESSION_SPAWN_RETRY_MAX } from "./types.ts";
|
|
12
12
|
import type { AllocatedLane, AllocatedTask, DependencyGraph, LaneExecutionResult, LaneMonitorSnapshot, LaneTaskOutcome, LaneTaskStatus, MonitorState, MtimeTracker, OrchestratorConfig, ParsedTask, TaskMonitorSnapshot, WaveExecutionResult, WorkspaceConfig, ExecutionUnit, PacketPaths, RuntimeAgentId, RuntimeAgentRole, SupervisorAlertCallback } from "./types.ts";
|
|
13
13
|
import { resolvePacketPaths, buildRuntimeAgentId } from "./types.ts";
|
|
14
|
-
import { readRegistrySnapshot, isTerminalStatus, isProcessAlive } from "./process-registry.ts";
|
|
14
|
+
import { readRegistrySnapshot, readLaneSnapshot, isTerminalStatus, isProcessAlive } from "./process-registry.ts";
|
|
15
15
|
import { allocateLanes } from "./waves.ts";
|
|
16
|
+
import { resolveOperatorId } from "./naming.ts";
|
|
16
17
|
import { runGit } from "./git.ts";
|
|
17
18
|
|
|
18
19
|
// ── Taskplane Package File Resolution ────────────────────────────────
|
|
@@ -1752,11 +1753,18 @@ export async function resolveTaskMonitorState(
|
|
|
1752
1753
|
stallTimeoutMs: number,
|
|
1753
1754
|
now: number,
|
|
1754
1755
|
runtimeBackend?: RuntimeBackend,
|
|
1756
|
+
v2Context?: { stateRoot: string; batchId: string; laneNumber: number },
|
|
1755
1757
|
): Promise<TaskMonitorSnapshot> {
|
|
1756
|
-
// TP-
|
|
1757
|
-
// V2:
|
|
1758
|
+
// TP-115: Backend-aware liveness check.
|
|
1759
|
+
// V2: read the lane snapshot file written by lane-runner every second.
|
|
1760
|
+
// Snapshot status is authoritative — no PID probing needed.
|
|
1761
|
+
// Legacy: check TMUX session.
|
|
1758
1762
|
let sessionAlive: boolean;
|
|
1759
|
-
if (runtimeBackend === "v2") {
|
|
1763
|
+
if (runtimeBackend === "v2" && v2Context) {
|
|
1764
|
+
const snap = readLaneSnapshot(v2Context.stateRoot, v2Context.batchId, v2Context.laneNumber);
|
|
1765
|
+
sessionAlive = snap != null && snap.status === "running";
|
|
1766
|
+
} else if (runtimeBackend === "v2") {
|
|
1767
|
+
// Fallback to registry-based check if no v2Context
|
|
1760
1768
|
sessionAlive = isV2AgentAlive(sessionName, runtimeBackend);
|
|
1761
1769
|
} else {
|
|
1762
1770
|
sessionAlive = await tmuxHasSessionAsync(sessionName);
|
|
@@ -2080,6 +2088,11 @@ export async function monitorLanes(
|
|
|
2080
2088
|
stallTimeoutMs,
|
|
2081
2089
|
now,
|
|
2082
2090
|
runtimeBackend,
|
|
2091
|
+
(runtimeBackend === "v2" && batchId) ? {
|
|
2092
|
+
stateRoot: stateRootForRegistry ?? repoRoot,
|
|
2093
|
+
batchId,
|
|
2094
|
+
laneNumber: lane.laneNumber,
|
|
2095
|
+
} : undefined,
|
|
2083
2096
|
);
|
|
2084
2097
|
|
|
2085
2098
|
currentTaskSnapshot = snapshot;
|
|
@@ -2957,9 +2970,10 @@ export async function executeLaneV2(
|
|
|
2957
2970
|
const stateRoot = resolveRuntimeStateRoot(repoRoot, workspaceRoot);
|
|
2958
2971
|
const batchId = config.orchestrator?.batchId || extraEnvVars?.ORCH_BATCH_ID || String(Date.now());
|
|
2959
2972
|
|
|
2960
|
-
// Build agent ID prefix
|
|
2973
|
+
// Build agent ID prefix — must match the wave planner's naming (TP-115).
|
|
2974
|
+
// Uses resolveOperatorId() so agent registry keys align with tmuxSessionName.
|
|
2961
2975
|
const tmuxPrefix = config.orchestrator?.tmux_prefix ?? "orch";
|
|
2962
|
-
const opId = config
|
|
2976
|
+
const opId = resolveOperatorId(config);
|
|
2963
2977
|
const agentIdPrefix = `${tmuxPrefix}-${opId}`;
|
|
2964
2978
|
|
|
2965
2979
|
// Load worker agent definition for system prompt
|
|
@@ -343,3 +343,22 @@ export function writeLaneSnapshot(
|
|
|
343
343
|
writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2) + "\n", "utf-8");
|
|
344
344
|
renameSync(tmpPath, path);
|
|
345
345
|
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Read a V2 lane snapshot from disk.
|
|
349
|
+
* Returns null if the file doesn't exist or is unreadable.
|
|
350
|
+
* @since TP-115
|
|
351
|
+
*/
|
|
352
|
+
export function readLaneSnapshot(
|
|
353
|
+
stateRoot: string,
|
|
354
|
+
batchId: string,
|
|
355
|
+
laneNumber: number,
|
|
356
|
+
): { status: string; updatedAt?: number } | null {
|
|
357
|
+
try {
|
|
358
|
+
const p = runtimeLaneSnapshotPath(stateRoot, batchId, laneNumber);
|
|
359
|
+
if (!existsSync(p)) return null;
|
|
360
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
361
|
+
} catch {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
}
|