taskplane 0.24.30 → 0.25.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 +41 -48
- package/bin/taskplane.mjs +51 -147
- package/dashboard/public/app.js +32 -18
- package/dashboard/public/style.css +4 -5
- package/dashboard/server.cjs +3 -0
- package/extensions/taskplane/engine-worker.ts +5 -0
- package/extensions/taskplane/engine.ts +160 -6
- package/extensions/taskplane/execution.ts +38 -9
- package/extensions/taskplane/extension.ts +33 -1
- package/extensions/taskplane/lane-runner.ts +46 -1
- package/extensions/taskplane/settings-tui.ts +81 -48
- package/extensions/taskplane/supervisor.ts +74 -40
- package/extensions/taskplane/types.ts +1 -1
- package/extensions/taskplane/waves.ts +108 -2
- package/extensions/taskplane/worktree.ts +114 -0
- package/package.json +1 -1
- package/templates/agents/supervisor.md +1 -1
- package/templates/agents/task-worker.md +7 -0
- package/templates/config/task-orchestrator.yaml +0 -93
- package/templates/config/task-runner.yaml +0 -94
|
@@ -2266,6 +2266,120 @@ export function preserveFailedLaneProgress(
|
|
|
2266
2266
|
}
|
|
2267
2267
|
|
|
2268
2268
|
|
|
2269
|
+
/**
|
|
2270
|
+
* TP-147: Preserve partial progress for all skipped tasks before cleanup/reset.
|
|
2271
|
+
*
|
|
2272
|
+
* Skipped tasks may have worker commits (STATUS.md updates, partial code)
|
|
2273
|
+
* that would be lost when the worktree is cleaned up. This function saves
|
|
2274
|
+
* their lane branches as task-ID-named saved branches, similar to how
|
|
2275
|
+
* preserveFailedLaneProgress works for failed tasks.
|
|
2276
|
+
*
|
|
2277
|
+
* Unlike failed tasks, skipped-task branches are NOT merged (partial work
|
|
2278
|
+
* could break verification). Instead they are preserved for manual recovery.
|
|
2279
|
+
*
|
|
2280
|
+
* @param allocatedLanes - Lanes from the current/last wave
|
|
2281
|
+
* @param taskOutcomes - All task outcomes accumulated so far
|
|
2282
|
+
* @param opId - Operator identifier
|
|
2283
|
+
* @param batchId - Batch ID
|
|
2284
|
+
* @param resolveRepo - Callback to resolve repo root and target branch per repoId
|
|
2285
|
+
* @returns PreserveFailedLaneProgressResult with per-task results and preserved branch set
|
|
2286
|
+
*/
|
|
2287
|
+
export function preserveSkippedLaneProgress(
|
|
2288
|
+
allocatedLanes: AllocatedLane[],
|
|
2289
|
+
taskOutcomes: LaneTaskOutcome[],
|
|
2290
|
+
opId: string,
|
|
2291
|
+
batchId: string,
|
|
2292
|
+
resolveRepo: ResolveRepoContext,
|
|
2293
|
+
): PreserveFailedLaneProgressResult {
|
|
2294
|
+
const results: SavePartialProgressResult[] = [];
|
|
2295
|
+
const preservedBranches = new Set<string>();
|
|
2296
|
+
const unsafeBranches = new Set<string>();
|
|
2297
|
+
|
|
2298
|
+
// Build a map: taskId → { laneBranch, repoId } from allocated lanes
|
|
2299
|
+
const taskToLane = new Map<string, { branch: string; repoId?: string }>();
|
|
2300
|
+
for (const lane of allocatedLanes) {
|
|
2301
|
+
for (const allocatedTask of lane.tasks) {
|
|
2302
|
+
taskToLane.set(allocatedTask.taskId, {
|
|
2303
|
+
branch: lane.branch,
|
|
2304
|
+
repoId: lane.repoId,
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
// Find skipped tasks
|
|
2310
|
+
const skippedTasks = taskOutcomes.filter(
|
|
2311
|
+
(to) => to.status === "skipped",
|
|
2312
|
+
);
|
|
2313
|
+
|
|
2314
|
+
// Track which lane branches we've already processed (a lane may have
|
|
2315
|
+
// multiple tasks; only save once per branch since all commits are shared)
|
|
2316
|
+
const processedBranches = new Set<string>();
|
|
2317
|
+
|
|
2318
|
+
for (const skippedTask of skippedTasks) {
|
|
2319
|
+
const laneInfo = taskToLane.get(skippedTask.taskId);
|
|
2320
|
+
if (!laneInfo) {
|
|
2321
|
+
results.push({
|
|
2322
|
+
saved: false,
|
|
2323
|
+
commitCount: 0,
|
|
2324
|
+
taskId: skippedTask.taskId,
|
|
2325
|
+
error: "Task not found in allocated lanes",
|
|
2326
|
+
});
|
|
2327
|
+
continue;
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
// Skip if we've already processed this branch
|
|
2331
|
+
if (processedBranches.has(laneInfo.branch)) {
|
|
2332
|
+
continue;
|
|
2333
|
+
}
|
|
2334
|
+
processedBranches.add(laneInfo.branch);
|
|
2335
|
+
|
|
2336
|
+
// Resolve repo-specific target branch and repo root
|
|
2337
|
+
const { repoRoot: perRepoRoot, targetBranch } = resolveRepo(laneInfo.repoId);
|
|
2338
|
+
|
|
2339
|
+
const result = savePartialProgress(
|
|
2340
|
+
laneInfo.branch,
|
|
2341
|
+
targetBranch,
|
|
2342
|
+
opId,
|
|
2343
|
+
skippedTask.taskId,
|
|
2344
|
+
batchId,
|
|
2345
|
+
perRepoRoot,
|
|
2346
|
+
laneInfo.repoId,
|
|
2347
|
+
);
|
|
2348
|
+
|
|
2349
|
+
results.push(result);
|
|
2350
|
+
|
|
2351
|
+
if (result.saved) {
|
|
2352
|
+
preservedBranches.add(result.savedBranch!);
|
|
2353
|
+
|
|
2354
|
+
execLog("partial-progress", skippedTask.taskId,
|
|
2355
|
+
`Task ${skippedTask.taskId} was skipped but has ${result.commitCount} commit(s) of partial progress preserved on branch ${result.savedBranch}`,
|
|
2356
|
+
{
|
|
2357
|
+
laneBranch: laneInfo.branch,
|
|
2358
|
+
savedBranch: result.savedBranch,
|
|
2359
|
+
commitCount: result.commitCount,
|
|
2360
|
+
repoId: laneInfo.repoId ?? "(default)",
|
|
2361
|
+
},
|
|
2362
|
+
);
|
|
2363
|
+
} else if (result.commitCount > 0 || result.error) {
|
|
2364
|
+
unsafeBranches.add(laneInfo.branch);
|
|
2365
|
+
|
|
2366
|
+
execLog("partial-progress", skippedTask.taskId,
|
|
2367
|
+
`WARNING: Failed to preserve partial progress for skipped task ${skippedTask.taskId} ` +
|
|
2368
|
+
`(${result.commitCount} commit(s) at risk on branch "${laneInfo.branch}")`,
|
|
2369
|
+
{
|
|
2370
|
+
laneBranch: laneInfo.branch,
|
|
2371
|
+
commitCount: result.commitCount,
|
|
2372
|
+
error: result.error ?? "unknown",
|
|
2373
|
+
repoId: laneInfo.repoId ?? "(default)",
|
|
2374
|
+
},
|
|
2375
|
+
);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
return { results, preservedBranches, unsafeBranches };
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
|
|
2269
2383
|
// ── Stale Branch Cleanup (TP-051) ────────────────────────────────────
|
|
2270
2384
|
|
|
2271
2385
|
/**
|
package/package.json
CHANGED
|
@@ -152,7 +152,7 @@ Use tools **proactively** when the situation calls for it:
|
|
|
152
152
|
- Operator asks to run tasks or start a batch → call `orch_start(target="all")` (or a specific area)
|
|
153
153
|
- Operator asks "how's it going?" → call `orch_status()` first, then summarize
|
|
154
154
|
- Batch paused due to a failure you diagnosed and fixed → call `orch_resume()`
|
|
155
|
-
- Batch completed successfully → offer to call `orch_integrate(mode="pr"
|
|
155
|
+
- Batch completed successfully → offer to call `orch_integrate()` (fast-forward is default and cleanest; use `mode="merge"` if diverged, `mode="pr"` only if remotes exist and branch is protected)
|
|
156
156
|
- Batch is stuck or failing repeatedly → call `orch_status()` to diagnose, then `orch_abort()` if needed
|
|
157
157
|
- Need to investigate before more tasks launch → call `orch_pause()` first
|
|
158
158
|
|
|
@@ -37,6 +37,13 @@ visibility into your progress. If you batch updates, the dashboard shows
|
|
|
37
37
|
7. If all steps are complete, update STATUS.md **Status** field to `✅ Complete`
|
|
38
38
|
and **Current Step** to the last step name — this is your final action
|
|
39
39
|
|
|
40
|
+
## CRITICAL: Do NOT Create .DONE Files
|
|
41
|
+
|
|
42
|
+
**The `.DONE` file is managed by the runtime, not by you.** Never create,
|
|
43
|
+
write, or touch a `.DONE` file. The lane-runner creates it automatically
|
|
44
|
+
when all segments of your task are complete. If you create `.DONE` early,
|
|
45
|
+
it will cause downstream segments to be skipped and deliverables to be lost.
|
|
46
|
+
|
|
40
47
|
## CRITICAL: Never Exit Without Updating STATUS.md
|
|
41
48
|
|
|
42
49
|
**Every turn MUST end with a tool call.** Do NOT produce a text-only response
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# ═══════════════════════════════════════════════════════════════════════
|
|
2
|
-
# Parallel Task Orchestrator Configuration
|
|
3
|
-
# ═══════════════════════════════════════════════════════════════════════
|
|
4
|
-
#
|
|
5
|
-
# Copy this file to `.pi/task-orchestrator.yaml` in your project and
|
|
6
|
-
# customize it. The orchestrator reads BOTH this file and task-runner.yaml.
|
|
7
|
-
#
|
|
8
|
-
# - task-runner.yaml → task areas, reference docs, worker/reviewer
|
|
9
|
-
# - task-orchestrator.yaml → lane count, worktrees, merge, failure policy
|
|
10
|
-
#
|
|
11
|
-
# This template is intentionally conservative so it is safe to adapt to a
|
|
12
|
-
# wide range of repositories.
|
|
13
|
-
# ═══════════════════════════════════════════════════════════════════════
|
|
14
|
-
|
|
15
|
-
# ── Orchestrator Core ─────────────────────────────────────────────────
|
|
16
|
-
|
|
17
|
-
orchestrator:
|
|
18
|
-
# Maximum parallel lanes (worktrees)
|
|
19
|
-
max_lanes: 3
|
|
20
|
-
|
|
21
|
-
# Where to create worktree directories.
|
|
22
|
-
# "sibling" = ../{prefix}-{opId}-{N} (e.g. ../project-wt-alice-1)
|
|
23
|
-
# "subdirectory" = .worktrees/{prefix}-{opId}-{N} (e.g. .worktrees/project-wt-alice-1)
|
|
24
|
-
worktree_location: "subdirectory"
|
|
25
|
-
worktree_prefix: "project-wt"
|
|
26
|
-
|
|
27
|
-
# Batch ID format used in branch names and logs.
|
|
28
|
-
batch_id_format: "timestamp"
|
|
29
|
-
|
|
30
|
-
# Runtime V2 execution backend (subprocess-only)
|
|
31
|
-
spawn_mode: "subprocess"
|
|
32
|
-
|
|
33
|
-
# Prefix for orchestrator session names.
|
|
34
|
-
session_prefix: "orch"
|
|
35
|
-
|
|
36
|
-
# Optional operator identifier for team-scale collision resistance.
|
|
37
|
-
# Auto-detected from OS username if empty. Set explicitly in CI or
|
|
38
|
-
# when multiple operators share the same machine.
|
|
39
|
-
# operator_id: ""
|
|
40
|
-
|
|
41
|
-
# ── Dependency Analysis ───────────────────────────────────────────────
|
|
42
|
-
|
|
43
|
-
dependencies:
|
|
44
|
-
# "prompt" = parse dependencies from PROMPT.md
|
|
45
|
-
# "agent" = use an agent to analyze tasks
|
|
46
|
-
source: "prompt"
|
|
47
|
-
cache: true
|
|
48
|
-
|
|
49
|
-
# ── Lane Assignment ───────────────────────────────────────────────────
|
|
50
|
-
|
|
51
|
-
assignment:
|
|
52
|
-
strategy: "affinity-first"
|
|
53
|
-
size_weights:
|
|
54
|
-
S: 1
|
|
55
|
-
M: 2
|
|
56
|
-
L: 4
|
|
57
|
-
|
|
58
|
-
# ── Pre-warming ───────────────────────────────────────────────────────
|
|
59
|
-
|
|
60
|
-
# Disabled by default. Add commands that fit your stack if you want to use it.
|
|
61
|
-
pre_warm:
|
|
62
|
-
auto_detect: false
|
|
63
|
-
commands: {}
|
|
64
|
-
always: []
|
|
65
|
-
|
|
66
|
-
# ── Merge ─────────────────────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
merge:
|
|
69
|
-
model: "" # empty = inherit from parent pi session
|
|
70
|
-
tools: "read,write,edit,bash,grep,find,ls"
|
|
71
|
-
|
|
72
|
-
# Verification commands to run after each merge.
|
|
73
|
-
# Add only the commands that are safe and relevant for your project.
|
|
74
|
-
verify: []
|
|
75
|
-
|
|
76
|
-
order: "fewest-files-first"
|
|
77
|
-
|
|
78
|
-
# Merge agent timeout in minutes. Increase for large batches with many files.
|
|
79
|
-
timeout_minutes: 90
|
|
80
|
-
|
|
81
|
-
# ── Failure Handling ──────────────────────────────────────────────────
|
|
82
|
-
|
|
83
|
-
failure:
|
|
84
|
-
on_task_failure: "skip-dependents"
|
|
85
|
-
on_merge_failure: "pause"
|
|
86
|
-
stall_timeout: 30
|
|
87
|
-
max_worker_minutes: 30
|
|
88
|
-
abort_grace_period: 60
|
|
89
|
-
|
|
90
|
-
# ── Monitoring ────────────────────────────────────────────────────────
|
|
91
|
-
|
|
92
|
-
monitoring:
|
|
93
|
-
poll_interval: 5
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# ═══════════════════════════════════════════════════════════════════════
|
|
2
|
-
# Task Runner Configuration
|
|
3
|
-
# ═══════════════════════════════════════════════════════════════════════
|
|
4
|
-
#
|
|
5
|
-
# Copy this file to `.pi/task-runner.yaml` in your project and customize it.
|
|
6
|
-
# This template is intentionally generic — replace the example paths, test
|
|
7
|
-
# commands, and task areas with ones that fit your repository.
|
|
8
|
-
# ═══════════════════════════════════════════════════════════════════════
|
|
9
|
-
|
|
10
|
-
# ── Project ───────────────────────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
project:
|
|
13
|
-
name: "Your Project"
|
|
14
|
-
description: "Short description of your project"
|
|
15
|
-
|
|
16
|
-
paths:
|
|
17
|
-
tasks: "tasks"
|
|
18
|
-
architecture: "docs/architecture.md"
|
|
19
|
-
|
|
20
|
-
# ── Verification Commands ─────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
# Add the commands your project uses for validation. Keep only the ones
|
|
23
|
-
# that are relevant to your stack.
|
|
24
|
-
testing:
|
|
25
|
-
commands:
|
|
26
|
-
test: "npm test"
|
|
27
|
-
build: "npm run build"
|
|
28
|
-
lint: "npm run lint"
|
|
29
|
-
|
|
30
|
-
# ── Standards ─────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
standards:
|
|
33
|
-
docs:
|
|
34
|
-
- "README.md"
|
|
35
|
-
- "CONTRIBUTING.md"
|
|
36
|
-
rules:
|
|
37
|
-
- "Keep changes scoped to the task"
|
|
38
|
-
- "Update documentation when behavior changes"
|
|
39
|
-
- "Prefer typed interfaces over unstructured data"
|
|
40
|
-
- "Avoid destructive changes unless explicitly requested"
|
|
41
|
-
|
|
42
|
-
# Per-area standards overrides. Omit or delete if you do not need them.
|
|
43
|
-
standards_overrides: {}
|
|
44
|
-
|
|
45
|
-
# ── Runner Settings ───────────────────────────────────────────────────
|
|
46
|
-
|
|
47
|
-
worker:
|
|
48
|
-
model: "" # empty = inherit from parent pi session
|
|
49
|
-
tools: "read,write,edit,bash,grep,find,ls"
|
|
50
|
-
thinking: "" # empty = inherit from parent pi session
|
|
51
|
-
# spawn_mode: "subprocess" # currently supported runtime mode
|
|
52
|
-
|
|
53
|
-
reviewer:
|
|
54
|
-
model: ""
|
|
55
|
-
tools: "read,write,bash,grep,find,ls"
|
|
56
|
-
thinking: "off"
|
|
57
|
-
|
|
58
|
-
context:
|
|
59
|
-
# worker_context_window: 200000 # 0 or omit = auto-detect from model registry; set explicitly to override
|
|
60
|
-
warn_percent: 85
|
|
61
|
-
kill_percent: 95
|
|
62
|
-
max_worker_iterations: 20
|
|
63
|
-
max_review_cycles: 2
|
|
64
|
-
no_progress_limit: 3
|
|
65
|
-
# max_worker_minutes: 30 # optional wall-clock guard for long worker runs
|
|
66
|
-
|
|
67
|
-
# ── Task Creation / Discovery ─────────────────────────────────────────
|
|
68
|
-
|
|
69
|
-
# Define the task areas that exist in your project.
|
|
70
|
-
task_areas:
|
|
71
|
-
general:
|
|
72
|
-
path: "taskplane-tasks"
|
|
73
|
-
prefix: "TP"
|
|
74
|
-
context: "taskplane-tasks/CONTEXT.md"
|
|
75
|
-
|
|
76
|
-
# Reference docs available for higher-context task prompts.
|
|
77
|
-
reference_docs:
|
|
78
|
-
overview: "README.md"
|
|
79
|
-
architecture: "docs/architecture.md"
|
|
80
|
-
contributing: "CONTRIBUTING.md"
|
|
81
|
-
|
|
82
|
-
# Docs that should never be loaded during task execution.
|
|
83
|
-
never_load:
|
|
84
|
-
- "PROGRESS.md"
|
|
85
|
-
- "HANDOFF-LOG.md"
|
|
86
|
-
|
|
87
|
-
# Self-documentation targets (where agents should log useful discoveries).
|
|
88
|
-
self_doc_targets:
|
|
89
|
-
tech_debt: "CONTEXT.md ## Technical Debt / Future Work"
|
|
90
|
-
|
|
91
|
-
# Docs requiring explicit user approval to modify.
|
|
92
|
-
protected_docs:
|
|
93
|
-
- "docs/"
|
|
94
|
-
- "templates/"
|