taskplane 0.23.16 → 0.24.1
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/bin/taskplane.mjs +8 -41
- package/dashboard/public/app.js +24 -24
- package/dashboard/server.cjs +29 -7
- package/extensions/task-runner.ts +7 -3
- package/extensions/taskplane/abort.ts +93 -81
- package/extensions/taskplane/agent-host.ts +4 -5
- package/extensions/taskplane/config-loader.ts +1158 -1010
- package/extensions/taskplane/config-schema.ts +13 -13
- package/extensions/taskplane/diagnostic-reports.ts +1 -1
- package/extensions/taskplane/diagnostics.ts +3 -3
- package/extensions/taskplane/engine.ts +37 -16
- package/extensions/taskplane/execution.ts +100 -1006
- package/extensions/taskplane/extension.ts +60 -189
- package/extensions/taskplane/formatting.ts +5 -5
- package/extensions/taskplane/merge.ts +63 -371
- package/extensions/taskplane/messages.ts +1 -1
- package/extensions/taskplane/naming.ts +4 -4
- package/extensions/taskplane/persistence.ts +53 -26
- package/extensions/taskplane/process-registry.ts +3 -3
- package/extensions/taskplane/resume.ts +65 -130
- package/extensions/taskplane/sessions.ts +57 -92
- package/extensions/taskplane/settings-tui.ts +4 -4
- package/extensions/taskplane/tmux-compat.ts +37 -0
- package/extensions/taskplane/types.ts +43 -43
- package/extensions/taskplane/waves.ts +12 -10
- package/extensions/taskplane/worktree.ts +8 -66
- package/package.json +1 -1
- package/templates/config/task-orchestrator.yaml +3 -4
|
@@ -109,8 +109,8 @@ export interface WorkerConfig {
|
|
|
109
109
|
tools: string;
|
|
110
110
|
/** Thinking mode setting passed to worker agent */
|
|
111
111
|
thinking: string;
|
|
112
|
-
/** Optional spawn mode override for task-runner */
|
|
113
|
-
spawnMode?: "subprocess"
|
|
112
|
+
/** Optional spawn mode override for task-runner (Runtime V2 subprocess-only). */
|
|
113
|
+
spawnMode?: "subprocess";
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/** Reviewer agent configuration */
|
|
@@ -139,7 +139,7 @@ export interface ContextConfig {
|
|
|
139
139
|
maxReviewCycles: number;
|
|
140
140
|
/** Max no-progress iterations before marking failure */
|
|
141
141
|
noProgressLimit: number;
|
|
142
|
-
/** Optional per-worker wall-clock cap (minutes, used in
|
|
142
|
+
/** Optional per-worker wall-clock cap (minutes, used in orchestrated flows) */
|
|
143
143
|
maxWorkerMinutes?: number;
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -260,10 +260,10 @@ export interface OrchestratorCoreConfig {
|
|
|
260
260
|
worktreePrefix: string;
|
|
261
261
|
/** Batch ID format used in logs/branch naming */
|
|
262
262
|
batchIdFormat: "timestamp" | "sequential";
|
|
263
|
-
/** How lane sessions are spawned */
|
|
264
|
-
spawnMode: "
|
|
265
|
-
/** Prefix for orchestrator
|
|
266
|
-
|
|
263
|
+
/** How lane sessions are spawned (Runtime V2 subprocess-only). */
|
|
264
|
+
spawnMode: "subprocess";
|
|
265
|
+
/** Prefix for orchestrator session naming */
|
|
266
|
+
sessionPrefix: string;
|
|
267
267
|
/** Operator identifier. Auto-detected from OS username if empty */
|
|
268
268
|
operatorId: string;
|
|
269
269
|
/** How completed batches are integrated. manual = user runs /orch-integrate. supervised = supervisor proposes plan, asks confirmation. auto = supervisor executes without asking. */
|
|
@@ -498,7 +498,7 @@ export interface TaskplaneConfig {
|
|
|
498
498
|
* | Preference field | Config path | Type |
|
|
499
499
|
* |--------------------|--------------------------------------|---------|
|
|
500
500
|
* | operatorId | orchestrator.orchestrator.operatorId | string |
|
|
501
|
-
* |
|
|
501
|
+
* | sessionPrefix | orchestrator.orchestrator.sessionPrefix | string |
|
|
502
502
|
* | spawnMode | orchestrator.orchestrator.spawnMode | string |
|
|
503
503
|
* | workerModel | taskRunner.worker.model | string |
|
|
504
504
|
* | reviewerModel | taskRunner.reviewer.model | string |
|
|
@@ -509,10 +509,10 @@ export interface TaskplaneConfig {
|
|
|
509
509
|
export interface UserPreferences {
|
|
510
510
|
/** Operator identifier (overrides orchestrator.orchestrator.operatorId) */
|
|
511
511
|
operatorId?: string;
|
|
512
|
-
/**
|
|
513
|
-
|
|
514
|
-
/** Spawn mode override (overrides orchestrator.orchestrator.spawnMode) */
|
|
515
|
-
spawnMode?: "
|
|
512
|
+
/** Orchestrator session prefix (overrides orchestrator.orchestrator.sessionPrefix) */
|
|
513
|
+
sessionPrefix?: string;
|
|
514
|
+
/** Spawn mode override (overrides orchestrator.orchestrator.spawnMode). */
|
|
515
|
+
spawnMode?: "subprocess";
|
|
516
516
|
/** Worker model override (overrides taskRunner.worker.model) */
|
|
517
517
|
workerModel?: string;
|
|
518
518
|
/** Reviewer model override (overrides taskRunner.reviewer.model) */
|
|
@@ -582,7 +582,7 @@ export const DEFAULT_ORCHESTRATOR_SECTION: OrchestratorSection = {
|
|
|
582
582
|
worktreePrefix: "taskplane-wt",
|
|
583
583
|
batchIdFormat: "timestamp",
|
|
584
584
|
spawnMode: "subprocess",
|
|
585
|
-
|
|
585
|
+
sessionPrefix: "orch",
|
|
586
586
|
operatorId: "",
|
|
587
587
|
integration: "manual",
|
|
588
588
|
},
|
|
@@ -411,7 +411,7 @@ export function assembleDiagnosticInput(
|
|
|
411
411
|
const record: PersistedTaskRecord = {
|
|
412
412
|
taskId,
|
|
413
413
|
laneNumber: lane?.laneNumber ?? 0,
|
|
414
|
-
sessionName: outcome?.sessionName || lane?.
|
|
414
|
+
sessionName: outcome?.sessionName || lane?.laneSessionId || "",
|
|
415
415
|
status: outcome?.status ?? "pending",
|
|
416
416
|
taskFolder: "",
|
|
417
417
|
startedAt: outcome?.startTime ?? null,
|
|
@@ -49,9 +49,9 @@ export interface SessionTokenCounts {
|
|
|
49
49
|
* | `context_overflow` | Hit context window limit (compactions + high ctx %) |
|
|
50
50
|
* | `wall_clock_timeout` | Killed by task-runner's max_worker_minutes timer |
|
|
51
51
|
* | `process_crash` | Non-zero exit code with no API error indicators |
|
|
52
|
-
* | `session_vanished` |
|
|
52
|
+
* | `session_vanished` | Session disappeared without exit summary |
|
|
53
53
|
* | `stall_timeout` | No STATUS.md progress for stall_timeout minutes |
|
|
54
|
-
* | `user_killed` | User manually killed the session (e.g.,
|
|
54
|
+
* | `user_killed` | User manually killed the session (e.g., forced process kill) |
|
|
55
55
|
* | `unknown` | Could not determine cause |
|
|
56
56
|
*/
|
|
57
57
|
export type ExitClassification =
|
|
@@ -157,7 +157,7 @@ export interface ExitSummary {
|
|
|
157
157
|
* - `timerKilled`: true if task-runner's max_worker_minutes timer killed the session
|
|
158
158
|
* - `contextKilled`: true if the task-runner explicitly killed the session due to context limit
|
|
159
159
|
* - `stallDetected`: true if monitoring detected no STATUS.md progress
|
|
160
|
-
* - `userKilled`: true if user manually killed the session (e.g., /orch-abort,
|
|
160
|
+
* - `userKilled`: true if user manually killed the session (e.g., /orch-abort, forced process kill)
|
|
161
161
|
* - `contextPct`: estimated context utilization % (0-100), null if unknown
|
|
162
162
|
*
|
|
163
163
|
* Design: single structured input object (not positional args) for
|
|
@@ -6,19 +6,19 @@ import { existsSync, readdirSync, readFileSync, unlinkSync } from "fs";
|
|
|
6
6
|
import { join, resolve } from "path";
|
|
7
7
|
|
|
8
8
|
import { formatDiscoveryResults, runDiscovery } from "./discovery.ts";
|
|
9
|
-
import { computeTransitiveDependents, execLog,
|
|
9
|
+
import { computeTransitiveDependents, execLog, executeLaneV2, executeWave, killV2LaneAgents } from "./execution.ts";
|
|
10
10
|
import type { RuntimeBackend } from "./execution.ts";
|
|
11
11
|
import type { MonitorUpdateCallback } from "./execution.ts";
|
|
12
12
|
// classifyExit no longer called directly — Tier 0 uses exitDiagnostic.classification
|
|
13
13
|
// from the diagnostic-reports pipeline (populated by assembleDiagnosticInput).
|
|
14
14
|
import { getCurrentBranch, runGit } from "./git.ts";
|
|
15
|
-
import { mergeWaveByRepo, MergeHealthMonitor } from "./merge.ts";
|
|
15
|
+
import { killAllMergeAgentsV2, mergeWaveByRepo, MergeHealthMonitor } from "./merge.ts";
|
|
16
16
|
import { applyMergeRetryLoop, computeCleanupGatePolicy, computeMergeFailurePolicy, extractFailedRepoId, formatRepoMergeSummary, ORCH_MESSAGES } from "./messages.ts";
|
|
17
17
|
import type { CleanupGateRepoFailure } from "./messages.ts";
|
|
18
18
|
import { assembleDiagnosticInput, emitDiagnosticReports } from "./diagnostic-reports.ts";
|
|
19
19
|
import { resolveOperatorId } from "./naming.ts";
|
|
20
20
|
import { applyPartialProgressToOutcomes, buildTier0EventBase, deleteBatchState, emitEngineEvent, emitTier0Event, loadBatchHistory, loadBatchState, persistRuntimeState, saveBatchHistory, seedPendingOutcomesForAllocatedLanes, syncTaskOutcomesFromMonitor, upsertTaskOutcome } from "./persistence.ts";
|
|
21
|
-
import {
|
|
21
|
+
import { readRegistrySnapshot, isTerminalStatus, isProcessAlive as registryIsProcessAlive } from "./process-registry.ts";
|
|
22
22
|
import { buildBatchProgressSnapshot, buildEngineEventBase, defaultResilienceState, FATAL_DISCOVERY_CODES, generateBatchId, TIER0_RETRYABLE_CLASSIFICATIONS, TIER0_RETRY_BUDGETS, tier0ScopeKey, tier0WaveScopeKey } from "./types.ts";
|
|
23
23
|
import type { AllocatedLane, AllocatedTask, BatchHistorySummary, BatchTaskSummary, BatchWaveSummary, DiscoveryResult, EngineEventCallback, EscalationContext, LaneExecutionResult, LaneTaskOutcome, MergeWaveResult, OrchBatchPhase, OrchBatchRuntimeState, OrchestratorConfig, SupervisorAlert, SupervisorAlertCallback, TaskRunnerConfig, Tier0EscalationPattern, Tier0RecoveryPattern, TokenCounts, WaveExecutionResult, WorkspaceConfig } from "./types.ts";
|
|
24
24
|
import { buildDependencyGraph, computeWaves, resolveBaseBranch, resolveRepoRoot, validateGraph } from "./waves.ts";
|
|
@@ -278,8 +278,7 @@ async function attemptWorkerCrashRetry(
|
|
|
278
278
|
// may be paused due to stop-wave policy, but Tier 0 retry should
|
|
279
279
|
// attempt recovery before the stop decision takes effect (R002-4).
|
|
280
280
|
const retryPauseSignal = { paused: false };
|
|
281
|
-
const
|
|
282
|
-
const retryResult = await retryExecutor(
|
|
281
|
+
const retryResult = await executeLaneV2(
|
|
283
282
|
retryLane,
|
|
284
283
|
orchConfig,
|
|
285
284
|
repoRoot,
|
|
@@ -546,8 +545,7 @@ async function attemptModelFallbackRetry(
|
|
|
546
545
|
// the task-runner to use the session model instead of configured model.
|
|
547
546
|
// TP-089: Also include ORCH_BATCH_ID so mailbox steering works for retries.
|
|
548
547
|
const modelFallbackEnv = { TASKPLANE_MODEL_FALLBACK: "1", ORCH_BATCH_ID: batchState.batchId };
|
|
549
|
-
const
|
|
550
|
-
const retryResult = await retryExecutor(
|
|
548
|
+
const retryResult = await executeLaneV2(
|
|
551
549
|
retryLane,
|
|
552
550
|
orchConfig,
|
|
553
551
|
repoRoot,
|
|
@@ -2475,16 +2473,39 @@ export async function executeOrchBatch(
|
|
|
2475
2473
|
if (preserveWorktreesForResume) {
|
|
2476
2474
|
execLog("batch", batchState.batchId, "skipping final cleanup to preserve worktrees/branches for resume");
|
|
2477
2475
|
} else {
|
|
2478
|
-
// Kill
|
|
2479
|
-
// On Windows,
|
|
2480
|
-
// directory
|
|
2481
|
-
const
|
|
2482
|
-
const
|
|
2483
|
-
if (
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2476
|
+
// Kill lingering Runtime V2 agents BEFORE removing worktrees.
|
|
2477
|
+
// On Windows, lingering processes with cwd inside the worktree can lock
|
|
2478
|
+
// the directory and cause `git worktree remove` to fail.
|
|
2479
|
+
const lingeringLaneSessions = new Set<string>();
|
|
2480
|
+
const registry = readRegistrySnapshot(stateRoot, batchState.batchId);
|
|
2481
|
+
if (registry) {
|
|
2482
|
+
for (const manifest of Object.values(registry.agents)) {
|
|
2483
|
+
if (manifest.role !== "worker" && manifest.role !== "reviewer") continue;
|
|
2484
|
+
if (isTerminalStatus(manifest.status) || !registryIsProcessAlive(manifest.pid)) continue;
|
|
2485
|
+
lingeringLaneSessions.add(manifest.agentId.replace(/-(worker|reviewer)$/, ""));
|
|
2487
2486
|
}
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
let performedAgentCleanup = false;
|
|
2490
|
+
if (lingeringLaneSessions.size > 0) {
|
|
2491
|
+
execLog("batch", batchState.batchId, `killing ${lingeringLaneSessions.size} lingering lane agent session(s) before cleanup`);
|
|
2492
|
+
for (const sessionName of lingeringLaneSessions) {
|
|
2493
|
+
killV2LaneAgents(sessionName, {
|
|
2494
|
+
stateRoot,
|
|
2495
|
+
batchId: batchState.batchId,
|
|
2496
|
+
logContext: "batch",
|
|
2497
|
+
});
|
|
2498
|
+
}
|
|
2499
|
+
performedAgentCleanup = true;
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
const killedMergeAgents = killAllMergeAgentsV2();
|
|
2503
|
+
if (killedMergeAgents > 0) {
|
|
2504
|
+
execLog("batch", batchState.batchId, `killed ${killedMergeAgents} lingering merge agent(s) before cleanup`);
|
|
2505
|
+
performedAgentCleanup = true;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
if (performedAgentCleanup) {
|
|
2488
2509
|
sleepSync(1000); // Give OS time to release file locks
|
|
2489
2510
|
}
|
|
2490
2511
|
|