Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cf7691e
docs(channels): Add named sessions Part 4B design
doudouOUC Sep 4, 2026
b75c833
docs(channels): address self-review of Part 4B design
doudouOUC Sep 4, 2026
c859434
docs(channels): revise Part 4B design after review
doudouOUC Sep 4, 2026
7def764
docs(channels): address round-2 review of Part 4B design
doudouOUC Sep 4, 2026
17e1f32
docs(channels): link Part 4B dispositions to follow-up issue #11024
doudouOUC Sep 4, 2026
1983508
fix(channels): resolve residual worktree session defects from #10643
doudouOUC Sep 4, 2026
9edf073
docs(channels): address round-3 review of Part 4B design
doudouOUC Sep 4, 2026
2f465d7
fix(channels): harden marker cleanup and parser guard per round-4 review
doudouOUC Sep 4, 2026
c4f71fd
docs(channels): address round-4/5 review of Part 4B design
doudouOUC Sep 4, 2026
fc180af
feat(channels): reset worktree tasks by transferring checkout ownership
doudouOUC Sep 5, 2026
87f028d
docs(channels): correct the R8-1 rollback rationale in the Part 4B de…
doudouOUC Sep 5, 2026
4b3ef6a
fix(channels): register loop tools for a worktree reset replacement
doudouOUC Sep 5, 2026
928189f
docs: align worktree-reset error taxonomy names with the implementation
doudouOUC Sep 5, 2026
4654521
fix(cli): register the worktree-reset route and tag in the contract s…
doudouOUC Sep 5, 2026
4d8ee0e
fix(cli): update the telemetry route catalog audit counts for worktre…
doudouOUC Sep 5, 2026
4276656
fix(channels): address round-3 review of the worktree reset implement…
doudouOUC Sep 5, 2026
6580fa6
test: pin the worktree transfer invariants round 3 left uncovered
doudouOUC Sep 5, 2026
e65c3ab
fix: address round-4 review of the worktree reset transfer
doudouOUC Sep 6, 2026
31040f1
fix: address round-5 review of the worktree reset transfer
doudouOUC Sep 6, 2026
e4a460b
Merge branch 'main' into docs/channel-named-sessions-part4b
wenshao Sep 7, 2026
8539ec3
Merge remote-tracking branch 'origin/main' into docs/channel-named-se…
doudouOUC Sep 7, 2026
587d519
docs: mark supersededSessionLive as diagnostic-only
doudouOUC Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,434 changes: 1,434 additions & 0 deletions docs/design/channel-named-sessions-part4b.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/developers/daemon/00-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Use these anchors when moving from the docs into the latest `main` code:
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| HTTP routes | The route catalog lives in `qwen-serve-protocol.md`; this daemon set only references it and explains implementation ownership. | [`../qwen-serve-protocol.md`](../qwen-serve-protocol.md), [`20`](./20-quickstart-operations.md) |
| Event schema | `EVENT_SCHEMA_VERSION = 1`; 53 known event types; id-less subscriber synthetic frames; `_meta.serverTimestamp` stamped by `EventBus.publish()` (with `formatSseFrame()` fallback for synthetic frames). | [`09`](./09-event-schema.md), [`10`](./10-event-bus.md) |
| Capabilities | `SERVE_PROTOCOL_VERSION = 'v1'`; 157 registered tags; 45 conditional tags. | [`11`](./11-capabilities-versioning.md) |
| Capabilities | `SERVE_PROTOCOL_VERSION = 'v1'`; 158 registered tags; 45 conditional tags. | [`11`](./11-capabilities-versioning.md) |
| Session shell | `POST /session/:id/shell` exists behind `--enable-session-shell`, bearer or trusted-loopback authority, and session-bound `X-Qwen-Client-Id`; capability tag is conditional. | [`11`](./11-capabilities-versioning.md), [`17`](./17-configuration.md), [`20`](./20-quickstart-operations.md) |
| Rate limiting | Optional per-tier HTTP rate limit is exposed by CLI flags/env and conditional capability tag. | [`11`](./11-capabilities-versioning.md), [`17`](./17-configuration.md) |

Expand Down
4 changes: 3 additions & 1 deletion docs/developers/daemon/08-session-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ Both:
1. Use a per-session `pendingRestoreIds` set on the channel so concurrent restore calls coalesce (`RestoreInProgressError`).
2. Cache `restoreState` on the entry so a late attacher gets the same payload the original restorer did.

For a persisted Part 4A worktree session, restore is an integrity-gated extension of this lifecycle. The sidecar identifies the requested workspace root explicitly, the checkout must be canonically contained below the corresponding `.qwen/worktrees/` directory, and its marker must be a single-link regular file containing the exact restored session ID. The daemon relocates an idle restored child only after those checks; an active child is accepted only when its reported cwd already equals the worktree. Those responses return canonical worktree metadata with `worktreeState: "persisted-v1"`. A cold restore that reports an active prompt without a current cwd returns unverified worktree metadata without that attestation, so isolation-aware clients reject it and may retry after the prompt settles. Invalid Part 4A state detaches an existing attachment or kills a cold restore with `requireZeroAttaches`; a missing sidecar likewise yields no attestation. Whenever the effective restore source is Channel-owned, the route suppresses the ACP agent's best-effort cleanup for Part 4A or unclassifiable sidecar state, so validation failure preserves the uncertain checkout evidence. Persisted source metadata takes precedence; when it is absent, the load/resume request supplies the effective source. A structurally valid legacy sidecar without `workspaceCwd` instead retains the existing best-effort agent restore: it must identify either the requested workspace root or its Git repository top-level, is containment-checked without marker attestation, may be cleaned up by the agent, and may return `worktree` without `worktreeState`. Apart from that explicit legacy compatibility case, only sessions whose effective restore source is not Channel-owned retain the existing best-effort cleanup before route validation.
For a persisted Part 4A worktree session, restore is an integrity-gated extension of this lifecycle. The sidecar identifies the requested workspace root explicitly, the checkout must be canonically contained below the corresponding `.qwen/worktrees/` directory, and its marker must be a single-link regular file containing the exact restored session ID. The daemon relocates an idle restored child only after those checks; an active child is accepted only when its reported cwd already equals the worktree, and an active child whose reported cwd is absent or elsewhere fails closed instead of being relocated under its prompt — except for a cold restore that could not defer its restore-prompt (`suppressWorktreeContextRestore` off, so the bridge fired the re-hung question instead of parking it): that shape keeps the pre-4B outcome, returning canonical worktree metadata without `worktreeState`, unrelocated, with the session surviving. The relocated and accepted responses return canonical worktree metadata with `worktreeState: "persisted-v1"`. A sidecar carrying `supersededBy` never restores: the route returns `409 worktree_session_superseded` with the replacement session id, a classification decided from that link alone before any marker read, so callers redirect and heal their bookkeeping only once a load of that id has succeeded — a pre-commit interrupted transfer names a replacement that is not the marker owner, cannot itself be restored, and is reaped by the retried reset; a restored replacement whose `supersedes` link agrees with the old sidecar while the marker never moved — or is absent — returns `409 worktree_reset_interrupted`, whose repair is retrying the reset against the superseded session; and a missing marker without that agreeing link pair returns `409 worktree_marker_missing`, whose repair is resetting the task rather than retrying the restore, because no restore path recreates a marker. The interrupted classification is checked first. Invalid Part 4A state detaches an existing attachment or kills a cold restore with `requireZeroAttaches`; a missing sidecar likewise yields no attestation. Whenever the effective restore source is Channel-owned, the route suppresses the ACP agent's best-effort cleanup for Part 4A or unclassifiable sidecar state, so validation failure preserves the uncertain checkout evidence. Persisted source metadata takes precedence; when it is absent, the load/resume request supplies the effective source. A structurally valid legacy sidecar without `workspaceCwd` instead retains the existing best-effort agent restore: it must identify either the requested workspace root or its Git repository top-level, is containment-checked without marker attestation, may be cleaned up by the agent, and may return `worktree` without `worktreeState`. Apart from that explicit legacy compatibility case, only sessions whose effective restore source is not Channel-owned retain the existing best-effort cleanup before route validation.

Worktree ownership transfer (`POST /session/:id/worktree-reset`, advertised by `session_worktree_reset_v1`) extends this lifecycle for Channel task resets: the daemon spawns a fresh thread-scoped replacement in the root workspace, relocates it into the verified checkout, links the sidecar pair (`supersededBy` on the old session first, then `supersedes` on the replacement), flips the marker to the replacement under a per-checkout route lock and an admission barrier that fences prompt admission plus the seven other writers that start work in the checkout or move the session cwd (rewind, cwd change, branch, fork, shell, goal control, workflow-task action), while the release and stop paths stay unfenced by design, and then severs the superseded session's client registrations and in-memory worktree association. The sever reports whether the superseded session is actually gone: a survivor whose child still holds background work keeps the barrier armed, is logged, and is reported to the caller as `supersededSessionLive: true` rather than being papered over by the success response. A fenced writer admitted on the superseded session mid-transfer is refused with `409 worktree_reset_active`; the full failure taxonomy, including which crash windows a retry rolls back and which fail closed for operator repair, is documented with the route in `qwen-serve-protocol.md`.

### Heartbeat

Expand Down
Loading
Loading