docs(daemon): align adapter spikes with web-first roadmap#4296
Conversation
📋 Review SummaryThis PR updates three daemon adapter documentation files (TUI, channel-web, IDE) to align with the web-first daemon roadmap established in the 2026-05-19 architecture decision. The changes reframe these adapters from "default migration candidates" to "historical/future reference spikes" while keeping native TUI and ACP-based IDE/channel paths as defaults. The documentation is clear, well-structured, and correctly reflects the current architectural direction. 🔍 General Feedback
🎯 Specific Feedback🔵 Low
✅ Highlights
|
wenshao
left a comment
There was a problem hiding this comment.
One additional suggestion could not be anchored inline because the relevant unchanged line is outside GitHub's diff hunk:
[Suggestion] In docs/developers/daemon-client-adapters/channel-web.md, the minimal channel flow should prefer the session-scoped permission route for multi-user daemon adapters. The SDK exposes session.respondToSessionPermission(), and the daemon advertises it via caps.features.session_permission_vote; using the session-scoped route keeps permission votes tied to the daemon session that emitted the request and avoids future implementers copying a less isolated pattern into channel/web deployments. Suggested wording: Cast permission votes through session.respondToSessionPermission() when caps.features.session_permission_vote is advertised; use the legacy request-id route only for explicitly single-user or older-daemon fallback.
— gpt-5.5 via Qwen Code /review
wenshao
left a comment
There was a problem hiding this comment.
[Suggestion] ide.md:62 — "yet" retained but removed from the other 2 files
The PR edited the "not wired" sentence in all 3 files but applied inconsistent fixes:
tui.md:64: removed "yet" entirelychannel-web.md:89: replaced "yet" with "by default"ide.md:62: left "yet" unchanged ("It is not wired into the defaultQwenAgentManagerpath yet")
"Yet" implies default migration is still the intended endpoint, contradicting the spike framing.
Suggested fix: Change to "It is not wired into the default QwenAgentManager path. Existing VS Code behavior remains ACP subprocess based."
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
| existing ACP subprocess behavior by default; daemon channel integration remains | ||
| future / behind-flag evaluation. | ||
|
|
||
| This draft covers server-side clients only: |
There was a problem hiding this comment.
[Critical] The title was changed from "Draft" to "Spike" but this line still reads "This draft covers server-side clients only". Internal inconsistency within the same file.
| This draft covers server-side clients only: | |
| This document covers server-side clients only: |
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
| ## Proposed Entry Points | ||
|
|
||
| Channel backend: | ||
| Historical channel backend experiment: |
There was a problem hiding this comment.
[Critical] The section header ## Proposed Entry Points (line 21 above) was not renamed to match the spike framing. The other 2 files both use ## Historical Experimental Entry Point. This subsection text was correctly updated to "Historical channel backend experiment:" but the parent heading was missed.
Suggested fix: Rename line 21 to ## Historical Experimental Entry Points (plural, since this file covers two entry points).
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
| `DaemonSessionClient` instead of creating an in-process `Config` + agent | ||
| runtime. | ||
| Document the default-off `DaemonTuiAdapter` spike that was added while | ||
| evaluating Mode B client integration. |
There was a problem hiding this comment.
[Critical] "Mode B" is retained here but all other "Mode B" references were removed from ide.md and channel-web.md by this PR. It is now an orphaned term, undefined anywhere in the doc set. A reader encountering this file for the first time has no way to understand what "Mode B" refers to.
| evaluating Mode B client integration. | |
| evaluating daemon-backed client integration. |
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
| daemon setting level. Until per-request `sessionScope` lands, multi-user channel | ||
| or web deployments must choose one of these safe shapes: | ||
| Multi-user channel or web deployments must explicitly isolate sessions. Use | ||
| per-request `sessionScope: 'thread'` when supported; otherwise choose one of |
There was a problem hiding this comment.
[Suggestion] The old text explicitly stated "Current daemon Stage 1 behavior is effectively sessionScope: single at the daemon setting level". This PR replaced it with "when supported" — a hedge that obscures whether sessionScope: 'thread' actually exists at the daemon server level (code search shows sessionScope type exists in channels but the daemon server core has zero references to it).
Suggested fix: Restore the diagnostic: "As of this spike, the daemon does not support per-request sessionScope. Until it does, multi-user deployments must choose one of these isolation shapes:"
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
| Document the default-off `DaemonChannelBridge` spike for server-side channel | ||
| and web backends. | ||
|
|
||
| As of the 2026-05-19 architecture decision, web chat / web terminal are the |
There was a problem hiding this comment.
[Suggestion] All 3 files add "As of the 2026-05-19 architecture decision" but no ADR, design doc, or decision record exists in the repository for this date. Future readers have no way to verify what this decision entailed, who made it, or whether it has since been superseded.
Suggested fix: Add an ADR in .qwen/design/, link to the relevant GitHub discussion, or soften the reference (e.g., "As of a May 2026 architecture direction...").
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
| - Smoke-test browser -> BFF -> daemon without exposing daemon token. | ||
|
|
||
| ## Blockers Before Default Migration | ||
| ## Current Follow-Up Direction |
There was a problem hiding this comment.
[Suggestion] The old "Blockers Before Default Migration" sections across all 3 files were explicit checklists of hard prerequisites (session-scoped permission route, daemon-stamped client identity, FileSystemService boundary, session lifecycle close/delete). The new "Current Follow-Up Direction" prose mentions these concepts vaguely, losing the gating semantics. A future implementer scanning the doc will not see a clear stop-sign.
Suggested fix: Add a brief "Security Prerequisites" subsection within this section listing the unresolved security items (client identity, session-scoped permission, filesystem boundary).
— qwen-latest-series-invite-beta-v28 via Qwen Code /review
b3c56db to
5cd64d5
Compare
5cd64d5 to
7430e5d
Compare
|
Handled the valid review items and the low-risk documentation polish in the same follow-up:
Generated by GPT-5 Codex |
|
@chiga0 thanks for recording the web-first pivot here — looking at it from the F3 side (PR #4335 just merged 2026-05-20 11:13Z, merge commit
I've updated issue #4175 to reflect the pivot:
The optional render-core extraction you mention (so native TUI + web terminal share view-model / rendering without forcing native TUI through daemon HTTP) is captured in F4 (3) as a follow-up. Happy to help on that or on web-side review if useful — F3's Approving the doc direction. Want me to also rebase #4296 onto current |
| 6. Route cancel through `session.cancel()`. | ||
| 7. Route model switch through `session.setModel()`. | ||
| 8. Route permission votes through `session.respondToPermission()`. | ||
| 8. Route permission votes through `session.respondToSessionPermission()` when |
There was a problem hiding this comment.
[Suggestion] The new permission-routing guidance says TUI should call session.respondToSessionPermission(), but the actual DaemonTuiAdapter implementation still calls session.respondToPermission() in both approve/reject paths. IDE and channel currently do the same in their adapter implementations, but those two docs hedge this as future/behind-flag evaluation; the TUI doc keeps describing a concrete experimental flow. That makes the spike doc look already aligned with the session-scoped permission route when the adapter code is not.
| 8. Route permission votes through `session.respondToSessionPermission()` when | |
| 8. Route permission votes through the legacy request-id permission route today; | |
| migrate to `session.respondToSessionPermission()` once the adapter is updated | |
| to gate on `caps.features.session_permission_vote`. |
— gpt-5.5 via Qwen Code /review
wenshao
left a comment
There was a problem hiding this comment.
[Suggestion] Undefined gating dependency: "web contract" is referenced as a prerequisite in both channel-web.md and ide.md "Current Follow-Up Direction" sections, but is never defined anywhere in the repository. Future readers have no way to know what this entails, who owns it, or when it will land. Consider defining it inline or linking to the relevant design doc / ADR.
[Suggestion] Inconsistent phase breakdown across the 3 "Current Follow-Up Direction" sections: ide.md uses numbered phases (1. web contract → 2. editor-context routing → 3. control-plane parity), while channel-web.md and tui.md use different natural-language groupings with different concepts (runtime diagnostics, session lifecycle semantics, shared terminal render core). A reader reconciling these into a unified roadmap will find conflicting structures with no single source of truth.
— DeepSeek/deepseek-v4-pro via Qwen Code /review
| @@ -16,13 +20,13 @@ The daemon currently rejects browser `Origin` requests by design. | |||
|
|
|||
| ## Proposed Entry Points | |||
|
|
|||
There was a problem hiding this comment.
[Suggestion] "Proposed historical channel backend experiment" — "Proposed" (forward-looking) contradicts "historical" (past). Something cannot be simultaneously proposed for the future and consigned to history. The intent appears to be describing this as a historical reference, so the word "Proposed" should be removed.
| Historical channel backend experiment, not a wired command today: |
— DeepSeek/deepseek-v4-pro via Qwen Code /review
| 5. Send final text back through the platform adapter. | ||
| 6. Cast permission votes through `session.respondToPermission()`. | ||
| 6. Cast permission votes through `session.respondToSessionPermission()` when | ||
| `caps.features.session_permission_vote` is advertised; use the legacy |
There was a problem hiding this comment.
[Suggestion] "use the legacy request-id route" — the legacy method (respondToPermission) is never explicitly named. A maintainer unfamiliar with the permission API evolution (respondToPermission → respondToSessionPermission) must grep the codebase to find the correct fallback. Consider naming it explicitly.
| `caps.features.session_permission_vote` is advertised; use the legacy | |
| use the legacy `respondToPermission` request-id route only for explicitly single-user or older-daemon fallback. |
— DeepSeek/deepseek-v4-pro via Qwen Code /review
| 7. Route cancel/model switch through `session.cancel()` and | ||
| `session.setModel()`. | ||
| 8. Route permission decisions through `session.respondToPermission()`. | ||
| 8. Route permission decisions through `session.respondToSessionPermission()` |
There was a problem hiding this comment.
[Suggestion] The permission-routing guidance says "when advertised; fall back to the legacy permission route" but does not name the capability key (caps.features.session_permission_vote) that channel-web.md explicitly documents. An IDE adapter implementer reading only this file would not know which capability flag to check. Add the exact key for consistency across the doc set.
| 8. Route permission decisions through `session.respondToSessionPermission()` | |
| Route permission decisions through `session.respondToSessionPermission()` | |
| when `caps.features.session_permission_vote` is advertised; fall back to the legacy `respondToPermission` route only for older daemons. |
— DeepSeek/deepseek-v4-pro via Qwen Code /review
| 6. Route cancel through `session.cancel()`. | ||
| 7. Route model switch through `session.setModel()`. | ||
| 8. Route permission votes through `session.respondToPermission()`. | ||
| 8. Route permission votes through `session.respondToSessionPermission()` when |
There was a problem hiding this comment.
[Suggestion] Same capability-key gap as ide.md: the permission-routing guidance omits the exact capability flag caps.features.session_permission_vote that channel-web.md documents. Add it for cross-file consistency.
| 8. Route permission votes through `session.respondToSessionPermission()` when | |
| Route permission votes through `session.respondToSessionPermission()` when | |
| `caps.features.session_permission_vote` is advertised; fall back to the legacy `respondToPermission` route only for older daemons. |
— DeepSeek/deepseek-v4-pro via Qwen Code /review
|
|
||
| Unknown events must be ignored, not fatal. Typed event reducers will land in a | ||
| later protocol PR. | ||
| Unknown events must be ignored, not fatal. Typed event reducers should stay in |
There was a problem hiding this comment.
[Suggestion] "Typed event reducers should stay in the daemon client/protocol layer, not in server internals" — this is a design constraint with no described enforcement mechanism. Since this doc is now framed as a Spike (historical reference), future implementers are unlikely to encounter or remember this rule. Consider either adding a note about how this constraint is enforced (lint rule, code review checklist, test), or softening the language if enforcement is aspirational.
— DeepSeek/deepseek-v4-pro via Qwen Code /review
|
just a doc update with daemon server, can be closed. |
Summary
Validation
git diff --checkpassed; Prettier reported all matched files use Prettier code style.Scope / Risk
Testing Matrix
Testing matrix notes:
Linked Issues / Bugs
Related to #3803 and #4175.