taskplane 0.5.11 → 0.6.0
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/README.md +1 -1
- package/bin/rpc-wrapper.mjs +777 -0
- package/dashboard/public/app.js +45 -6
- package/dashboard/public/style.css +31 -0
- package/dashboard/server.cjs +326 -1
- package/extensions/task-runner.ts +1111 -30
- package/extensions/taskplane/config-loader.ts +31 -0
- package/extensions/taskplane/config-schema.ts +88 -0
- package/extensions/taskplane/diagnostic-reports.ts +463 -0
- package/extensions/taskplane/diagnostics.ts +323 -0
- package/extensions/taskplane/engine.ts +407 -62
- package/extensions/taskplane/extension.ts +259 -8
- package/extensions/taskplane/index.ts +1 -0
- package/extensions/taskplane/merge.ts +787 -69
- package/extensions/taskplane/messages.ts +594 -2
- package/extensions/taskplane/persistence.ts +342 -19
- package/extensions/taskplane/quality-gate.ts +1033 -0
- package/extensions/taskplane/resume.ts +505 -36
- package/extensions/taskplane/supervisor-primer.md +664 -0
- package/extensions/taskplane/types.ts +534 -6
- package/extensions/taskplane/verification.ts +537 -0
- package/extensions/taskplane/worktree.ts +329 -1
- package/package.json +1 -1
- package/skills/create-taskplane-task/references/prompt-template.md +0 -2
- package/templates/agents/task-reviewer.md +54 -2
- package/templates/agents/task-worker.md +8 -4
|
@@ -10,7 +10,7 @@ import { execLog } from "./execution.ts";
|
|
|
10
10
|
import { runGit } from "./git.ts";
|
|
11
11
|
import { resolveOperatorId } from "./naming.ts";
|
|
12
12
|
import { DEFAULT_ORCHESTRATOR_CONFIG, WorktreeError } from "./types.ts";
|
|
13
|
-
import type { BulkWorktreeError, CreateLaneWorktreesResult, CreateWorktreeOptions, OrchestratorConfig, PreflightCheck, PreflightResult, RemoveAllWorktreesResult, RemoveWorktreeOutcome, RemoveWorktreeResult, WorktreeInfo } from "./types.ts";
|
|
13
|
+
import type { AllocatedLane, BulkWorktreeError, CreateLaneWorktreesResult, CreateWorktreeOptions, LaneTaskOutcome, OrchestratorConfig, PreflightCheck, PreflightResult, RemoveAllWorktreesResult, RemoveWorktreeOutcome, RemoveWorktreeResult, WorktreeInfo } from "./types.ts";
|
|
14
14
|
|
|
15
15
|
// ── Worktree Helpers ─────────────────────────────────────────────────
|
|
16
16
|
|
|
@@ -1572,6 +1572,21 @@ export function removeAllWorktrees(
|
|
|
1572
1572
|
removeBatchContainerIfEmpty(containerPath);
|
|
1573
1573
|
}
|
|
1574
1574
|
|
|
1575
|
+
// TP-029: Remove empty .worktrees/ base directory in subdirectory mode.
|
|
1576
|
+
// In sibling mode the base dir is the repo's parent (e.g., "..") — never remove that.
|
|
1577
|
+
// Only attempt removal when empty (same safety as container cleanup).
|
|
1578
|
+
if (config && config.orchestrator.worktree_location !== "sibling") {
|
|
1579
|
+
const basePath = resolveWorktreeBasePath(repoRoot, config);
|
|
1580
|
+
try {
|
|
1581
|
+
if (existsSync(basePath)) {
|
|
1582
|
+
const entries = readdirSync(basePath);
|
|
1583
|
+
if (entries.length === 0) {
|
|
1584
|
+
rmdirSync(basePath);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
} catch { /* safe default — leave it alone */ }
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1575
1590
|
return {
|
|
1576
1591
|
totalAttempted: worktrees.length,
|
|
1577
1592
|
removed,
|
|
@@ -1982,3 +1997,316 @@ export function forceCleanupWorktree(
|
|
|
1982
1997
|
}
|
|
1983
1998
|
}
|
|
1984
1999
|
|
|
2000
|
+
|
|
2001
|
+
// ── Partial Progress Preservation ────────────────────────────────────
|
|
2002
|
+
|
|
2003
|
+
/**
|
|
2004
|
+
* Result of saving partial progress for a single failed task.
|
|
2005
|
+
*/
|
|
2006
|
+
export interface SavePartialProgressResult {
|
|
2007
|
+
/** Whether partial progress was saved (branch created or already existed) */
|
|
2008
|
+
saved: boolean;
|
|
2009
|
+
/** The saved branch name, if saved */
|
|
2010
|
+
savedBranch?: string;
|
|
2011
|
+
/** Number of commits ahead of the target branch */
|
|
2012
|
+
commitCount: number;
|
|
2013
|
+
/** Task ID this progress belongs to */
|
|
2014
|
+
taskId: string;
|
|
2015
|
+
/** Error message if save failed */
|
|
2016
|
+
error?: string;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
/**
|
|
2020
|
+
* Compute the saved branch name for partial progress from a failed task.
|
|
2021
|
+
*
|
|
2022
|
+
* Naming convention per roadmap Phase 2 section 2a:
|
|
2023
|
+
* - Repo mode: `saved/{opId}-{taskId}-{batchId}`
|
|
2024
|
+
* - Workspace mode: `saved/{opId}-{repoId}-{taskId}-{batchId}`
|
|
2025
|
+
*
|
|
2026
|
+
* Pure function — no side effects.
|
|
2027
|
+
*
|
|
2028
|
+
* @param opId - Operator identifier (sanitized)
|
|
2029
|
+
* @param taskId - Task identifier (e.g., "TP-028")
|
|
2030
|
+
* @param batchId - Batch ID timestamp (e.g., "20260308T111750")
|
|
2031
|
+
* @param repoId - Repo identifier (workspace mode only; omit for repo mode)
|
|
2032
|
+
* @returns Saved branch name
|
|
2033
|
+
*/
|
|
2034
|
+
export function computePartialProgressBranchName(
|
|
2035
|
+
opId: string,
|
|
2036
|
+
taskId: string,
|
|
2037
|
+
batchId: string,
|
|
2038
|
+
repoId?: string,
|
|
2039
|
+
): string {
|
|
2040
|
+
if (repoId) {
|
|
2041
|
+
return `saved/${opId}-${repoId}-${taskId}-${batchId}`;
|
|
2042
|
+
}
|
|
2043
|
+
return `saved/${opId}-${taskId}-${batchId}`;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
/**
|
|
2047
|
+
* Save partial progress from a failed task's lane branch.
|
|
2048
|
+
*
|
|
2049
|
+
* Checks if the lane branch has commits ahead of the target branch,
|
|
2050
|
+
* and if so, creates a saved branch preserving those commits.
|
|
2051
|
+
*
|
|
2052
|
+
* Uses `resolveSavedBranchCollision()` for idempotent collision handling:
|
|
2053
|
+
* - Same SHA → no-op (keep existing)
|
|
2054
|
+
* - Different SHA → create with timestamp suffix
|
|
2055
|
+
*
|
|
2056
|
+
* @param laneBranch - The lane branch that may have partial commits
|
|
2057
|
+
* @param targetBranch - The base/target branch to compare against
|
|
2058
|
+
* @param opId - Operator identifier
|
|
2059
|
+
* @param taskId - Task identifier
|
|
2060
|
+
* @param batchId - Batch ID
|
|
2061
|
+
* @param repoRoot - Repository root for git operations
|
|
2062
|
+
* @param repoId - Repo identifier (workspace mode only)
|
|
2063
|
+
* @returns SavePartialProgressResult describing what was done
|
|
2064
|
+
*/
|
|
2065
|
+
export function savePartialProgress(
|
|
2066
|
+
laneBranch: string,
|
|
2067
|
+
targetBranch: string,
|
|
2068
|
+
opId: string,
|
|
2069
|
+
taskId: string,
|
|
2070
|
+
batchId: string,
|
|
2071
|
+
repoRoot: string,
|
|
2072
|
+
repoId?: string,
|
|
2073
|
+
): SavePartialProgressResult {
|
|
2074
|
+
// Check if lane branch exists
|
|
2075
|
+
const branchCheck = runGit(
|
|
2076
|
+
["rev-parse", "--verify", `refs/heads/${laneBranch}`],
|
|
2077
|
+
repoRoot,
|
|
2078
|
+
);
|
|
2079
|
+
if (!branchCheck.ok) {
|
|
2080
|
+
return { saved: false, commitCount: 0, taskId, error: `Lane branch "${laneBranch}" not found` };
|
|
2081
|
+
}
|
|
2082
|
+
const branchSHA = branchCheck.stdout.trim();
|
|
2083
|
+
|
|
2084
|
+
// Count commits ahead of target branch
|
|
2085
|
+
const unmergedResult = hasUnmergedCommits(laneBranch, targetBranch, repoRoot);
|
|
2086
|
+
if (!unmergedResult.ok) {
|
|
2087
|
+
return {
|
|
2088
|
+
saved: false,
|
|
2089
|
+
commitCount: 0,
|
|
2090
|
+
taskId,
|
|
2091
|
+
error: `Failed to count commits: ${unmergedResult.error}`,
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
if (unmergedResult.count === 0) {
|
|
2096
|
+
// No partial progress — lane branch has no new commits
|
|
2097
|
+
return { saved: false, commitCount: 0, taskId };
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
// Compute saved branch name using task-ID naming convention
|
|
2101
|
+
const savedName = computePartialProgressBranchName(opId, taskId, batchId, repoId);
|
|
2102
|
+
|
|
2103
|
+
// Check for collision (idempotent re-runs, retries)
|
|
2104
|
+
const existingCheck = runGit(
|
|
2105
|
+
["rev-parse", "--verify", `refs/heads/${savedName}`],
|
|
2106
|
+
repoRoot,
|
|
2107
|
+
);
|
|
2108
|
+
const existingSHA = existingCheck.ok ? existingCheck.stdout.trim() : "";
|
|
2109
|
+
|
|
2110
|
+
const resolution = resolveSavedBranchCollision(savedName, existingSHA, branchSHA);
|
|
2111
|
+
|
|
2112
|
+
switch (resolution.action) {
|
|
2113
|
+
case "keep-existing":
|
|
2114
|
+
// Already preserved at the same SHA — idempotent success
|
|
2115
|
+
return {
|
|
2116
|
+
saved: true,
|
|
2117
|
+
savedBranch: resolution.savedName,
|
|
2118
|
+
commitCount: unmergedResult.count,
|
|
2119
|
+
taskId,
|
|
2120
|
+
};
|
|
2121
|
+
|
|
2122
|
+
case "create":
|
|
2123
|
+
case "create-suffixed": {
|
|
2124
|
+
const createResult = runGit(
|
|
2125
|
+
["branch", resolution.savedName, branchSHA],
|
|
2126
|
+
repoRoot,
|
|
2127
|
+
);
|
|
2128
|
+
if (!createResult.ok) {
|
|
2129
|
+
return {
|
|
2130
|
+
saved: false,
|
|
2131
|
+
commitCount: unmergedResult.count,
|
|
2132
|
+
taskId,
|
|
2133
|
+
error: `Failed to create saved branch "${resolution.savedName}": ${createResult.stderr}`,
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2136
|
+
return {
|
|
2137
|
+
saved: true,
|
|
2138
|
+
savedBranch: resolution.savedName,
|
|
2139
|
+
commitCount: unmergedResult.count,
|
|
2140
|
+
taskId,
|
|
2141
|
+
};
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
default:
|
|
2145
|
+
return {
|
|
2146
|
+
saved: false,
|
|
2147
|
+
commitCount: unmergedResult.count,
|
|
2148
|
+
taskId,
|
|
2149
|
+
error: `Unknown collision resolution action`,
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
/**
|
|
2155
|
+
* Result of preserving partial progress across all failed tasks.
|
|
2156
|
+
*/
|
|
2157
|
+
export interface PreserveFailedLaneProgressResult {
|
|
2158
|
+
/** Per-task results for each failed task that was checked */
|
|
2159
|
+
results: SavePartialProgressResult[];
|
|
2160
|
+
/**
|
|
2161
|
+
* Set of saved branch names that were created (e.g., `saved/{opId}-{taskId}-{batchId}`).
|
|
2162
|
+
* These branches independently preserve the commits — lane branches can still be
|
|
2163
|
+
* safely deleted during cleanup since the saved refs retain reachability.
|
|
2164
|
+
*/
|
|
2165
|
+
preservedBranches: Set<string>;
|
|
2166
|
+
/**
|
|
2167
|
+
* Set of lane branch names where preservation FAILED but commits existed.
|
|
2168
|
+
* These branches are unsafe to reset/delete — doing so would lose commits
|
|
2169
|
+
* that were not successfully saved to a separate branch. Callers should skip
|
|
2170
|
+
* worktree reset and branch deletion for these branches to prevent data loss.
|
|
2171
|
+
*/
|
|
2172
|
+
unsafeBranches: Set<string>;
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
/**
|
|
2176
|
+
* Callback for resolving repo root and target branch for a given repoId.
|
|
2177
|
+
*
|
|
2178
|
+
* Allows callers (engine.ts, resume.ts) to pass workspace-aware resolution
|
|
2179
|
+
* logic without creating a circular dependency (worktree.ts → waves.ts → worktree.ts).
|
|
2180
|
+
*
|
|
2181
|
+
* @param repoId - Repo identifier (undefined in repo mode)
|
|
2182
|
+
* @returns { repoRoot, targetBranch } for the given repo
|
|
2183
|
+
*/
|
|
2184
|
+
export type ResolveRepoContext = (repoId: string | undefined) => {
|
|
2185
|
+
repoRoot: string;
|
|
2186
|
+
targetBranch: string;
|
|
2187
|
+
};
|
|
2188
|
+
|
|
2189
|
+
/**
|
|
2190
|
+
* Preserve partial progress for all failed tasks before cleanup/reset.
|
|
2191
|
+
*
|
|
2192
|
+
* Iterates task outcomes to find failed/stalled tasks, maps each to its
|
|
2193
|
+
* lane branch via the allocated lanes, and saves any partial commits as
|
|
2194
|
+
* task-ID-named saved branches.
|
|
2195
|
+
*
|
|
2196
|
+
* Returns two branch sets:
|
|
2197
|
+
* - `preservedBranches`: saved branch names that were successfully created
|
|
2198
|
+
* (lane branches can be safely deleted since these refs retain commits)
|
|
2199
|
+
* - `unsafeBranches`: lane branch names where preservation FAILED but commits
|
|
2200
|
+
* existed (callers must NOT reset/delete these to prevent data loss)
|
|
2201
|
+
*
|
|
2202
|
+
* Workspace-aware: uses the provided `resolveRepo` callback to resolve
|
|
2203
|
+
* per-repo target branches and repo roots for correct commit counting
|
|
2204
|
+
* in workspace mode.
|
|
2205
|
+
*
|
|
2206
|
+
* @param allocatedLanes - Lanes from the current/last wave (maps tasks to branches)
|
|
2207
|
+
* @param taskOutcomes - All task outcomes accumulated so far
|
|
2208
|
+
* @param opId - Operator identifier
|
|
2209
|
+
* @param batchId - Batch ID
|
|
2210
|
+
* @param resolveRepo - Callback to resolve repo root and target branch per repoId
|
|
2211
|
+
* @returns PreserveFailedLaneProgressResult with per-task results and preserved branch set
|
|
2212
|
+
*/
|
|
2213
|
+
export function preserveFailedLaneProgress(
|
|
2214
|
+
allocatedLanes: AllocatedLane[],
|
|
2215
|
+
taskOutcomes: LaneTaskOutcome[],
|
|
2216
|
+
opId: string,
|
|
2217
|
+
batchId: string,
|
|
2218
|
+
resolveRepo: ResolveRepoContext,
|
|
2219
|
+
): PreserveFailedLaneProgressResult {
|
|
2220
|
+
const results: SavePartialProgressResult[] = [];
|
|
2221
|
+
const preservedBranches = new Set<string>();
|
|
2222
|
+
const unsafeBranches = new Set<string>();
|
|
2223
|
+
|
|
2224
|
+
// Build a map: taskId → { laneBranch, repoId } from allocated lanes
|
|
2225
|
+
const taskToLane = new Map<string, { branch: string; repoId?: string }>();
|
|
2226
|
+
for (const lane of allocatedLanes) {
|
|
2227
|
+
for (const allocatedTask of lane.tasks) {
|
|
2228
|
+
taskToLane.set(allocatedTask.taskId, {
|
|
2229
|
+
branch: lane.branch,
|
|
2230
|
+
repoId: lane.repoId,
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
// Find failed/stalled tasks
|
|
2236
|
+
const failedTasks = taskOutcomes.filter(
|
|
2237
|
+
(to) => to.status === "failed" || to.status === "stalled",
|
|
2238
|
+
);
|
|
2239
|
+
|
|
2240
|
+
// Track which lane branches we've already processed (a lane may have
|
|
2241
|
+
// multiple tasks; only save once per branch since all commits are shared)
|
|
2242
|
+
const processedBranches = new Set<string>();
|
|
2243
|
+
|
|
2244
|
+
for (const failedTask of failedTasks) {
|
|
2245
|
+
const laneInfo = taskToLane.get(failedTask.taskId);
|
|
2246
|
+
if (!laneInfo) {
|
|
2247
|
+
// Task not found in allocated lanes — skip (shouldn't happen)
|
|
2248
|
+
results.push({
|
|
2249
|
+
saved: false,
|
|
2250
|
+
commitCount: 0,
|
|
2251
|
+
taskId: failedTask.taskId,
|
|
2252
|
+
error: "Task not found in allocated lanes",
|
|
2253
|
+
});
|
|
2254
|
+
continue;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
// Skip if we've already processed this branch (multiple failed tasks on same lane)
|
|
2258
|
+
if (processedBranches.has(laneInfo.branch)) {
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2261
|
+
processedBranches.add(laneInfo.branch);
|
|
2262
|
+
|
|
2263
|
+
// Resolve repo-specific target branch and repo root
|
|
2264
|
+
const { repoRoot: perRepoRoot, targetBranch } = resolveRepo(laneInfo.repoId);
|
|
2265
|
+
|
|
2266
|
+
const result = savePartialProgress(
|
|
2267
|
+
laneInfo.branch,
|
|
2268
|
+
targetBranch,
|
|
2269
|
+
opId,
|
|
2270
|
+
failedTask.taskId,
|
|
2271
|
+
batchId,
|
|
2272
|
+
perRepoRoot,
|
|
2273
|
+
laneInfo.repoId,
|
|
2274
|
+
);
|
|
2275
|
+
|
|
2276
|
+
results.push(result);
|
|
2277
|
+
|
|
2278
|
+
if (result.saved) {
|
|
2279
|
+
// Track the saved branch name for caller visibility
|
|
2280
|
+
preservedBranches.add(result.savedBranch!);
|
|
2281
|
+
|
|
2282
|
+
execLog("partial-progress", failedTask.taskId,
|
|
2283
|
+
`Task ${failedTask.taskId} failed but has ${result.commitCount} commit(s) of partial progress on branch ${result.savedBranch}`,
|
|
2284
|
+
{
|
|
2285
|
+
laneBranch: laneInfo.branch,
|
|
2286
|
+
savedBranch: result.savedBranch,
|
|
2287
|
+
commitCount: result.commitCount,
|
|
2288
|
+
repoId: laneInfo.repoId ?? "(default)",
|
|
2289
|
+
},
|
|
2290
|
+
);
|
|
2291
|
+
} else if (result.commitCount > 0 || result.error) {
|
|
2292
|
+
// Preservation FAILED but commits may exist on the lane branch.
|
|
2293
|
+
// Mark this branch as unsafe to reset/delete — doing so would
|
|
2294
|
+
// irreversibly lose the partial work.
|
|
2295
|
+
unsafeBranches.add(laneInfo.branch);
|
|
2296
|
+
|
|
2297
|
+
execLog("partial-progress", failedTask.taskId,
|
|
2298
|
+
`WARNING: Failed to preserve partial progress for task ${failedTask.taskId} ` +
|
|
2299
|
+
`(${result.commitCount} commit(s) at risk on branch "${laneInfo.branch}")`,
|
|
2300
|
+
{
|
|
2301
|
+
laneBranch: laneInfo.branch,
|
|
2302
|
+
commitCount: result.commitCount,
|
|
2303
|
+
error: result.error ?? "unknown",
|
|
2304
|
+
repoId: laneInfo.repoId ?? "(default)",
|
|
2305
|
+
},
|
|
2306
|
+
);
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
return { results, preservedBranches, unsafeBranches };
|
|
2311
|
+
}
|
|
2312
|
+
|
package/package.json
CHANGED
|
@@ -99,7 +99,6 @@ Copy this template when creating a new task. Replace all `[bracketed]` fields.
|
|
|
99
99
|
- [ ] "Check If Affected" docs reviewed
|
|
100
100
|
- [ ] Discoveries logged in STATUS.md
|
|
101
101
|
- [ ] `.DONE` created in this folder
|
|
102
|
-
- [ ] Task archived (auto — handled by task-runner extension)
|
|
103
102
|
|
|
104
103
|
## Documentation Requirements
|
|
105
104
|
|
|
@@ -208,7 +207,6 @@ this from PROMPT.md.
|
|
|
208
207
|
- [ ] "Check If Affected" docs reviewed
|
|
209
208
|
- [ ] Discoveries logged
|
|
210
209
|
- [ ] `.DONE` created
|
|
211
|
-
- [ ] Archive and push
|
|
212
210
|
|
|
213
211
|
---
|
|
214
212
|
|
|
@@ -21,10 +21,38 @@ your verdict. If you don't write the file, your review is lost.
|
|
|
21
21
|
|
|
22
22
|
## Verdict Criteria
|
|
23
23
|
|
|
24
|
-
- **APPROVE** —
|
|
25
|
-
|
|
24
|
+
- **APPROVE** — Step will achieve its stated outcomes. Minor suggestions belong
|
|
25
|
+
in the Suggestions section — they are captured for reference but do NOT block
|
|
26
|
+
progress. **If your only findings are minor or suggestion-level, your verdict
|
|
27
|
+
is APPROVE.**
|
|
28
|
+
- **REVISE** — Step will fail, produce incorrect results, or miss a stated
|
|
29
|
+
requirement without fixes. Use ONLY for issues that would cause the worker to
|
|
30
|
+
need to redo work later if left unaddressed.
|
|
26
31
|
- **RETHINK** — Approach is fundamentally wrong. Explain why and suggest alternative.
|
|
27
32
|
|
|
33
|
+
### When to APPROVE vs REVISE
|
|
34
|
+
|
|
35
|
+
**APPROVE** (with suggestions) when:
|
|
36
|
+
- The approach will work, but you see a cleaner alternative
|
|
37
|
+
- A checkbox could be more specific, but the existing wording covers the outcome
|
|
38
|
+
- Documentation style or STATUS.md formatting could improve
|
|
39
|
+
- You'd suggest additional tests but the core coverage is adequate
|
|
40
|
+
|
|
41
|
+
**REVISE** when:
|
|
42
|
+
- A requirement from PROMPT.md will not be met by the current plan/code
|
|
43
|
+
- A bug or regression is introduced
|
|
44
|
+
- A critical edge case is unhandled and would cause runtime failure
|
|
45
|
+
- Backward compatibility is broken without migration
|
|
46
|
+
|
|
47
|
+
### Do NOT issue REVISE for
|
|
48
|
+
|
|
49
|
+
- Missing checkboxes for work that's already covered by a broader item
|
|
50
|
+
- Splitting a single outcome checkbox into implementation sub-steps
|
|
51
|
+
- STATUS.md cleanup, formatting, or wording preferences
|
|
52
|
+
- "Re-run tests and record the result" — test runs are the worker's concern
|
|
53
|
+
- "Check If Affected" docs that turn out to need no changes
|
|
54
|
+
- Suggestions that improve quality but aren't required for correctness
|
|
55
|
+
|
|
28
56
|
## Plan Review Format
|
|
29
57
|
|
|
30
58
|
Write to the specified output file using the `write` tool:
|
|
@@ -100,6 +128,30 @@ The worker is an LLM with full codebase access — trust it to figure out
|
|
|
100
128
|
implementation specifics. Your job is to catch gaps in **what** needs to happen
|
|
101
129
|
and **why**, not to dictate **how** at the code level.
|
|
102
130
|
|
|
131
|
+
## Checkpoint Granularity Alignment
|
|
132
|
+
|
|
133
|
+
STATUS.md checkboxes represent **meaningful outcomes**, not implementation
|
|
134
|
+
details. A checkbox like "Corrupt state handling (paused + diagnostic)" is a
|
|
135
|
+
single outcome — the worker determines how to achieve it.
|
|
136
|
+
|
|
137
|
+
**Do NOT** request splitting outcome-level checkboxes into implementation
|
|
138
|
+
sub-steps. When adding items via REVISE, only add items that represent genuinely
|
|
139
|
+
**missing outcomes** — things the worker would not have done without your review.
|
|
140
|
+
|
|
141
|
+
Examples:
|
|
142
|
+
|
|
143
|
+
| ❌ Pedantic (don't request) | ✅ Legitimate (request if missing) |
|
|
144
|
+
|---|---|
|
|
145
|
+
| Split "Add retry logic" into 3 checkboxes for timeout, backoff, and counter | "Missing: retry counter must persist across pause/resume" |
|
|
146
|
+
| Add checkbox for "verify types compile" | "Missing: backward compatibility with v2 state files" |
|
|
147
|
+
| Add checkbox for "update STATUS.md formatting" | "Missing: corrupt state should enter paused, not delete" |
|
|
148
|
+
|
|
149
|
+
## Where Findings Go
|
|
150
|
+
|
|
151
|
+
- **critical / important** → Issues Found section → triggers REVISE if blocking
|
|
152
|
+
- **minor / suggestion** → Suggestions section → captured in STATUS.md Notes
|
|
153
|
+
by the worker, **no checkbox created**, does NOT trigger REVISE
|
|
154
|
+
|
|
103
155
|
## Rules
|
|
104
156
|
|
|
105
157
|
- Be specific — reference actual files and line numbers
|
|
@@ -116,13 +116,17 @@ from the next item, combine them.
|
|
|
116
116
|
When a reviewer returns REVISE with specific feedback items:
|
|
117
117
|
|
|
118
118
|
1. **Read the review file** in `.reviews/`
|
|
119
|
-
2. **
|
|
120
|
-
fixes into single checkboxes rather than creating one per reviewer
|
|
121
|
-
|
|
119
|
+
2. **Issues Found items** → add as new checkboxes in the current step. Group
|
|
120
|
+
related fixes into single checkboxes rather than creating one per reviewer
|
|
121
|
+
sentence. These are mandatory — they represent things that would cause
|
|
122
|
+
incorrect results if not addressed.
|
|
123
|
+
3. **Suggestions items** → log in the STATUS.md **Notes** section for reference.
|
|
124
|
+
Do NOT create checkboxes for suggestions. They are advisory, not blocking.
|
|
125
|
+
4. **Commit the hydrated STATUS.md** (see Checkpoint Discipline exceptions):
|
|
122
126
|
```bash
|
|
123
127
|
git add -A && git commit -m "hydrate: add R00N revision items to Step N"
|
|
124
128
|
```
|
|
125
|
-
|
|
129
|
+
5. THEN implement the revisions, checking off each item as you go
|
|
126
130
|
|
|
127
131
|
### Rules
|
|
128
132
|
|