taskplane 0.24.2 → 0.24.4

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.
@@ -610,7 +610,7 @@ export const DEFAULT_ORCHESTRATOR_SECTION: OrchestratorSection = {
610
610
  onTaskFailure: "skip-dependents",
611
611
  onMergeFailure: "pause",
612
612
  stallTimeout: 30,
613
- maxWorkerMinutes: 30,
613
+ maxWorkerMinutes: 120,
614
614
  abortGracePeriod: 60,
615
615
  },
616
616
  monitoring: {
@@ -2214,7 +2214,7 @@ export async function executeLaneV2(
2214
2214
  projectName: config.project?.name || "project",
2215
2215
  maxIterations: 20,
2216
2216
  noProgressLimit: 3,
2217
- maxWorkerMinutes: config.failure?.maxWorkerMinutes || 30,
2217
+ maxWorkerMinutes: config.failure?.maxWorkerMinutes || 120,
2218
2218
  warnPercent: 85,
2219
2219
  killPercent: 95,
2220
2220
  onSupervisorAlert,
@@ -286,30 +286,32 @@ export async function executeTaskV2(
286
286
  let iterationTelemetry: Partial<AgentHostResult> = {};
287
287
 
288
288
  const spawned = spawnAgent(hostOpts, undefined, (telemetry) => {
289
- // Context pressure check
290
- if (telemetry.contextUsage) {
291
- const pct = telemetry.contextUsage.percent;
292
- if (pct >= config.warnPercent) {
293
- const msg = `Wrap up (context ${Math.round(pct)}%)`;
294
- if (!existsSync(wrapUpFile)) writeFileSync(wrapUpFile, msg);
295
- }
296
- if (pct >= config.killPercent) {
297
- workerKillReason = "context";
298
- spawned.kill();
289
+ try {
290
+ // Context pressure check
291
+ if (telemetry.contextUsage) {
292
+ const pct = telemetry.contextUsage.percent;
293
+ if (pct >= config.warnPercent) {
294
+ const msg = `Wrap up (context ${Math.round(pct)}%)`;
295
+ if (!existsSync(wrapUpFile)) writeFileSync(wrapUpFile, msg);
296
+ }
297
+ if (pct >= config.killPercent) {
298
+ workerKillReason = "context";
299
+ spawned.kill();
300
+ }
299
301
  }
300
- }
301
302
 
302
- iterationTelemetry = telemetry;
303
- lastTelemetry = telemetry;
304
- // Emit lane snapshot
305
- emitSnapshot(config, taskId, "running", telemetry, statusPath);
303
+ iterationTelemetry = telemetry;
304
+ lastTelemetry = telemetry;
305
+ // Emit lane snapshot
306
+ emitSnapshot(config, taskId, "running", telemetry, statusPath);
307
+ } catch { /* non-fatal: telemetry callback must never crash the engine */ }
306
308
  });
307
309
 
308
310
  // Reviewer telemetry is written by the worker bridge during review_step.
309
311
  // Poll snapshot refresh independently from worker message_end cadence so
310
312
  // the dashboard sees reviewer activity while tool calls are in-flight.
311
313
  const reviewerRefresh = setInterval(() => {
312
- emitSnapshot(config, taskId, "running", iterationTelemetry, statusPath);
314
+ try { emitSnapshot(config, taskId, "running", iterationTelemetry, statusPath); } catch { /* non-fatal */ }
313
315
  }, 1000);
314
316
 
315
317
  let workerResult: AgentHostResult;
@@ -605,6 +607,12 @@ export function readReviewerTelemetrySnapshot(
605
607
  }
606
608
  }
607
609
 
610
+ /**
611
+ * Emit a lane snapshot to disk. NON-THROWING by contract — all errors are
612
+ * caught and logged. This function is called from setInterval callbacks
613
+ * and onTelemetry callbacks where an unhandled throw would trigger
614
+ * uncaughtException and crash the engine-worker process.
615
+ */
608
616
  function emitSnapshot(
609
617
  config: LaneRunnerConfig,
610
618
  taskId: string,
@@ -612,51 +620,56 @@ function emitSnapshot(
612
620
  telemetry: Partial<AgentHostResult>,
613
621
  statusPath: string,
614
622
  ): void {
615
- // Parse progress from STATUS.md
616
- let progress: RuntimeTaskProgress | null = null;
617
623
  try {
618
- const content = readFileSync(statusPath, "utf-8");
619
- const parsed = parseStatusMd(content);
620
- const currentStepMatch = content.match(/\*\*Current Step:\*\*\s*(.+)/);
621
- const checked = parsed.steps.reduce((sum, s) => sum + s.totalChecked, 0);
622
- const total = parsed.steps.reduce((sum, s) => sum + s.totalItems, 0);
623
- progress = {
624
- currentStep: currentStepMatch?.[1]?.trim() || "Unknown",
625
- checked,
626
- total,
627
- iteration: parsed.iteration,
628
- reviews: parsed.reviewCounter,
624
+ // Parse progress from STATUS.md
625
+ let progress: RuntimeTaskProgress | null = null;
626
+ try {
627
+ const content = readFileSync(statusPath, "utf-8");
628
+ const parsed = parseStatusMd(content);
629
+ const currentStepMatch = content.match(/\*\*Current Step:\*\*\s*(.+)/);
630
+ const checked = parsed.steps.reduce((sum, s) => sum + s.totalChecked, 0);
631
+ const total = parsed.steps.reduce((sum, s) => sum + s.totalItems, 0);
632
+ progress = {
633
+ currentStep: currentStepMatch?.[1]?.trim() || "Unknown",
634
+ checked,
635
+ total,
636
+ iteration: parsed.iteration,
637
+ reviews: parsed.reviewCounter,
638
+ };
639
+ } catch { /* best effort */ }
640
+
641
+ const reviewerSnapshot = readReviewerTelemetrySnapshot(config, statusPath);
642
+
643
+ const snapshot: RuntimeLaneSnapshot = {
644
+ batchId: config.batchId,
645
+ laneNumber: config.laneNumber,
646
+ laneId: `lane-${config.laneNumber}`,
647
+ repoId: config.repoId,
648
+ taskId,
649
+ segmentId: null,
650
+ status,
651
+ worker: {
652
+ agentId: buildRuntimeAgentId(config.agentIdPrefix, config.laneNumber, "worker"),
653
+ status: mapLaneSnapshotStatusToWorkerStatus(status),
654
+ elapsedMs: telemetry.durationMs ?? 0,
655
+ toolCalls: telemetry.toolCalls ?? 0,
656
+ contextPct: telemetry.contextUsage?.percent ?? 0,
657
+ costUsd: telemetry.costUsd ?? 0,
658
+ lastTool: telemetry.lastTool ?? "",
659
+ inputTokens: telemetry.inputTokens ?? 0,
660
+ outputTokens: telemetry.outputTokens ?? 0,
661
+ cacheReadTokens: telemetry.cacheReadTokens ?? 0,
662
+ cacheWriteTokens: telemetry.cacheWriteTokens ?? 0,
663
+ },
664
+ reviewer: reviewerSnapshot,
665
+ progress,
666
+ updatedAt: Date.now(),
629
667
  };
630
- } catch { /* best effort */ }
631
-
632
- const reviewerSnapshot = readReviewerTelemetrySnapshot(config, statusPath);
633
-
634
- const snapshot: RuntimeLaneSnapshot = {
635
- batchId: config.batchId,
636
- laneNumber: config.laneNumber,
637
- laneId: `lane-${config.laneNumber}`,
638
- repoId: config.repoId,
639
- taskId,
640
- segmentId: null,
641
- status,
642
- worker: {
643
- agentId: buildRuntimeAgentId(config.agentIdPrefix, config.laneNumber, "worker"),
644
- status: mapLaneSnapshotStatusToWorkerStatus(status),
645
- elapsedMs: telemetry.durationMs ?? 0,
646
- toolCalls: telemetry.toolCalls ?? 0,
647
- contextPct: telemetry.contextUsage?.percent ?? 0,
648
- costUsd: telemetry.costUsd ?? 0,
649
- lastTool: telemetry.lastTool ?? "",
650
- inputTokens: telemetry.inputTokens ?? 0,
651
- outputTokens: telemetry.outputTokens ?? 0,
652
- cacheReadTokens: telemetry.cacheReadTokens ?? 0,
653
- cacheWriteTokens: telemetry.cacheWriteTokens ?? 0,
654
- },
655
- reviewer: reviewerSnapshot,
656
- progress,
657
- updatedAt: Date.now(),
658
- };
659
668
 
660
- writeLaneSnapshot(config.stateRoot, config.batchId, config.laneNumber, snapshot as any);
669
+ writeLaneSnapshot(config.stateRoot, config.batchId, config.laneNumber, snapshot as any);
670
+ } catch {
671
+ // Non-fatal: snapshot is telemetry, not execution-critical.
672
+ // Swallow to prevent uncaughtException crash in setInterval/callback contexts.
673
+ }
661
674
  }
662
675
 
@@ -23,7 +23,7 @@ reviewers), or merge branches (that's merge agents). You supervise all of them.
23
23
 
24
24
  **Your tools:** `read`, `write`, `edit`, `bash`, `grep`, `find`, `ls`. You have
25
25
  full filesystem and command-line access. Use it to read state files, run git
26
- commands, edit batch state, manage tmux sessions, and run verification.
26
+ commands, edit batch state, inspect worker/merge agent execution, and run verification.
27
27
 
28
28
  **Your system prompt** is built from `templates/agents/supervisor.md` (base
29
29
  template, ships with the package) composed with `.pi/agents/supervisor.md`
@@ -43,13 +43,13 @@ You (supervisor) ← operator talks to you
43
43
  │ ├── Computes waves (topological sort)
44
44
  │ ├── Assigns tasks to lanes (parallel execution slots)
45
45
  │ ├── Provisions git worktrees per lane
46
- │ ├── Spawns worker sessions in tmux
46
+ │ ├── Spawns worker processes/sessions per lane
47
47
  │ ├── Polls for .DONE files and STATUS.md progress
48
48
  │ ├── Merges lane branches into orch branch after each wave
49
49
  │ └── Advances to next wave after successful merge
50
50
 
51
51
  ├── Worker Agents (LLM, one per task)
52
- │ ├── Run in tmux sessions inside git worktrees
52
+ │ ├── Run as subprocess agents inside git worktrees
53
53
  │ ├── Read PROMPT.md for requirements, STATUS.md for state
54
54
  │ ├── Write code, run tests, check STATUS.md boxes
55
55
  │ ├── Commit at step boundaries
@@ -216,7 +216,7 @@ Wave N starts
216
216
  ├── 1. Provision: Create lane worktrees from orch branch
217
217
  │ └── git worktree add .worktrees/{opId}-{batchId}/lane-{N} -b task/{opId}-lane-{N}-{batchId} orch/{opId}-{batchId}
218
218
 
219
- ├── 2. Execute: Spawn tmux sessions for each lane
219
+ ├── 2. Execute: Spawn worker sessions for each lane
220
220
  │ ├── Each session runs the task-runner extension
221
221
  │ ├── Task-runner iterates through task steps
222
222
  │ ├── Workers write code, check STATUS.md boxes, commit
@@ -225,7 +225,7 @@ Wave N starts
225
225
 
226
226
  ├── 3. Monitor: Poll loop checks every 5 seconds
227
227
  │ ├── Check .DONE file existence → task succeeded
228
- │ ├── Check tmux session alive → still running
228
+ │ ├── Check lane process/session alive → still running
229
229
  │ ├── Check STATUS.md → track progress for dashboard
230
230
  │ └── Check stall timeout → no STATUS.md change for too long
231
231
 
@@ -250,7 +250,7 @@ Wave N starts
250
250
  | Stage | Failure | Symptom |
251
251
  |-------|---------|---------|
252
252
  | Provision | Stale worktree from previous run | `git worktree add` fails |
253
- | Execute | Worker session crashes | tmux session disappears without .DONE |
253
+ | Execute | Worker session crashes | lane process exits without .DONE |
254
254
  | Execute | Worker makes no progress | STATUS.md unchanged for `stallTimeout` minutes |
255
255
  | Execute | API error (rate limit, overload) | Session exits, pi handles retry internally |
256
256
  | Merge | Merge agent times out | No result JSON within `merge.timeoutMinutes` |
@@ -342,8 +342,8 @@ git log --oneline orch/{branch}..task/{lane-branch} # empty = already merged
342
342
  or "🔒 Merge agent on lane N appears stuck (no output for 20 min)."
343
343
 
344
344
  **How it works:** The merge health monitor (TP-056) actively polls merge agent
345
- tmux sessions every 2 minutes during the merge phase. It checks:
346
- - **Session liveness:** `tmux has-session` — is the session alive?
345
+ processes every 2 minutes during the merge phase. It checks:
346
+ - **Process liveness:** process registry + PID checks — is the agent still alive?
347
347
  - **Activity detection:** Captures the last 10 lines of pane output and compares
348
348
  with the previous snapshot. If output hasn't changed, the session may be stalled.
349
349
 
@@ -354,9 +354,9 @@ tmux sessions every 2 minutes during the merge phase. It checks:
354
354
  - **Stuck** (20 min no output): `merge_health_stuck` event → recommendation to kill
355
355
 
356
356
  **Recovery:**
357
- 1. Attach to the session to inspect: `tmux attach -t {sessionName}`
358
- 2. If truly stuck, kill the session: `tmux kill-session -t {sessionName}`
359
- 3. The engine detects the dead session and applies the `on_merge_failure` policy
357
+ 1. Inspect lane/merge diagnostics: `read_lane_logs(lane)` and recent merge alerts
358
+ 2. If truly stuck, stop the batch/merge path via orchestrator tools (`orch_abort(hard=true)` when required)
359
+ 3. The engine detects the dead agent and applies the `on_merge_failure` policy
360
360
  4. Resume with `/orch-resume` if needed
361
361
 
362
362
  **Note:** The monitor does NOT kill sessions autonomously — it emits events for
@@ -427,7 +427,7 @@ batch terminal.
427
427
 
428
428
  ### Pattern 5: Worker Session Crash
429
429
 
430
- **Symptom:** Task shows failed, tmux session is gone, no `.DONE`.
430
+ **Symptom:** Task shows failed, worker process is gone, no `.DONE`.
431
431
 
432
432
  **Diagnosis:**
433
433
  ```bash
@@ -567,12 +567,12 @@ rm -rf .worktrees/{path}
567
567
  git worktree prune
568
568
  ```
569
569
 
570
- ### Check tmux sessions
571
- ```bash
572
- tmux ls # list all sessions
573
- tmux has-session -t {name} 2>&1 # check specific session
574
- tmux kill-session -t {name} # kill specific session
575
- tmux capture-pane -t {name} -p # see what's on screen
570
+ ### Check active agents
571
+ ```text
572
+ list_active_agents() # list running worker/reviewer/merge agents
573
+ read_agent_status() # summarize STATUS.md + telemetry for all lanes
574
+ read_lane_logs(<lane>) # inspect stderr/crash diagnostics for a lane
575
+ trigger_wrap_up(<lane>) # graceful stop signal for a worker lane
576
576
  ```
577
577
 
578
578
  ---
@@ -774,7 +774,7 @@ If the batch is actively running, call `orch_pause()` first.
774
774
  - `read_agent_status(lane?)` — Read STATUS.md + telemetry for a lane (step, progress, context %, cost, elapsed). Omit lane for all lanes.
775
775
  - `trigger_wrap_up(lane)` — Write `.task-wrap-up` signal to gracefully stop a worker on a lane.
776
776
  - `read_lane_logs(lane)` — Read stderr/crash logs and exit diagnostics for a lane.
777
- - `list_active_agents()` — List all tmux sessions with role, lane, task, context %, elapsed, cost.
777
+ - `list_active_agents()` — List active worker/reviewer/merge agents with role, lane, task, context %, elapsed, cost.
778
778
 
779
779
  Plus general tools: `read`, `write`, `edit`, `bash`, `grep`, `find`, `ls`
780
780
  for inspecting files, running git commands, and editing batch state.
@@ -1010,7 +1010,7 @@ When you activate at the start of a batch:
1010
1010
  2. Note the `orchBranch`, `baseBranch`, `wavePlan`, `totalWaves`
1011
1011
  3. Check that the orch branch exists: `git branch | grep orch/`
1012
1012
  4. Verify worktrees are provisioned for the current wave
1013
- 5. Confirm tmux sessions are alive for active lanes
1013
+ 5. Confirm active worker lanes are alive (agent status + lane logs)
1014
1014
  6. Read configuration for key values: `merge.timeoutMinutes`, `maxLanes`,
1015
1015
  review levels, verification commands
1016
1016
  7. Report to operator: "Batch {batchId} active. {N} waves, {M} tasks.
@@ -1317,8 +1317,7 @@ before writing** — if files already exist (partial setup), read and merge.
1317
1317
  "worktreeLocation": "subdirectory",
1318
1318
  "worktreePrefix": ".worktrees",
1319
1319
  "batchIdFormat": "timestamp",
1320
- "spawnMode": "tmux",
1321
- "tmuxPrefix": "tp",
1320
+ "spawnMode": "subprocess",
1322
1321
  "operatorId": ""
1323
1322
  },
1324
1323
  "dependencies": { "source": "prompt", "cache": true },
@@ -1340,7 +1339,7 @@ before writing** — if files already exist (partial setup), read and merge.
1340
1339
  - `project.name`: Use the actual project name (from package.json, README, etc.)
1341
1340
  - `paths.tasks` and `taskAreas`: Match what was agreed in the task area discussion
1342
1341
  - `testing.commands`: Use the detected test command as a named object (e.g., `{"test": "cd extensions && node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/*.test.ts"}`)
1343
- - `orchestrator.spawnMode`: Use `"tmux"` if tmux is available, `"subprocess"` otherwise
1342
+ - `orchestrator.spawnMode`: Use `"subprocess"` (default, recommended runtime mode)
1344
1343
  - `orchestrator.maxLanes`: Start with 2 for first-time users (safe default)
1345
1344
  - `merge.verify`: Add the project's test command for post-merge verification
1346
1345
 
@@ -1495,8 +1494,8 @@ when the supervisor suggests it.
1495
1494
  5. **Orphaned batch state**: Read `.pi/batch-state.json` — if it exists and
1496
1495
  phase is terminal (`completed`, `failed`, `stopped`), check if it's old
1497
1496
  (> 7 days since `endedAt`) and suggest cleanup
1498
- 6. **tmux availability**: Run `which tmux` if unavailable, warn that
1499
- orchestrator will use subprocess mode (less observable)
1497
+ 6. **Agent observability tools**: Confirm supervisor tool connectivity by checking
1498
+ `orch_status()` and `list_active_agents()` respond without errors
1500
1499
  7. **Disk space**: Run `df -h .` (Unix) or `wmic logicaldisk get size,freespace`
1501
1500
  (Windows) — warn if less than 5GB free (worktrees use space)
1502
1501
  8. **Supervisor lockfile**: Check `.pi/supervisor/lock.json` — if it exists
@@ -1517,7 +1516,7 @@ Infrastructure:
1517
1516
  ✅ Config valid (3 task areas configured)
1518
1517
  ✅ Git clean, on 'develop'
1519
1518
  ⚠️ 2 stale worktree directories from batch 20260315T093012
1520
- tmux available
1519
+ agent observability tools available
1521
1520
  ✅ No orphaned batch state
1522
1521
  ❌ Stale supervisor lockfile found (no active batch)
1523
1522
 
@@ -104,19 +104,19 @@ export const ACTION_CLASSIFICATION_EXAMPLES: Readonly<Record<RecoveryActionClass
104
104
  "Reading batch-state.json, STATUS.md, events.jsonl, merge results",
105
105
  "Running git status, git log, git diff",
106
106
  "Running test suites (node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test ..., etc.)",
107
- "Listing tmux sessions (tmux list-sessions)",
107
+ "Inspecting active agents and lane status (list_active_agents, read_agent_status)",
108
108
  "Checking worktree health (git worktree list)",
109
109
  "Reading any file for diagnostics",
110
110
  ],
111
111
  tier0_known: [
112
- "Restarting a crashed tmux worker session",
112
+ "Triggering graceful wrap-up/retry flow for a stalled worker lane",
113
113
  "Cleaning up stale worktrees for retry",
114
114
  "Retrying a timed-out merge",
115
115
  "Resetting a session name collision",
116
116
  "Clearing a git lock file (.git/index.lock)",
117
117
  ],
118
118
  destructive: [
119
- "Killing a tmux session (tmux kill-session)",
119
+ "Forcing lane/batch termination paths (for example orch_abort(hard=true))",
120
120
  "Editing batch-state.json fields",
121
121
  "Running git reset, git merge, git checkout -B",
122
122
  "Removing worktrees (git worktree remove)",
@@ -2053,7 +2053,7 @@ Use these to:
2053
2053
  - Read batch state, STATUS.md files, merge results, event logs
2054
2054
  - Run git commands for diagnostics and manual merge recovery
2055
2055
  - Edit batch-state.json for state repairs (when needed)
2056
- - Manage tmux sessions (list, kill, attach)
2056
+ - Manage worker lane execution state (agent status, wrap-up, diagnostics)
2057
2057
  - Run verification commands (tests)
2058
2058
 
2059
2059
  ## Standing Orders
@@ -2084,19 +2084,19 @@ Every action you take falls into one of three categories:
2084
2084
  - Reading batch-state.json, STATUS.md, events.jsonl, merge results
2085
2085
  - Running \`git status\`, \`git log\`, \`git diff\`
2086
2086
  - Running test suites (\`node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test ...\`, etc.)
2087
- - Listing tmux sessions (\`tmux list-sessions\`)
2087
+ - Inspecting active agents and lane status (\`list_active_agents\`, \`read_agent_status\`)
2088
2088
  - Checking worktree health (\`git worktree list\`)
2089
2089
  - Reading any file for diagnostics
2090
2090
 
2091
2091
  ### Tier 0 Known (known recovery patterns)
2092
- - Restarting a crashed tmux worker session
2092
+ - Triggering graceful wrap-up/retry flow for a stalled worker lane
2093
2093
  - Cleaning up stale worktrees for retry
2094
2094
  - Retrying a timed-out merge
2095
2095
  - Resetting a session name collision
2096
2096
  - Clearing a git lock file (\`.git/index.lock\`)
2097
2097
 
2098
2098
  ### Destructive (state mutations, irreversible operations)
2099
- - Killing a tmux session (\`tmux kill-session\`)
2099
+ - Forcing lane/batch termination paths (for example \`orch_abort(hard=true)\`)
2100
2100
  - Editing batch-state.json fields
2101
2101
  - Running \`git reset\`, \`git merge\`, \`git checkout -B\`
2102
2102
  - Removing worktrees (\`git worktree remove\`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskplane",
3
- "version": "0.24.2",
3
+ "version": "0.24.4",
4
4
  "description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -38,7 +38,7 @@ Use these to:
38
38
  - Read batch state, STATUS.md files, merge results, event logs
39
39
  - Run git commands for diagnostics and manual merge recovery
40
40
  - Edit batch-state.json for state repairs (when needed)
41
- - Manage tmux sessions (list, kill, attach)
41
+ - Manage worker lane execution state (agent status, wrap-up, diagnostics)
42
42
  - Run verification commands (tests)
43
43
 
44
44
  ## Standing Orders
@@ -69,19 +69,19 @@ Every action you take falls into one of three categories:
69
69
  - Reading batch-state.json, STATUS.md, events.jsonl, merge results
70
70
  - Running `git status`, `git log`, `git diff`
71
71
  - Running test suites (`node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test ...`, etc.)
72
- - Listing tmux sessions (`tmux list-sessions`)
72
+ - Inspecting active agents and lane status (`list_active_agents`, `read_agent_status`)
73
73
  - Checking worktree health (`git worktree list`)
74
74
  - Reading any file for diagnostics
75
75
 
76
76
  ### Tier 0 Known (known recovery patterns)
77
- - Restarting a crashed tmux worker session
77
+ - Triggering graceful wrap-up/retry flow for a stalled worker lane
78
78
  - Cleaning up stale worktrees for retry
79
79
  - Retrying a timed-out merge
80
80
  - Resetting a session name collision
81
81
  - Clearing a git lock file (`.git/index.lock`)
82
82
 
83
83
  ### Destructive (state mutations, irreversible operations)
84
- - Killing a tmux session (`tmux kill-session`)
84
+ - Forcing lane/batch termination paths (for example `orch_abort(hard=true)`)
85
85
  - Editing batch-state.json fields
86
86
  - Running `git reset`, `git merge`, `git checkout -B`
87
87
  - Removing worktrees (`git worktree remove`)