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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskplane",
3
- "version": "0.24.30",
3
+ "version": "0.25.0",
4
4
  "description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -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")` or the operator's preferred mode
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/"