#18962: feat: add priority preemption — heartbeat lane separation
docs
gateway
cli
agents
size: M
Cluster:
Session Management Enhancements
## Summary
- Route heartbeat runs to a dedicated `heartbeat` lane so they never block human messages on the main lane
- Controlled by a new config toggle: `messages.queue.priorityPreemption` (default: `false`)
- When disabled, all behavior is identical to before; when enabled, heartbeats get their own lane with concurrency 1
## Changes
7 lines of logic across 6 files:
1. **`src/process/lanes.ts`** — add `CommandLane.Heartbeat` to lane enum
2. **`src/config/types.messages.ts`** — add `priorityPreemption` to `QueueConfig` type
3. **`src/config/zod-schema.core.ts`** — add schema validation for the new config field
4. **`src/gateway/server-lanes.ts`** — configure heartbeat lane concurrency (1) at gateway startup
5. **`src/auto-reply/reply/agent-runner-execution.ts`** — route heartbeat agent runs to heartbeat lane when enabled
6. **`src/infra/heartbeat-runner.ts`** — heartbeat runner checks its own lane instead of main when enabled
Plus: lint fix for unused vars in `command-queue.test.ts`, changelog entry, and doc updates to queue and heartbeat pages.
## Test plan
- [x] All 12 command queue tests pass (lane isolation, concurrency, clearLane, error recovery, default routing)
- [x] All 20 heartbeat core tests pass
- [x] All 38 heartbeat runner tests pass
- [x] 2/2 queue followup tests pass
- [x] 2/2 config validation tests pass
- [x] Lint clean on all changed files
- [x] Type-check clean on all changed files
- [x] Live tested on gateway with `priorityPreemption: true` enabled — heartbeats routed to dedicated lane, human messages unblocked
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds opt-in heartbeat lane separation via `messages.queue.priorityPreemption` config toggle. When enabled, heartbeat runs route to a dedicated `CommandLane.Heartbeat` lane (concurrency 1) instead of sharing the `main` lane with human messages, preventing heartbeats from blocking real user interactions for 30-60+ seconds.
- Adds `Heartbeat` to `CommandLane` enum, `priorityPreemption` to config type + Zod schema
- `server-lanes.ts` unconditionally sets heartbeat lane concurrency to 1 (negligible cost when unused)
- `agent-runner-execution.ts` routes heartbeat runs to the heartbeat lane when enabled; `undefined` correctly falls through to `main` via `resolveGlobalLane()`
- `heartbeat-runner.ts` checks the heartbeat lane (not main) for capacity when preemption is ON, ensuring human messages on main don't cause heartbeats to unnecessarily skip
- Test file adds comprehensive safety-net tests for lane isolation, concurrency, `clearCommandLane`, `getTotalQueueSize`, error recovery, and default routing
- PR also bundles unrelated new skill files and design documents
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — the feature is opt-in (default `false`), minimal in scope, and well-tested.
- The core logic is 7 lines across 6 files, all guarded behind an opt-in config flag. When disabled, behavior is identical to before. The lane routing flows correctly through the existing `resolveGlobalLane` → `enqueueCommandInLane` pipeline. The queue size check in `heartbeat-runner.ts` is consistent with where heartbeats are actually enqueued. New tests cover the underlying lane infrastructure. No security concerns, no breaking changes, no regressions when the feature is off.
- No files require special attention. All changes are straightforward and well-documented.
<sub>Last reviewed commit: c581e40</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#21851: fix: drain pending system events when main command lane goes idle
by alan-purring · 2026-02-20
78.8%
#19270: fix: retry event-driven heartbeats blocked by requests-in-flight
by deggertsen · 2026-02-17
73.6%
#12786: fix: drop heartbeat runs that arrive while another run is active
by mcaxtr · 2026-02-09
73.0%
#10644: feat: add runDuringHeartbeats option for memory flush (AI Assisted)
by tripphillips · 2026-02-06
73.0%
#16373: fix: suppress leaked heartbeat poll prompts in reply delivery
by luisecab · 2026-02-14
72.9%
#6689: Fix: auto-remove idle session lanes to prevent unbounded command qu...
by kamb5686 · 2026-02-01
72.9%
#21014: fix(cron): suppress main-session summary for HEARTBEAT_OK responses
by nickjlamb · 2026-02-19
72.8%
#11647: fix(webchat): filter HEARTBEAT_OK messages from chat.history response
by liuxiaopai-ai · 2026-02-08
72.4%
#17583: feat(heartbeat): add agentId to route default heartbeat to a specif...
by scottgl9 · 2026-02-15
72.2%
#16321: Fix #12767: suppress HEARTBEAT_OK leakage in Telegram DM replies
by tdjackey · 2026-02-14
72.2%