taskplane 0.22.5 → 0.22.7
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 +50 -2
- package/package.json +1 -1
- package/templates/agents/task-worker.md +17 -15
|
@@ -2148,6 +2148,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2148
2148
|
|
|
2149
2149
|
// ── review_step Tool (orchestrated mode only) ───────────────────
|
|
2150
2150
|
|
|
2151
|
+
/** Per-step code review cycle counter. Reset when reviewer is killed after APPROVE. */
|
|
2152
|
+
const stepCodeReviewCounts = new Map<number, number>();
|
|
2153
|
+
|
|
2151
2154
|
/**
|
|
2152
2155
|
* Reset reviewer telemetry fields on state to idle/zero.
|
|
2153
2156
|
* Called after a review completes to clear dashboard metrics.
|
|
@@ -2291,6 +2294,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2291
2294
|
const reviewsDir = join(task.taskFolder, ".reviews");
|
|
2292
2295
|
if (!existsSync(reviewsDir)) mkdirSync(reviewsDir, { recursive: true });
|
|
2293
2296
|
|
|
2297
|
+
// Per-step code review cycle limit
|
|
2298
|
+
if (reviewType === "code") {
|
|
2299
|
+
const codeCount = (stepCodeReviewCounts.get(stepNum) || 0) + 1;
|
|
2300
|
+
stepCodeReviewCounts.set(stepNum, codeCount);
|
|
2301
|
+
const maxCycles = config.context.max_review_cycles || 2;
|
|
2302
|
+
if (codeCount > maxCycles) {
|
|
2303
|
+
logExecution(statusPath, `Skip code review`,
|
|
2304
|
+
`Step ${stepNum} code review cycle limit reached (${codeCount}/${maxCycles}) — auto-approving`);
|
|
2305
|
+
// Kill reviewer to free context for next step
|
|
2306
|
+
if (state.persistentReviewerKill) {
|
|
2307
|
+
try { state.persistentReviewerKill(); } catch {}
|
|
2308
|
+
}
|
|
2309
|
+
state.persistentReviewerSession = null;
|
|
2310
|
+
state.persistentReviewerKill = null;
|
|
2311
|
+
state.persistentReviewerSignalNum = 0;
|
|
2312
|
+
state.reviewerRespawnCount = 0;
|
|
2313
|
+
stepCodeReviewCounts.delete(stepNum);
|
|
2314
|
+
return {
|
|
2315
|
+
content: [{ type: "text" as const, text: `APPROVE — Code review cycle limit reached (${maxCycles}). Auto-approved to prevent context exhaustion.` }],
|
|
2316
|
+
details: undefined,
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
|
|
2294
2321
|
// Low-risk step check (safety net — worker template also skips)
|
|
2295
2322
|
if (isLowRiskStep(stepNum, task.steps.length)) {
|
|
2296
2323
|
const label = stepNum === 0 ? "Preflight" : "final step";
|
|
@@ -2551,11 +2578,29 @@ export default function (pi: ExtensionAPI) {
|
|
|
2551
2578
|
updateWidgets();
|
|
2552
2579
|
|
|
2553
2580
|
// Extract verdict and build result
|
|
2554
|
-
const { resultText } = processReviewVerdict(
|
|
2581
|
+
const { resultText, verdict } = processReviewVerdict(
|
|
2555
2582
|
reviewContent, statusPath, num, reviewType, stepNum, state.reviewCounter,
|
|
2556
2583
|
);
|
|
2557
2584
|
|
|
2558
|
-
//
|
|
2585
|
+
// After code review APPROVE: kill the persistent reviewer to free context.
|
|
2586
|
+
// The reviewer persists through plan+code for one step, and through
|
|
2587
|
+
// REVISE→fix→re-review cycles (it knows what it asked to be fixed).
|
|
2588
|
+
// Only kill on APPROVE — a REVISE means the worker needs to fix and
|
|
2589
|
+
// re-submit, and the same reviewer should evaluate the follow-up.
|
|
2590
|
+
if (reviewType === "code" && (verdict === "APPROVE" || verdict === "UNAVAILABLE")) {
|
|
2591
|
+
console.error(`[task-runner] code review ${verdict} for step ${stepNum} — killing reviewer for fresh context on next step`);
|
|
2592
|
+
logExecution(statusPath, `Reviewer R${num}`,
|
|
2593
|
+
`code review ${verdict} — killing persistent reviewer (step ${stepNum} cycle done)`);
|
|
2594
|
+
if (state.persistentReviewerKill) {
|
|
2595
|
+
try { state.persistentReviewerKill(); } catch {}
|
|
2596
|
+
}
|
|
2597
|
+
state.persistentReviewerSession = null;
|
|
2598
|
+
state.persistentReviewerKill = null;
|
|
2599
|
+
state.persistentReviewerSignalNum = 0;
|
|
2600
|
+
state.reviewerRespawnCount = 0;
|
|
2601
|
+
stepCodeReviewCounts.delete(stepNum);
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2559
2604
|
state.reviewerStatus = "idle";
|
|
2560
2605
|
state.reviewerType = "";
|
|
2561
2606
|
state.reviewerStep = 0;
|
|
@@ -2643,6 +2688,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2643
2688
|
fallbackContent, statusPath, num, reviewType, stepNum, state.reviewCounter, "fallback",
|
|
2644
2689
|
);
|
|
2645
2690
|
|
|
2691
|
+
// Reset respawn counter on successful fallback review
|
|
2692
|
+
state.reviewerRespawnCount = 0;
|
|
2693
|
+
|
|
2646
2694
|
clearReviewerState();
|
|
2647
2695
|
writeLaneState(state);
|
|
2648
2696
|
updateWidgets();
|
package/package.json
CHANGED
|
@@ -289,33 +289,35 @@ checkpoints protect against regressions even when intermediate steps use targete
|
|
|
289
289
|
2. The merge agent (before merging to the orchestrator branch)
|
|
290
290
|
3. CI (before merging to main)
|
|
291
291
|
|
|
292
|
-
## File Reading Strategy (Context Budget)
|
|
292
|
+
## File Reading Strategy (Context Budget) — CRITICAL
|
|
293
293
|
|
|
294
|
-
Your context window is finite. Reading large files
|
|
295
|
-
|
|
296
|
-
|
|
294
|
+
Your context window is finite. **Reading large files without offset/limit is the
|
|
295
|
+
#1 cause of context exhaustion** — one full read of a 3000-line file consumes
|
|
296
|
+
~5% of a 1M context window. Three such reads = 15% gone before you've done
|
|
297
|
+
anything.
|
|
298
|
+
|
|
299
|
+
### HARD RULES
|
|
300
|
+
|
|
301
|
+
1. **NEVER read a file > 500 lines without offset/limit.** Always grep first.
|
|
302
|
+
2. **NEVER read the same file twice in full.** Re-read only the changed region.
|
|
303
|
+
3. **ALWAYS check file size before reading:** `wc -l <file>` or `ls -la <file>`
|
|
297
304
|
|
|
298
305
|
### Pattern: grep-first, read-with-offset
|
|
299
306
|
|
|
300
|
-
1. **
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
2. **Read** just that region with `offset` and `limit`:
|
|
305
|
-
```
|
|
306
|
-
read extensions/task-runner.ts (offset: 1773, limit: 50)
|
|
307
|
-
```
|
|
308
|
-
3. **Edit** surgically with exact `oldText → newText`
|
|
307
|
+
1. **Check size:** `wc -l extensions/task-runner.ts` → 4100 lines (DO NOT read fully)
|
|
308
|
+
2. **Locate** the relevant section: `grep -n "function buildPrompt" extensions/task-runner.ts`
|
|
309
|
+
3. **Read** just that region: `read extensions/task-runner.ts (offset: 1773, limit: 50)`
|
|
310
|
+
4. **Edit** surgically with exact `oldText → newText`
|
|
309
311
|
|
|
310
312
|
### When to read a full file
|
|
311
313
|
|
|
312
314
|
- Files under ~500 lines — read the whole thing, it's fine
|
|
313
|
-
- Config files, test files, templates — usually small enough
|
|
315
|
+
- Config files, small test files, templates — usually small enough
|
|
314
316
|
- New files you're creating — read after writing to verify
|
|
315
317
|
|
|
316
318
|
### When NOT to read a full file
|
|
317
319
|
|
|
318
|
-
- Source files over ~
|
|
320
|
+
- Source files over ~500 lines — grep first, read with offset/limit
|
|
319
321
|
- Generated files, lock files, large data files — almost never need full reads
|
|
320
322
|
- Files you've already read this session — re-read only the changed region
|
|
321
323
|
|