feat(cli): Add agent view PTY workers - #7800
Conversation
05467fb to
44036f4
Compare
2f54001 to
1b994c1
Compare
|
Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. 中文请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。 |
1 similar comment
|
Please do not rebase or force-push to an active PR as it invalidates existing review comments. Note for future reference, the bots always squash all changes into a single commit automatically as part of the integration. 中文请勿对活跃的 PR 执行 rebase 或 force-push,因为这会使已有的评审评论失效。另外,供日后参考:作为集成流程的一部分,机器人始终会自动将所有改动压缩(squash)为单个提交。 |
|
Thanks for the PR! Template looks good ✓ Problem: this is a feature addition (stacked PR 2/5 for Agent View, refs #6383), not a bug fix — no reproduction needed. The need for a PTY worker runtime layer is clear from the stack design: the supervisor (PR 1/5) needs a concrete process and terminal bridge before lifecycle code can manage sessions. Direction: aligned. Background session management and agent view are active areas — Claude Code's CHANGELOG has extensive work on background sessions, worker heartbeats, agent view attach/detach, and managed session lifecycle. This layer provides the PTY process plumbing that later lifecycle PRs in the stack will build on. Size: not core paths (all files in Approach: the five modules are cohesive — PTY host process server/client over Unix sockets with per-host auth tokens, attach lease management with TTL expiry, bounded output ring with UTF-8-safe trimming, worker sideband env communication, and managed detach for session adoption. Each module has a clear responsibility and the test coverage is thorough. The socket protocol is simple (newline-delimited JSON) and the security posture looks solid (timing-safe token comparison, 0o700/0o600 socket permissions, bounded request lines, allowlisted kill signals). No unrelated changes or scope creep — everything serves the stated goal. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题:这是功能新增(Agent View 堆栈 PR 2/5,关联 #6383),不是 bug 修复——无需复现。PTY worker runtime 层的需求来自堆栈设计:supervisor(PR 1/5)需要具体的进程和终端桥接,后续 lifecycle 代码才能管理 session。 方向:对齐。后台 session 管理和 agent view 是活跃方向——Claude Code 的 CHANGELOG 有大量后台 session、worker 心跳、agent view attach/detach 和托管 session 生命周期相关工作。这一层提供后续 lifecycle PR 将构建其上的 PTY 进程管道。 规模:非核心路径(全部文件在 方案:五个模块职责清晰——通过 Unix socket 的 PTY host 进程服务端/客户端(带 per-host auth token)、带 TTL 过期的 attach 租约管理、UTF-8 安全裁剪的有界输出环、worker sideband 环境通信、以及 session 接管的 managed detach。测试覆盖充分。Socket 协议简洁(换行分隔 JSON),安全姿态扎实(timing-safe token 比较、0o700/0o600 socket 权限、有界请求行、白名单 kill 信号)。无无关改动或范围蔓延。 进入代码审查 🔍 — Qwen Code · qwen3.8-max-preview Reviewed at |
Code ReviewIndependent proposal: given "add a PTY worker host layer for managed Agent View sessions", I would have built: (1) a PTY host module wrapping node-pty with bounded output capture, (2) a Unix socket server exposing host control (status, logs, resize, kill, shutdown, attach) with per-host auth, (3) an attach lease mechanism to prevent duplicate attaches, (4) a worker sideband for env-based worker ↔ supervisor communication, and (5) a managed detach entry point for session adoption. The PR's five modules map almost exactly to this decomposition. Comparison: the PR matches the independent proposal. The implementation is well-structured — each module has a single responsibility, the socket protocol is minimal (newline-delimited JSON, one request per connection for control ops, persistent connection for attach streams), and the test suite covers the important paths: auth enforcement, duplicate attach rejection, bounded output with UTF-8 safety, lease expiry, signal allowlisting, and socket permission restrictions. No critical blockers found. A few observations, none blocking:
No AGENTS.md violations: ESM throughout, no TestingThis is an unattended CI run. No CI workflow runs exist for this commit — the PR targets the feature branch
The PR author reports macOS verification with Real-scenario testing: N/A — non-UI worker runtime layer, and this is an unattended CI run. A maintainer can trigger the isolated Not verified: build and unit test execution (no CI ran on this feature branch PR; PR code is never executed during triage). 中文说明代码审查独立方案: 给定"为托管 Agent View session 添加 PTY worker host 层",我会构建:(1) 包装 node-pty 的 PTY host 模块(带有界输出捕获),(2) 通过 Unix socket 暴露 host 控制的服务器(status、logs、resize、kill、shutdown、attach,带 per-host auth),(3) 防止重复 attach 的租约机制,(4) 基于环境变量的 worker ↔ supervisor 通信 sideband,(5) session 接管的 managed detach 入口。PR 的五个模块几乎完全对应这一分解。 对比: PR 与独立方案一致。实现结构良好——每个模块职责单一,socket 协议精简(换行分隔 JSON,控制操作每连接一请求,attach 流使用持久连接),测试覆盖重要路径:auth 强制、重复 attach 拒绝、UTF-8 安全的有界输出、租约过期、信号白名单、socket 权限限制。 未发现关键阻塞问题。几个观察,均非阻塞:
无 AGENTS.md 违规。 测试这是无人值守 CI 运行。此提交无 CI 工作流运行——PR 目标是功能分支 PR 作者报告 macOS 验证(作者声明,非独立验证)。Windows 和 Linux 未经作者测试。 真实场景测试:不适用——非 UI worker runtime 层,且为无人值守 CI 运行。 未验证:构建和单元测试执行(功能分支 PR 无 CI 运行;triage 期间不执行 PR 代码)。 — Qwen Code · qwen3.8-max-preview Reviewed at |
|
Confidence: 4/5 — clean, well-structured infrastructure PR; the only gap is the structural absence of CI on this feature branch target. This is solid plumbing work. The five-module decomposition maps cleanly to the problem: PTY host lifecycle, socket-based control with auth, attach leasing, worker sideband communication, and managed detach. The code reads well — the socket protocol is minimal, the The test suite is thorough for a runtime layer: 1157 lines covering auth enforcement, duplicate attach rejection, lease expiry with corrupted timestamps, UTF-8 trimming with multi-byte characters, oversized request handling, and socket permission verification. The tests use real Unix sockets where it matters (the pty-host-process tests) and clean fakes where it doesn't (the pty-host tests with injected PTY). My independent proposal for this problem was essentially the same decomposition — I didn't find a simpler path the PR missed. The 821-line The one reservation is structural: no CI ran because the PR targets the feature branch 中文说明置信度:4/5 ——干净、结构良好的基础设施 PR;唯一缺口是功能分支目标导致 CI 结构性缺失。 这是扎实的管道工作。五模块分解清晰对应问题:PTY host 生命周期、基于 socket 的带 auth 控制、attach 租约、worker sideband 通信、managed detach。代码可读性好——socket 协议精简, 测试套件对 runtime 层来说很充分:1157 行覆盖 auth 强制、重复 attach 拒绝、带损坏时间戳的租约过期、多字节字符 UTF-8 裁剪、超大请求处理、socket 权限验证。测试在关键处使用真实 Unix socket(pty-host-process 测试),在非关键处使用干净的 fake(注入 PTY 的 pty-host 测试)。 我的独立方案基本是相同的分解——没有找到 PR 遗漏的更简路径。821 行的 唯一保留是结构性的:因 PR 目标是功能分支 — Qwen Code · qwen3.8-max-preview Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
- Narrow AgentViewSupervisorSubscriptionOptions to omit timeoutMs, which the subscription never reads - Throw when DEV=true with a .ts entrypoint but tsx is missing, instead of silently spawning a process that will crash - Add test for the qwen fallback path when argv[1] is undefined - Add test for worker sideband auth bypass (workerEvent without token)
|
🔓 Takeover auto-released: the autofix loop paused on this PR 7 day(s) ago (🤖 AutoFix stopped: this counting window now contains 3 time-budget exhaustions (pushed rounds in between included; this ) and no re-arm followed, so the 中文说明🔓 已自动释放接管:autofix 循环在 7 天前暂停于此 PR(🤖 AutoFix stopped: this counting window now contains 3 time-budget exhaustions (pushed rounds in between included; this ),此后无人重新武装,现移除 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
Not reviewed: build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and its suite did not run locally — win32 branches (pipe paths, skipIf guards, signal-less kill) verified by reading only.
Not reviewed: build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and its suite did not run locally.
Not explored to full depth (tool budget reached): "agent reverse-audit (round 1)": isolate which ingredient of the real bridgeAgentViewTerminal path suppresses the connection idle timer under Node v22.23.0 (bisected receive/pause/resume, wri….
Not reviewed: reverse audit — did not converge within the reverse-audit round cap of 5.
Deferred under the convergence posture (round 18, not a blocker) — recorded, not requested in this round:
packages/cli/src/agent-view/attach-lease.test.ts:142 (+1 locations) — [probe] negative ttlMs never rejected in testspackages/cli/src/agent-view/attach-lease.test.ts:149 (+1 locations) — [probe] 'exactly MAX accepted' TTL boundary unpinnedpackages/cli/src/agent-view/attach-lease.test.ts:189 (+1 locations) — [probe] expire() full-sweep contract unpinnedpackages/cli/src/agent-view/attach-lease.test.ts:232 (+1 locations) — [probe] heartbeat() !lease guard unpinnedpackages/cli/src/agent-view/attach-lease.ts:58 (+3 locations) — [probe] Pattern: production default constants unverified (3…packages/cli/src/agent-view/attach-lease.ts:68 (+1 locations) — [probe] Lazy expire() in acquire() untestedpackages/cli/src/agent-view/managed-detach.test.ts:20 (+1 locations) — [probe] path.resolve() contract unpinned by absolute-only fixturespackages/cli/src/agent-view/managed-detach.ts:39 (+1 locations) — [probe] globalDir forwarding via storeOptions unpinnedpackages/cli/src/agent-view/managed-detach.ts:50 (+1 locations) — [probe] stdout fallback terminal geometry never assertedpackages/cli/src/agent-view/pty-host-process.test.ts:48 (+1 locations) — [probe] detach→re-attach cycle has zero coverage; resetInput never…packages/cli/src/agent-view/pty-host-process.test.ts:97 (+1 locations) — [probe] second-attach rejection test doesn't pin active stream…packages/cli/src/agent-view/pty-host-process.test.ts:734 (+1 locations) — [probe] exit-poller two-strike rule unpinnedpackages/cli/src/agent-view/pty-host-process.test.ts:805 (+1 locations) — [probe] coalesced leftover delivery after attach ack untestedpackages/cli/src/agent-view/pty-host-process.test.ts:1299 (+1 locations) — [probe] launch-path auth-token presentation unpinnedpackages/cli/src/agent-view/pty-host-process.test.ts:1305 (+1 locations) — [probe] RPC-failure fallback child kills never exercisedpackages/cli/src/agent-view/pty-host-process.ts:265 (+1 locations) — [probe] Attach-handshake failures swallowed by no-op error listenerpackages/cli/src/agent-view/pty-host-process.ts:316 (+1 locations) — [probe] remote dispose() settles exited early; lost RPC leaves…packages/cli/src/agent-view/pty-host-process.ts:400 (+1 locations) — [probe] listen-failure dispose branch untested; orphaned worker…packages/cli/src/agent-view/pty-host-process.ts:428 (+1 locations) — [review] Predictable fallback socket dir enables permanent DoS squatpackages/cli/src/agent-view/pty-host-process.ts:730 (+1 locations) — [probe] socket.setTimeout(0) attach exemption untested- …and 11 more (see the run report)
中文说明
仅完成部分审查,审查缺口已披露。
未审查:build-and-test — Test (windows-latest, Node 22.x) was skipped in CI and its suite did not run locally — win32 branches (pipe paths, skipIf guards, signal-less kill) verified by reading only。
未审查:build-and-test — Test (macos-latest, Node 22.x) was skipped in CI and its suite did not run locally。
未探索到全部深度(达到工具调用预算):"agent reverse-audit (round 1)":isolate which ingredient of the real bridgeAgentViewTerminal path suppresses the connection idle timer under Node v22.23.0 (bisected receive/pause/resume, wri…。
未审查:反向审计——在 5 轮的反审轮数上限内未收敛。
收敛姿态下延后(第 18 轮,非阻断)——已记录,本轮不要求修改:共 31 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.21.13)
|
@qwen-code /verify |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 493 passed · 0 failed · 493 total 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:493 通过 · 0 失败 · 493 总计 Verification reportPR 7800 Deep Verification — PTY worker host layer (Agent View stack 2/5)Verdict: 中文摘要
Scope selectionPR diff is purely additive: 11 new files under
A/B load-bearing proofEnvironment per cell: real
Head: 27/27 (Harness A) + 9/9 (Harness B). Controls flip exactly the probed behavior and nothing else (25/27 and 26/27 sibling cells unchanged in the respective mutants). Witnesses: One probe nuance: in the M3 control, the 4-byte-astral cell (B5) stayed clean by coincidental width alignment (cap 1000 is a multiple of 4), while 2-byte (odd cap) and 3-byte cells corrupted — the width matrix, not any single case, is what pins the repair. Mutation matrix (vacuity check on the PR's own tests)Unmutated control green: 216/216 (
No survivors → no coverage-gap or dead-code classification needed. Witness: FindingsNone blocking. All executed assertions passed; no regression reproduced. Observations (non-blocking, informational):
Not covered
MethodologyRan in the CI verify container ( Evidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
packages/cli/src/agent-view/ has no references elsewhere in main, and the first revision concluded from that it was abandoned and should be deleted. It is the base of #7799, whose remaining four PRs (#7800-#7803) are open, non-draft, and touch the directory directly. Static reachability in main cannot see consumers that live in pending PRs. This surfaces a real conflict the document was papering over: that series builds natively the terminal and supervisor layer section 4 argues to leave to herdr. Recorded as open question 7.6 rather than resolved, because it is a product decision.
The row read as settled fact by citing herdr alone. #7800 is building PTY workers natively, so §4 states one side of an open disagreement rather than a decision. Label it as a position and point at §7.6, which owns it.
There is no conflict. #7800, #7801 and #7803 touch no file under packages/core; #7802 touches three unrelated utilities; none of the four touches agents/team/, send-message.ts, tasks.ts or mailbox.ts — the entire surface this design changes. The conflict was an artifact of how 4 was written. Phrased as "not building X" it read as a project-wide ruling rather than this design's scope, so a PR building X looked like a contradiction. It is not one: whether Qwen hosts terminals natively is orthogonal to whether two sessions can ask each other a question. Removes open question 6, restores the two non-goal rows, and scopes 4 explicitly to this design.
yiliang114
left a comment
There was a problem hiding this comment.
Reviewed — 0 unresolved threads. Note: a number of resolved Criticals were silently resolved; the bot's re-scan did not re-flag, so treat as addressed. Approve.
|
Qwen Code review did not complete successfully. The review pipeline failed before a review could be posted. A transient error is retried automatically; if you are seeing this, retry with |
Superseded by 3c63475: all review threads are resolved and the current head passed the targeted local verification.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Partially reviewed — gaps disclosed.
9 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- X19-1 attach-handshake failures swallowed by no-op error listener — already reported (comment 3735552361)
- X19-2 predictable fallback socket dir enables permanent DoS squat — already reported (comments 3750798749, 3744227498)
- X19-3 RPC-failure child-kill fallbacks untested — already reported (round-18 deferred list)
- X19-4 listen-failure dispose branch untested — already reported (round-18 deferred list)
- X19-5 server malformed-request path untested — already reported (comment 3735552377)
- X19-6 managed-detach terminal fallback / globalDir forwarding unasserted — already reported (round-18 deferred list)
- X19-7 stateReportChains.delete mutant survived — already reported (comments 3750798471, 3748472882)
- X19-8 stateReportChains.clear mutant survived — already reported (comment 3750798481)
- X19-9 defaultSpawnPtyHost/withHostStderrTail untested — already reported (comment 3735552443)
Not reviewed: reverse audit — reached the 5-round cap without two consecutive dry rounds; rounds 3, 4, and 5 each surfaced new verified findings.
Not reviewed: build-and-test — Test (windows-latest, Node 22.x) failed in CI at the reviewed commit; attribution could not be measured from this Linux review (win32 branches verified by reading only).
Not reviewed: build-and-test — Test (macos-latest, Node 22.x) failed in CI at the reviewed commit; attribution could not be measured from this Linux review.
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) failed in CI at the reviewed commit; attribution could not be measured from this Linux review.
Deferred under the convergence posture (round 19, not a blocker) — recorded, not requested in this round:
packages/cli/src/agent-view/pty-host-process.ts:719 — [probe] shape rejections misreported as invalid_jsonpackages/cli/src/agent-view/pty-host.ts:209 — [probe] appendChunk retains caller Buffers by referencepackages/cli/src/agent-view/pty-host.ts:276 — [probe] schemaVersion rejection branch untestedpackages/cli/src/agent-view/pty-host-process.test.ts:1360 — [probe] readLine/readChunk never settle on close without newlinepackages/cli/src/agent-view/pty-host.test.ts:23 — [probe] BoundedOutputRing constructor guard untestedpackages/cli/src/agent-view/worker-sideband.test.ts:232 — [probe] control-event validator rejection branches ungatedpackages/cli/src/agent-view/pty-host-process.ts:664 (+3 locations) — [probe] Pattern: lock-contention guards mutation-ungatedpackages/cli/src/agent-view/worker-sideband.test.ts:233 — [probe] control-read transport-error contract unpinnedpackages/cli/src/agent-view/worker-sideband.test.ts:170 — [probe] partial-answer acceptance ungatedpackages/cli/src/agent-view/worker-sideband.test.ts:429 — [probe] process.env default parameter never exercisedpackages/cli/src/agent-view/pty-host-process.test.ts:517 — [probe] socket-dir hardening chmod ungatedpackages/cli/src/agent-view/pty-host.ts:390 — [review] signal-less kill SIGHUP divergence between handles
中文说明
仅完成部分审查,审查缺口已披露。
本轮确认的 9 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未审查:reverse audit — reached the 5-round cap without two consecutive dry rounds; rounds 3, 4, and 5 each surfaced new verified findings。
未审查:build-and-test — Test (windows-latest, Node 22.x) failed in CI at the reviewed commit; attribution could not be measured from this Linux review (win32 branches verified by reading only)。
未审查:build-and-test — Test (macos-latest, Node 22.x) failed in CI at the reviewed commit; attribution could not be measured from this Linux review。
未审查:build-and-test — Integration Tests (CLI, No Sandbox) failed in CI at the reviewed commit; attribution could not be measured from this Linux review。
收敛姿态下延后(第 19 轮,非阻断)——已记录,本轮不要求修改:共 12 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.21.14)
|
Cross-platform verification conclusion for the current head ( Evidence:
The remaining evidence gap is a native Windows run covering named-pipe bind/connect/close, real ConPTY spawn/process-tree cleanup, and detached PTY-host shutdown. I would not block #7800 on that gap because this PR adds dormant infrastructure and no public activation path. Before #7802 exposes Agent View, though, we should require one current-stack native Windows run (at minimum these five suites, ideally with a small real ConPTY smoke). If #7800 goes through the merge queue, the platform jobs will run there; a direct squash merge is not guaranteed to run them under the current branch rules. |
yiliang114
left a comment
There was a problem hiding this comment.
LGTM — the current head has no unresolved blocking findings, and the PR-scoped tests plus the native macOS PTY smoke pass. Native Windows verification remains a non-blocking follow-up before #7802 exposes the feature.
|
Released in v0.21.15. |
* feat(cli): manage agent view session lifecycle * fix(cli): preserve agent view lifecycle state * fix(cli): harden agent view lifecycle persistence * fix(cli): harden agent view lifecycle * fix(cli): harden agent view lifecycle recovery * fix(cli): close agent view lifecycle review gaps * fix(cli): address lifecycle review suggestions * fix(cli): Address round-4 agent-view lifecycle review feedback - Respawn decisions now use refreshed state under the host-setup lock: refreshed updatedAt for stop observation (C1), re-read host after refresh, unconditional attach block reason, identity-checked registry deletion, stored worker pid kill when no in-memory host (C5/C6/C9/C12) - Stored stop fallback captures pids at scheduling time and only marks stopped when the worker record still matches (C2) - Failed re-adoption of a stale adopting record falls back to a terminal adoption_failed state (C3); auto-exit blocks while adopting (C4) - Attach prep clears stale persisted attach flags without bumping updatedAt (C7); unplanned exits keep the queued prompts (C8) - Repeated stops always rewrite state to stay observable (C11); hibernating transitions are guarded and re-validated (C10/S20) - Suggestions: S1/S2/S5/S6/S8/S10/S11/S13/S14/S15/S16/S17/S18 * fix(cli): Address round-5 agent-view lifecycle review feedback - Queued user input now survives worker replacement: unplanned exits, send-triggered revives, and the stored stop fallback keep pending prompt/answer controls and drop only stop/redraw (R5-1/R5-2/R5-11) - The queue marker is persisted before the in-memory control so a failed write rejects cleanly (R5-4); orphaned markers left by dead daemons are cleared on send (R5-9); superseded-host exits, buffered worker events, and pre-queue events can no longer resurrect or clear a settled session (R5-3/R5-12/R5-13) - Activity/state writes use field-level patches instead of whole-file read-modify-write off stale snapshots (R5-8); list() isolates per-session heal failures (R5-5); stale adopting records reconcile to a terminal state instead of blocking auto-exit (R5-7); dispatch's ready-wait catch honors deliberate stops (R5-10) - Suggestions: shared inputKind/sessionState validators (R5-14/R5-15), AgentViewSessionStoppedError for stop classification (R5-18), shared worker-token digest (R5-20), roster self-heal on read (R5-22), truncated queued-prompt preview (R5-23), CI keys stripped from the worker pty env (R5-24), live-control-aware stale clear (R5-25), and test coverage for R5-16/R5-17/R5-19/R5-21/R5-26/R5-27 * fix(cli): address R6 review findings and slim test suite R6 Critical fixes: - Replace whole-snapshot writes with patchAgentViewSessionState - Add bootGeneration guard for killStoredWorkerPids and ready-wait - Add preserveQueuedInputControls to failure paths - Add isStoppedError branch in adopt() catch - Move hibernation mark transitions inside withHostSetupLock - Add resolveSessionCwd for symlink-safe cwd comparison - Stamp event.at at emit time for dequeue ordering guard - Re-validate lastQueuedPromptAt in clearStalePendingPromptIfNeeded - Absolutize getCurrentQwenCliEntrypoint via path.resolve - Restore ensureSessionStillLaunchable transient read check - Remove dead hibernation policy enabled field - Use injectable now clock in snapshot cache Test slimming: - Remove 26 redundant/vacuous tests across supervisor-process, presentation, supervisor-store, and worker-sideband test files - Simplify SessionSnapshotCache (remove dirty/version counters) * Merge agent/agent-view-pty-workers into agent/agent-view-lifecycle * fix(cli): address R7 review findings Fix 14 issues from round-7 review: - R6-1: patchAgentViewSessionState replaces writeAgentViewSessionState in respawn - R6-10: adopt catch mirrors dispatch - rejectPendingWorkerReady + terminateSession moved into non-stopped branch - R6-12: adopt() wrapped in withHostSetupLock for per-session serialization - R7-2: hibernateIdleSessionsWithPolicy calls refreshMissingWorkerState in !host branch - R7-5: scheduleStopFallback ordered before markStoppedSession in host branch - R7-6: writeAttachState wrapped in try/catch in attach finally - R7-14: markFailedSession preserves completed terminal verdict, uses patch - R7-15: shortHash reverted to 12-hex for endpoint stability - R7-24: updateExitedSession checks sessionState !== starting before completed - R7-27: healing catch restores both state and activity on partial failure - R7-28: in-lock re-validation excludes sessionState === working - R7-29: applyWorkerEvent returns boolean, caller resolves only when applied - R7-30: shutdownAll uses Promise.allSettled instead of Promise.all - R7-34: patchAgentViewSessionState serialized via stateMutationQueues Also fixes 3 pty-host.test.ts failures from merge with #7800: - Add NO_COLOR/FORCE_COLOR/CI to INTERNAL_ONLY_WORKER_ENV_KEYS - Add initialPrompt validation to validateAgentViewLaunchConfig - Use launch.env TERM instead of hardcoded xterm-256color * fix(cli): don't optimistically resolve exit tracker on SIGINT * fix(cli): sync non-agent-view files to latest pty-workers base * fix(cli): address R8 review findings * fix(cli): address remaining R8 critical findings - guard queued-prompt marker until the pending input control is consumed - release host cleanup on the no-host killSession branch - rotate the worker sideband token on respawn and persist its digest - decide the stale-worker heal inside the queued mutation so concurrent terminal verdicts are preserved * fix(cli): close agent-view respawn, worker-event and prompt-marker races - respawn: persist the 'starting' state patch and rotated tokenDigest before launch so a fast replacement ready authenticates and passes the dead-worker guard - applyWorkerEvent: decide the state patch inside the queued mutation so an exit verdict enqueued after the guard read is not clobbered - store: route activity.json read-merge-writes through a per-session mutation queue and add patchAgentViewActivityIf - clearPersistedPromptQueue: re-validate lastQueuedPromptAt inside the queued mutation before clearing - clearStalePendingPromptIfNeeded: take the orphan branch only when no live host is registered, so a drained control is not mistaken for a lost one - correct the queued-answer comment (answers are intentionally ephemeral) * fix(cli): close agent-view stale-attach, stop-fallback and hibernate races * fix(cli): close R11 stop-clobber, restart marker wedge and ready-waiter hang - respawn pre-launch patch and updateExitedSession now re-validate inside the queued state mutation so a concurrent stop verdict is never clobbered - pending-prompt markers queued before daemon start are orphaned, un-wedging restarted needs_input sessions - dropped ready events reject the pending waiter instead of hanging 15s - bootGeneration entries are released on session kill/terminate - pre-bridge attach failures keep the socket open for the error envelope * fix(cli): close R12 stop-launch orphan, marker clobber and pid-signaling races - terminate orphan worker when dispatch/adopt stop errors bypass queueStop - drain queued stop control before hibernate; re-validate pin under roster lock - serialize worker file writes through the shared per-path mutation queue - make dequeue/state heals marker-guarded and skip terminal sessions - sanitize adopted session ids once; guard stale pid signaling * fix(cli): close R13 verdict races, resume casing and stop/respawn lifecycle gaps * fix(cli): close R14 respawn EADDRINUSE, dispatch pid timing and stale verdict races * fix(cli): Harden Agent View lifecycle verdicts, ghost cleanup, and resume argv * fix(cli): Confirm worker death before terminal verdicts and close roster fail-open paths Round-16 review fixes for the Agent View lifecycle: - Roster strict reader now rejects a declared-but-non-boolean pinned field; roster mutations read through the same fail-closed path so a corrupt-but-present roster.json can no longer be overwritten with an emptied roster (pins exist nowhere else). - The dead-worker event guards also drop events against 'hibernating' records, so a straggler event after the sweep's point of no return cannot flip the record back to alive and fail the hibernated mark. - respawn releases the predecessor's registry entry before launching, keeping the graceful-stop fallback timer from matching the retired host mid-launch. - Worker events normalize waitingFor case at ingest so the queued- prompt dequeue gates and presentation agree. - shouldAdvanceActivityTime stops advancing lastActivityAt while an input control suppresses the marker dequeue, keeping the stale-marker wall-clock evidence honest. - Hibernation sweep, stop fallback, remove, and shutdownAll confirm the actual exit (shutdown RPC with SIGKILL escalation, then host.exited) before writing terminal verdicts: a still-draining worker must not keep the session socket with no signalling path able to reach it. * fix(cli): harden agent view lifecycle races * fix(cli): serialize agent view lifecycle transitions * fix(cli): close agent view prompt recovery races * fix(cli): close agent view lifecycle races * fix(cli): make agent view lifecycle recoverable * fix(cli): close agent view lifecycle races * fix(cli): serialize stopped session healing * fix(cli): harden agent view lifecycle recovery --------- Co-authored-by: 俊良 <zzj542558@alibaba-inc.com> Co-authored-by: yiliang114 <effortyiliang@gmail.com>





What this PR does
Stack position: 2/5. Parent: #7799. Next: #7801.
This stacked PR adds the PTY worker host layer used by managed Agent View sessions. It launches local terminal hosts for session workers, exposes authenticated host control, forwards attach streams, retains bounded recent output for logs, and preserves UTF-8 boundaries while trimming output.
Why it's needed
The supervisor needs a concrete worker runtime before it can manage lifecycle state. This layer provides the process and terminal bridge that later lifecycle code can start, reconnect, stop, hibernate, and attach without coupling the roster UI directly to worker process details.
Reviewer Test Plan
How to verify
npm run build; the repository should build successfully.cd packages/cli && npx vitest run src/agent-view --coverage.enabled=false; all Agent View unit tests should pass.Evidence (Before & After)
N/A — this is a non-UI worker runtime layer.
Tested on
Environment (optional)
macOS, Node.js v26.2.0. Local verification required reinstalling current workspace dependencies and applying the existing Ink patch to local
node_modules.Risk & Scope
Linked Issues
Refs #6383
中文说明
此 PR 的内容
堆栈位置:2/5。父 PR:#7799。下一个 PR:#7801。
这个 stacked PR 增加托管 Agent View session 使用的 PTY worker host 层。它为 session worker 启动本地终端 host,暴露带认证的 host 控制,转发 attach stream,保留有界 recent output 供 logs 使用,并在裁剪输出时保留 UTF-8 边界。
为什么需要
supervisor 需要一个具体的 worker runtime,之后才能管理生命周期状态。这一层提供后续 lifecycle 代码可以启动、重连、停止、休眠和 attach 的进程与终端桥接能力,同时避免 roster UI 直接耦合 worker 进程细节。
评审者测试计划
如何验证
npm run build;仓库应成功构建。cd packages/cli && npx vitest run src/agent-view --coverage.enabled=false;全部 Agent View 单元测试应通过。证据(变更前后)
不适用——这是非 UI 的 worker runtime 层。
测试平台
环境(可选)
macOS,Node.js v26.2.0。本地验证前需要补齐当前 workspace 依赖,并把仓库已有 Ink patch 应用到本地
node_modules。风险与范围
关联 Issue
关联 #6383