Repository navigation
proposal(channels): Add owner-scoped named sessions for concurrent tasks #10103
Description
Status sync — 2026-09-11
All planned named-session delivery stages have merged into main; the proposal below is retained as the acceptance contract, not a list of unimplemented features.
- Part 1 — Same-chat session-aware delivery: fix(channels): Make same-chat delivery session-aware #10145, merged 2026-08-26.
- Part 2 — Owner-scoped catalog, persistence, and idle-only task selection: feat(channels): Add owner-scoped named sessions #10198, merged 2026-08-27.
- Part 3A — Named-task output attribution: feat(channels): Attribute named task output #10420, merged 2026-08-30.
- Part 3B — Concurrent named-task control: feat(channels): Enable concurrent named task control #10574, merged 2026-08-31.
- Part 4A — Worktree-isolated named tasks: feat(channels): Add worktree-isolated named tasks #10643, merged 2026-09-04.
- Part 4B — Reset the selected task while retaining its worktree: feat(channels): Implement named-session worktree reset (Part 4B) #11015, merged 2026-09-07.
- Follow-up route restoration and owned-worktree deletion: fix(channels): restore worktree-task routes through the managed load path #11308 and feat(cli): reap owned worktrees when daemon sessions are deleted #11309, merged 2026-09-07 and 2026-09-08 respectively; tracked in feat(channels): Worktree session lifecycle cleanup and residual Part 4A findings #11024.
- Maintainer acceptance of the original end-to-end criteria, followed by closure of this delivery tracker. Reconcile existing verification evidence and explicitly record any remaining platform or scenario gaps.
Keep residual worktree lifecycle/recovery work in #11024 rather than treating the merged stages as still pending. In particular, #11024 item 3 (committed-transfer resume and client registration) still needs current-main re-verification before its disposition is decided. Physical worktree cleanup is a follow-up outside this proposal's original MVP scope; it does not change the non-destructive close/reset contract.
This update verifies GitHub merge state and declared delivery scope only; it does not claim a fresh end-to-end acceptance run or close this issue.
中文进度: 同聊天投递、命名目录、输出归属、并发控制、worktree 创建与保留 worktree 的 reset 均已合入 main。下一步是按原验收标准汇总已有证据并补齐明确缺口,而非重复开发;worktree 遗留继续由 #11024 跟踪。
What would you like to be added?
Add an opt-in, owner-scoped named-session mode for daemon-managed Channels so one user can keep multiple independent agent tasks in the same chat and switch between them without discarding prior sessions. Different users in the same group should be able to use the bot concurrently while retaining separate task catalogs and control permissions.
The proposed configuration is:
{
"sessionScope": "user",
"multiSession": true
}sessionScope should continue to define who shares a session. multiSession should independently define whether that owner can retain and select more than one named session. The first version should support only sessionScope: "user" and daemon-managed Channel workers.
User model
The ownership boundary is channelName + chatId + senderId. For example, one group may contain:
Alice: review, feature-a, feature-b
Bob: bugfix, docs
Alice and Bob may use the same task names, but neither user may list, select, cancel, close, approve, or otherwise control the other user's sessions. Session context and control are private to the owner; bot replies in a group remain visible to group members and must not be presented as confidential.
Chat commands
The MVP command surface should be:
/sessions
/sessions all
/session current
/session new <name>
/session new <name> --worktree
/session use <name>
/session cancel [<name>]
/session close <name>
Normal messages go to the currently selected task. /model applies to that task's session. Existing /clear, /new, and /reset reset only the selected named task and do not affect the owner's other tasks.
Task names should use a bounded ASCII slug, be unique case-insensitively within one owner, and never be accepted as a daemon session ID. The MVP should cap each owner at eight open tasks, with the daemon's process-wide limits remaining authoritative.
Concurrency and delivery semantics
After the concurrency phase lands, switching away from a running task must not pause or cancel it. Each session keeps its existing per-session prompt queue. Late foreground responses, background responses, tool updates, permission requests, and user-input cards must retain their originating session and delivery target.
Messages emitted by named sessions should identify their source without adding the label to the persisted transcript. Suggested presentation:
[feature-a] ... # direct chat
[Alice · feature-a] ... # group chat
Bare /approve should resolve only a request for the currently selected task. A request from another running task must require /approve <request-id> or the platform's already-correlated card action. All permission and user-input paths must continue to validate the original owner, session, run, and target.
Persistence and recovery
Introduce a separate versioned managed-session registry rather than changing the existing legacy route-file schema. The registry should persist owner identity, active task name, task name, exact daemon session ID, working directory, isolation mode, open/closed state, and creation/selection timestamps.
The existing active route remains the compatibility pointer for normal message dispatch, while delivery metadata must be retained for every open managed session so an inactive running task can still send results. Management operations for one owner must be serialized and committed through an atomic registry write.
Selecting a dormant task must load and validate the exact persisted session before changing the active pointer. If loading fails, the prior active task remains selected and the unavailable task must not be silently replaced with a fresh session. A newly created daemon session whose ownership record cannot be persisted must be detached and left inaccessible from Channel chat.
When the mode is first enabled, an existing route should be adopted as a task named default without changing its transcript. Closing a task is non-destructive: reject it while a prompt or permission request is active, detach its live client, and retain its transcript and worktree for exact reopening. Neither close nor clear should physically delete a worktree.
Worktree isolation
The daemon already supports isolated worktree session creation. Channel session creation should forward that option for /session new <name> --worktree, generate a collision-resistant slug that does not expose raw sender identifiers, and persist the actual working directory reported by the daemon session.
Shared-working-directory sessions remain useful for review and other non-mutating work, but the task list and creation acknowledgement must identify them as shared. Concurrent feature development should be documented with --worktree. Worktrees start from committed repository state and do not implicitly copy uncommitted changes.
MVP compatibility constraints
Fail configuration or task creation closed when an unsupported combination is requested:
multiSessionwith a scope other thanuser;- standalone
qwen channel startuntil its normal-shutdown cleanup contract is redesigned; - non-zero channel or group
groupHistoryLimit, because ambient group history is not task-scoped; - Channel webhooks, because their target currently has no managed task identity;
- Channel loops, because persisted loop jobs currently re-resolve the active route and could drift after a task switch.
Channel memory remains intentionally channel/chat-scoped and shared across named tasks; it must not be used as the task ownership registry.
Why is this needed?
The current Channel router retains one current session for each routing key. With sessionScope: "user", the same user can have separate sessions in different chats, but only one selectable session in a given chat. /new, /clear, and /reset start fresh by removing the current route; they do not retain an owner-visible catalog for later selection, and there is no chat-side /sessions command.
Platform threads with sessionScope: "chat_thread" provide independent contexts, but those contexts are shared by participants in the thread and therefore do not solve private per-user task switching in one group. The daemon's session catalog is also insufficient as a chat ownership index: it can filter creation source by Channel instance, but it does not encode the Channel sender and managed task name needed for safe listing and control.
A practical personal workflow routinely needs independent long-lived contexts: one task reviewing a change while two isolated tasks develop separate features, each with its own model, transcript, status, cancellation, permissions, and follow-up conversation. Background subagents can parallelize one parent task, but they are not a substitute for persistent, independently selectable sessions.
Additional context
Current source audit baseline: 5cff52c6e856e6528408863d83eb36eba6058b14.
Proposed delivery plan and estimated size
Exclude generated files, lockfiles, and snapshots from these estimates. Total diff means additions plus deletions; estimates have roughly 30% uncertainty.
| Part | Scope | Production | Tests | Docs | Estimated total diff |
|---|---|---|---|---|---|
| 1 | Make same-chat platform delivery session-aware | 120–220 | 250–450 | 0–30 | 400–700 |
| 2 | Add named-session catalog, ownership, persistence, idle-only selection, and migration | 650–950 | 800–1,300 | 100–180 | 1,550–2,400 |
| 3 | Allow switching while tasks run; add named cancellation, permission correlation, and result labels | 250–450 | 500–800 | 50–100 | 800–1,350 |
| 4 | Forward daemon worktree creation and verify isolated concurrent development | 180–300 | 300–550 | 80–150 | 600–1,000 |
Part 1 is an independently useful correctness fix for existing same-chat sessions. Part 2 should initially reject switching away from an active task, giving it a complete and safe intermediate contract. Part 3 removes that guard only after delivery and permission behavior is session-aware. Part 4 completes the intended concurrent feature-development workflow.
Acceptance criteria
- Two users in the same group can independently create, list, select, model-switch, clear, cancel, close, and reopen their own named tasks.
- One user can run at least three tasks concurrently; switching the active task does not cancel or redirect earlier work.
- Results and permission requests remain correlated to their originating owner and task after subsequent messages and switches.
- A user cannot control another user's task by knowing its name or daemon session ID.
- Restart restores task names and exact sessions lazily; a failed load leaves the prior active task unchanged.
- Existing single-route behavior is unchanged when
multiSessionis absent or false. - Unsupported group history, webhook, loop, scope, and standalone combinations fail closed with actionable messages.
- Platform adapter tests cover same-chat concurrent sessions, including passive reply correlation and activity-indicator cleanup.
- Worktree tasks use distinct working directories, survive daemon restart, and are not physically deleted by close or clear.
- Focused package tests, build, typecheck, lint, and daemon-backed Channel E2E tests pass for each delivery part.
Out of scope for the MVP
- Shared/collaborative named sessions controlled by several group members.
/session send <name> <prompt>direct dispatch without selecting first.- Task-targeted Channel webhooks or loops.
- Standalone Channel persistence.
- Automatic worktree deletion, branch integration, or destructive cleanup.
- Exposing the daemon-wide Channel session catalog directly to chat users.
Activity
docs(channels): Add named sessions Part 4B design
docs(channels): Add named sessions Part 4B design
docs(channels): Add named sessions Part 4B design
docs(channels): Add named sessions Part 4B design
feat(channels): Implement named-session worktree reset (Part 4B) (Qwe…
doudouOUC commentedon Sep 11, 2026
Closing as completed for the original owner-scoped named-session delivery plan. All planned stages are merged into main: #10145, #10198, #10420, #10574, #10643, and #11015. Follow-up route restoration and worktree cleanup landed in #11308 and #11309. Residual worktree lifecycle/recovery work remains tracked in #11024, including current-main re-verification of its third item; this closure does not mark that residual resolved. This closure is based on existing merged delivery records; no new end-to-end acceptance run was performed for this status reconciliation.