taskplane 0.22.2 → 0.22.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/extensions/task-runner.ts +32 -4
- package/package.json +1 -1
|
@@ -154,6 +154,8 @@ interface TaskState {
|
|
|
154
154
|
persistentReviewerKill: (() => void) | null;
|
|
155
155
|
/** TP-057: Signal counter for the persistent reviewer (monotonically increasing). */
|
|
156
156
|
persistentReviewerSignalNum: number;
|
|
157
|
+
/** Reviewer respawn counter — circuit breaker to prevent infinite respawn loops. */
|
|
158
|
+
reviewerRespawnCount: number;
|
|
157
159
|
totalIterations: number;
|
|
158
160
|
stepStatuses: Map<number, StepInfo>;
|
|
159
161
|
}
|
|
@@ -172,7 +174,7 @@ function freshState(): TaskState {
|
|
|
172
174
|
reviewerInputTokens: 0, reviewerOutputTokens: 0, reviewerCacheReadTokens: 0, reviewerCacheWriteTokens: 0,
|
|
173
175
|
reviewerCostUsd: 0, reviewerContextPct: 0, reviewerProc: null, reviewerTimer: null,
|
|
174
176
|
reviewCounter: 0,
|
|
175
|
-
persistentReviewerSession: null, persistentReviewerKill: null, persistentReviewerSignalNum: 0,
|
|
177
|
+
persistentReviewerSession: null, persistentReviewerKill: null, persistentReviewerSignalNum: 0, reviewerRespawnCount: 0,
|
|
176
178
|
totalIterations: 0, stepStatuses: new Map(),
|
|
177
179
|
};
|
|
178
180
|
}
|
|
@@ -2503,9 +2505,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
2503
2505
|
|
|
2504
2506
|
if (needsSpawn && state.persistentReviewerSession) {
|
|
2505
2507
|
// Session was previously active but died — log fallback
|
|
2506
|
-
|
|
2508
|
+
state.reviewerRespawnCount++;
|
|
2509
|
+
const MAX_REVIEWER_RESPAWNS = 3;
|
|
2510
|
+
if (state.reviewerRespawnCount > MAX_REVIEWER_RESPAWNS) {
|
|
2511
|
+
console.error(`[task-runner] reviewer respawn limit (${MAX_REVIEWER_RESPAWNS}) exceeded — skipping review`);
|
|
2512
|
+
logExecution(statusPath, `Reviewer R${num}`,
|
|
2513
|
+
`reviewer respawn limit exceeded (${state.reviewerRespawnCount}/${MAX_REVIEWER_RESPAWNS}) — skipping review`);
|
|
2514
|
+
state.persistentReviewerSession = null;
|
|
2515
|
+
state.persistentReviewerKill = null;
|
|
2516
|
+
state.persistentReviewerSignalNum = 0;
|
|
2517
|
+
return {
|
|
2518
|
+
content: [{ type: "text" as const, text: `⚠️ Reviewer respawn limit exceeded (${MAX_REVIEWER_RESPAWNS}). Review skipped — proceeding without review.` }],
|
|
2519
|
+
details: undefined,
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
console.error(`[task-runner] persistent reviewer session dead — respawning (${state.reviewerRespawnCount}/${MAX_REVIEWER_RESPAWNS})`);
|
|
2507
2523
|
logExecution(statusPath, `Reviewer R${num}`,
|
|
2508
|
-
`persistent reviewer dead — respawning for ${reviewType} review`);
|
|
2524
|
+
`persistent reviewer dead — respawning for ${reviewType} review (${state.reviewerRespawnCount}/${MAX_REVIEWER_RESPAWNS})`);
|
|
2509
2525
|
state.persistentReviewerSession = null;
|
|
2510
2526
|
state.persistentReviewerKill = null;
|
|
2511
2527
|
state.persistentReviewerSignalNum = 0;
|
|
@@ -2553,7 +2569,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
2553
2569
|
};
|
|
2554
2570
|
} catch (err: any) {
|
|
2555
2571
|
// ── Fallback: kill persistent session, try fresh spawn ──
|
|
2556
|
-
|
|
2572
|
+
state.reviewerRespawnCount++;
|
|
2573
|
+
console.error(`[task-runner] persistent reviewer error (${state.reviewerRespawnCount}/3): ${err?.message || err}`);
|
|
2557
2574
|
logExecution(statusPath, `Reviewer R${num}`,
|
|
2558
2575
|
`persistent reviewer failed — falling back to fresh spawn: ${err?.message || err}`);
|
|
2559
2576
|
|
|
@@ -2565,6 +2582,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
2565
2582
|
state.persistentReviewerKill = null;
|
|
2566
2583
|
state.persistentReviewerSignalNum = 0;
|
|
2567
2584
|
|
|
2585
|
+
// Circuit breaker — skip review if we've exhausted respawns
|
|
2586
|
+
if (state.reviewerRespawnCount > 3) {
|
|
2587
|
+
console.error(`[task-runner] reviewer respawn limit exceeded — skipping review`);
|
|
2588
|
+
logExecution(statusPath, `Reviewer R${num}`,
|
|
2589
|
+
`reviewer respawn limit exceeded — review skipped`);
|
|
2590
|
+
return {
|
|
2591
|
+
content: [{ type: "text" as const, text: `⚠️ Reviewer respawn limit exceeded. Review skipped — proceeding without review.` }],
|
|
2592
|
+
details: undefined,
|
|
2593
|
+
};
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2568
2596
|
// ── Fresh spawn fallback (original behavior) ────────
|
|
2569
2597
|
try {
|
|
2570
2598
|
const promptContent = readFileSync(requestPath, "utf-8");
|