Skip to content

docs(design): Define selective session restore - #8743

Merged
doudouOUC merged 17 commits into
mainfrom
docs/issue-8678-selective-session-restore-design
Aug 13, 2026
Merged

docs(design): Define selective session restore#8743
doudouOUC merged 17 commits into
mainfrom
docs/issue-8678-selective-session-restore-design

Conversation

@doudouOUC

@doudouOUC doudouOUC commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

This documentation PR defines the reviewed implementation contract for #8678's selective daemon session restore. The prerequisite work in #8691, #8833, #8882, and #8933 has merged, so the runtime implementation can proceed from current main; #8883 and the later ownership slices remain related but are not prerequisites.

The design replaces cold loadSession/resumeSession full transcript materialization with one cold restore projection and a narrower live projection. It specifies one sequential index scan plus selected-record seeks, cooperative scheduling between complete records, shared Goal/artifact/FileHistory reducers, request-local cache admission, and exact replay-shape handling for all, recent(limit), and none.

The lifecycle reuses the existing session-id reservation, Session publication, and stored-session rollback boundaries. It validates the replay envelope before runtime hydration, keeps selective side effects behind the existing fallible setup, and avoids introducing a second admission state machine or a general-purpose activation framework.

Explicitly recent bulk replay is bounded to 32 MiB and 10,000 updates, while an omitted historyPageSize preserves legacy full visible replay. The design adds no public REST or SDK success field. Durable checkpoints, worker-thread or streaming JSON parsing, and unrelated full-content readers remain follow-up work.

This PR contains the design and implementation plan only; it does not contain the runtime implementation, benchmark results, or E2E evidence.

Why it's needed

The current daemon cold path materializes the complete JSONL transcript before configuration and can materialize it again after writer-lease acquisition. historyPageSize is applied only after those allocations, so a client requesting a small recent page can still pay duplicate full-read and reconstruction cost.

The existing reader also parses complete physical records synchronously on a shared ACP child. Cumulative scan work can delay active sibling sessions, while one large JSON record remains an indivisible parse interval. The design therefore combines bounded selection with cooperative record-boundary yielding without adding protocol surface or a second reader.

The merged prerequisites now provide safe restore timeouts, attachment identity, transactional WebUI switching, and exact request-shape coalescing. This document binds selective restore to those existing ownership and failure contracts before core and cross-package implementation begins.

Reviewer Test Plan

How to verify

  1. Confirm the PR changes only the selective-restore design and implementation plan and that fix(serve): Make session restore timeouts safe and observable #8691, fix(webui): Fence stale session work by attachment identity #8833, fix(webui): Make cross-session switching transactional #8882, and fix(serve): Keep restore request shapes distinct #8933 are merged.
  2. Verify the cold reader contract is one sequential index scan plus selected seeks, with active-chain lineage, Goal/artifact/FileHistory parity, typed snapshot failures, and non-clobbering cache admission.
  3. Verify cooperative yields occur only between complete physical records or selected aggregates; a single large synchronous JSON parse remains explicitly out of scope.
  4. Confirm the lifecycle reuses existing session reservation, publication, and rollback boundaries, and does not add a parallel admission state machine or universal activation framework.
  5. Confirm exact replay shapes do not coalesce across action, response/stream mode, page limit, or inherited-history policy; omitted historyPageSize retains full-replay compatibility.
  6. Confirm explicitly recent replay accepts exactly 32 MiB and 10,000 updates and rejects the first extra byte or 10,001st update, subject to explicit maintainer sign-off during implementation review.
  7. Run npx prettier --check docs/design/2026-08-08-selective-session-restore.md docs/plans/2026-08-08-selective-session-restore.md and git diff --check; both should pass.

Evidence (Before & After)

N/A — documentation-only change with no user-visible or runtime behavior.

Tested on

OS Status
🍏 macOS ✅ tested
🪟 Windows N/A
🐧 Linux N/A

Environment (optional)

macOS Darwin arm64; Node.js 22; Prettier, Git diff validation, and two consecutive broad clean audit passes.

Risk & Scope

  • Main risk or tradeoff: The future implementation touches core and cross-package restore infrastructure. The 256 MiB transcript ceiling and 32 MiB transformed-replay ceiling require explicit maintainer sign-off, and cooperative yielding cannot preempt one large synchronous JSON parse.
  • Not validated / out of scope: Runtime implementation, E2E and benchmark results, durable checkpoints, worker-thread or streaming JSON parsing, TUI and non-interactive resume migration, export, fork/branch, legacy qwen/session/loadUpdates, independent live-task/realtime startup readers, and later ownership slices.
  • Breaking changes / migration notes: This documentation PR has no runtime breaking change. The proposed implementation preserves full replay when historyPageSize is omitted and introduces typed failures only for the explicitly documented transcript and recent-page bounds after maintainer approval.

Linked Issues

References #8678

Prerequisites #8691, #8833, #8882, and #8933 are merged. Related but not required: #8883 and the later ownership slices.

中文说明

本 PR 做了什么

这个文档 PR 定义了 #8678 daemon 会话选择性恢复方案经过评审的实施契约。前置工作 #8691#8833#8882#8933 均已合入,因此运行时实现可以基于当前 main 推进;#8883 与后续 ownership 切片仍然相关,但不是前置条件。

方案使用一个冷恢复 projection 和一个更窄的 live projection,替代冷 loadSession/resumeSession 对完整 transcript 的物化。它规定执行一次顺序索引扫描加 selected-record seek,在完整记录之间协作式让出调度,复用 Goal、artifact 与 FileHistory reducer,按请求将新索引加入缓存,并对 allrecent(limit)none 采用精确 replay shape。

生命周期复用现有 session-id reservation、Session 发布和 stored-session 回滚边界。它在运行时 hydration 前验证 replay envelope,将选择性恢复新增的副作用放在现有可失败 setup 之后,并且不引入第二套 admission 状态机或通用 activation 框架。

显式 recent bulk replay 限制为 32 MiB 和 10,000 条 update,省略 historyPageSize 时继续保留旧版完整可见 replay。方案不增加公开 REST 或 SDK 成功字段。持久 checkpoint、worker-thread 或 streaming JSON 解析以及无关的全量内容 reader 仍属于后续工作。

本 PR 只包含设计与实施计划,不包含运行时实现、benchmark 结果或 E2E 证据。

为什么需要

当前 daemon 冷路径会在配置构建前物化完整 JSONL transcript,并可能在获取 writer lease 后再次物化。historyPageSize 只在这些分配完成后才生效,因此客户端即使只请求一小页最近历史,也可能承担重复的全量读取和重建成本。

现有 reader 还会在共享 ACP child 上同步解析完整物理记录。累计扫描工作可能延迟活跃 sibling session,而单条大型 JSON 记录仍然是不可分割的解析区间。因此方案将有界选择与记录边界上的协作式让出结合起来,同时不增加协议面或第二套 reader。

已合入的前置工作现在提供安全恢复超时、attachment identity、事务式 WebUI 切换和精确 request-shape coalescing。本设计在 core 与跨 package 实现开始前,将选择性恢复绑定到这些既有 ownership 和失败契约。

Reviewer 测试计划

验证方式

  1. 确认本 PR 只修改选择性恢复设计与实施计划,并确认 fix(serve): Make session restore timeouts safe and observable #8691fix(webui): Fence stale session work by attachment identity #8833fix(webui): Make cross-session switching transactional #8882fix(serve): Keep restore request shapes distinct #8933 已合入。
  2. 确认冷 reader 契约为一次顺序索引扫描加 selected seek,并保留 active-chain lineage、Goal/artifact/FileHistory 语义一致性、typed snapshot failure 和不覆盖已有项的缓存 admission。
  3. 确认 cooperative yield 只发生在完整物理记录或 selected aggregate 之间;单条大型同步 JSON parse 仍明确不在范围内。
  4. 确认生命周期复用现有 session reservation、publication 和 rollback 边界,不增加并行 admission 状态机或通用 activation 框架。
  5. 确认 action、response/stream mode、page limit 或 inherited-history policy 不同的精确 replay shape 不会 coalesce;省略 historyPageSize 时保留完整 replay 兼容性。
  6. 确认显式 recent replay 接受恰好 32 MiB 和 10,000 条 update,并拒绝第一个额外字节或第 10,001 条 update;这些边界须在实施评审中获得 maintainer 明确确认。
  7. 运行 npx prettier --check docs/design/2026-08-08-selective-session-restore.md docs/plans/2026-08-08-selective-session-restore.mdgit diff --check,两者都应通过。

证据(Before & After)

N/A——纯文档变更,没有用户可见或运行时行为变化。

测试平台

OS 状态
🍏 macOS ✅ 已测试
🪟 Windows N/A
🐧 Linux N/A

环境(可选)

macOS Darwin arm64;Node.js 22;使用 Prettier、Git diff 校验和两轮连续全面 clean 审计。

风险与范围

  • 主要风险或权衡:未来实现会触及 core 与跨 package 的恢复基础设施。256 MiB transcript 上限和 32 MiB 转换后 replay 上限需要 maintainer 明确确认,且 cooperative yield 无法抢占单条大型同步 JSON parse。
  • 未验证 / 不在范围内:运行时实现、E2E 与 benchmark 结果、持久 checkpoint、worker-thread 或 streaming JSON 解析、TUI 与 non-interactive resume 迁移、export、fork/branch、旧 qwen/session/loadUpdates、独立 live-task/realtime startup reader,以及后续 ownership 切片。
  • 破坏性变更 / 迁移说明:这个文档 PR 没有运行时破坏性变更。拟议实现会在省略 historyPageSize 时保留完整 replay,并且只有在 maintainer 批准后,才会为明确记录的 transcript 和 recent-page 边界引入 typed failure。

关联 Issue

References #8678

前置 #8691#8833#8882#8933 均已合入。相关但非前置:#8883 与后续 ownership 切片。

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@github-actions github-actions Bot added the review/self-reported The linked issue was opened by the PR author (self-reported) label Aug 8, 2026
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC doudouOUC self-assigned this Aug 9, 2026
@doudouOUC
doudouOUC marked this pull request as ready for review August 9, 2026 02:05
@doudouOUC
doudouOUC enabled auto-merge August 9, 2026 02:06
@doudouOUC
doudouOUC requested review from wenshao and yiliang114 August 9, 2026 02:06
@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Qwen Triage finishedview run. See the stage comments in this thread for the result.

Qwen Triage 已完成 —— 查看运行。结果见本线程中的各阶段评论。

@doudouOUC
doudouOUC marked this pull request as draft August 9, 2026 02:40
auto-merge was automatically disabled August 9, 2026 02:40

Pull request was converted to draft

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

📄 Docs-only change — the automatic review ran at --effort medium (verified findings, no reverse audit; medium posts no inline comments). Outcome:

Review complete: pr-8743 — Comment, not posted (0 Critical, 1 Suggestion)

Reviewed head: 4427b212b1dea1c1f713d97a5da91ce350e49f7a. Full report in the workflow run. For a full high-effort review with inline comments, comment @qwen-code /review.

中文说明

📄 纯文档变更 —— 自动评审以 --effort medium 运行(发现已验证、无反向审计;medium 不发布行内评论),结果见上方引用行。评审的 head:4427b212b1dea1c1f713d97a5da91ce350e49f7a。完整报告见 workflow 运行;如需带行内评论的完整高强度(high-effort)评审,请评论 @qwen-code /review

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Design Review

I verified every code-level claim in this design doc against current main — all are accurate:

Claim Code location Verified
Full materialization on cold load packages/cli/src/config/config.ts:1998sessionService.loadSession()
Duplicate load on lease acquisition packages/core/src/config/config.ts:3153
historyPageSize applied after materialization packages/cli/src/acp-integration/acpAgent.ts:4920,4944
256 MiB / 4 MiB / 16 MiB reader limits session-transcript-reader.ts:29,30,40
32 MiB REST serialization ceiling serve/routes/session.ts:178 (2 × 16 MiB)
10,000 update cap acp-bridge/src/bridge.ts:237
Writer lease default-off, startup-frozen config.ts:2225-2226, acpAgent.ts:11726

The streaming dispatch design (no catch-all ChatRecord[]), goal bootstrap for recent-page restore, one-shot projection release, and no-fallback-to-old-loader are all sound technical decisions.

Concerns

1. Ordering: safety before performance (primary concern)

The design proposes selective restore before transactional WebUI switching. But the user-visible symptom from the incident is "current conversation stopped" — that's directly fixed by transactional switching, which is a performance-independent safety guarantee. Selective restore reduces the probability of timeout, but when it still occurs (e.g. a 200 MiB transcript on a slow machine, or under memory pressure), the user still loses their session.

Suggested ordering:

#8691 (timeout safety) → transactional switching (user safety) → selective restore (performance) → checkpoint (tail-proportional)

2. PR scope: consider splitting

The design says "implement one end-to-end fix PR." The most obvious waste — the duplicate loadSession() in activateChatRecording() — is a small, low-risk change that immediately helps the worst case. Consider splitting into:

  • PR-A: eliminate duplicate load + early historyPageSize application (small, low-risk, immediate relief)
  • PR-B: full projection architecture (streaming dispatch, goal bootstrap, live projection, envelope limits, consumer migration)

3. File history: "unavoidable" cost may be deferrable

The design states file-history payloads are an "explicit unavoidable selected-read cost" because prompt ids and batch validity live inside JSON. Consider deferring file-history restoration to first /rewind or file operation, rather than eagerly during cold restore. For sessions with heavy file activity, this could be a significant fraction of selected bytes.

4. 32 MiB transformed envelope: consider configurability

A single source record can expand to many ACP updates (tool result projections, etc.). A hard 32 MiB failure means the entire restore fails for an edge case that incremental trimming could handle gracefully. Consider making the limit configurable via settings.experimental, or allowing incremental trimming of non-critical updates before hard failure.

5. Small-session regression

For small sessions (< 1 MiB), the index build + selective read + dispatcher overhead may exceed a direct sequential full read. Consider a fast path that uses the current full read when the transcript is below a threshold (e.g. 4 MiB), so the new path only activates where it actually helps.

Minor

  • The 6 TypeScript interfaces could be simplified — some fields like backgroundNotificationTaskIds could be lazily derived from the index rather than eagerly projected.
  • The design doesn't discuss memory accounting for the index hints themselves (compression candidates, telemetry positions, etc.). The existing cache estimator should explicitly cover these additions.

Summary

This is a high-quality design doc with accurate code analysis and sound technical decisions. The main disagreement is on implementation ordering — I'd prioritize transactional switching (safety) over selective restore (performance) — and on PR granularity. The file-history deferral and small-session fast-path suggestions are worth evaluating before the implementation PR.

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Thanks for the thorough review. I agree with the main ordering concern. Here is the proposed disposition:

  1. Ordering — accepted. I’ll update the implementation order to #8691 timeout safety → transactional switching → selective restore → checkpointing. The design PR can still be reviewed independently, but selective-restore implementation should wait until the transactional boundary is settled.

  2. Scope — concern accepted, proposed PR-A/PR-B boundary not adopted. The duplicate read only exists when the default-off writer-lease path is enabled, and the second read is the authoritative snapshot taken after acquiring the lease, so removing it independently would weaken correctness. Also, historyPageSize currently limits replay only after the full session has been loaded; applying it before I/O is the projection work itself. I’ll keep selective restore as an end-to-end vertical slice, structured into reviewable commits rather than landing an incomplete projection API.

  3. File history — keep eager streaming restoration. Deferring restoration until /rewind or a file operation is too late: the first resumed turn may create a new snapshot that must inherit the restored tracked files and backups. The design will retain streaming reduction, last-write-wins semantics, and the final 100-snapshot cap, and will explicitly document why lazy restoration requires a separate lifecycle change.

  4. 32 MiB envelope — keep the hard limit and typed failure. Making it configurable would weaken the daemon/bridge memory boundary, while trimming “non-critical” updates could silently break tool-call/result, goal, turn, or artifact semantics. I’ll document those rejected alternatives more explicitly; requesting a smaller replay page remains the recovery path for collective overflow, while an individually oversized source record must fail explicitly.

  5. Small sessions — measure first. I’ll add small-transcript benchmark criteria, including inputs below 4 MiB. If the selective path shows a meaningful absolute regression, the optimization should remain inside the same scanner/reducer semantics rather than falling back to the old full loader and maintaining two behavioral engines.

On the minor points:

  • The interface shapes are internal design boundaries, not a requirement to preserve six concrete public types. They can be collapsed during implementation where the call sites permit. backgroundNotificationTaskIds should remain eagerly projected because session priming consumes it immediately and the data is small.
  • Index-hint memory accounting is already required by the design’s shared estimator and cap, but I agree it should be testable. I’ll add an explicit hint-heavy index case to the validation plan.

I’ll revise the design and implementation plan along these lines without expanding the feature scope.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Follow-up: the agreed design changes are now implemented in 2001c6b00e.

  • Restored the implementation order to #8691 → transactional WebUI switching → selective restore with bounded hydration → checkpointing, while allowing this documentation PR to land independently.
  • Kept selective restore as one end-to-end vertical slice and documented why the post-lease authoritative read and pre-materialization paging cannot be split into the proposed PR-A.
  • Required file-history state to be consumed before Session publication, retained the fixed explicitly-recent 32 MiB transformed-envelope policy, and documented individual/aligned-group overflow and explicit smaller-page retry semantics.
  • Added small-session benchmark criteria without a production fallback to the old loader, plus complete index-hint cache accounting and admission tests.
  • Clarified that the TypeScript snippets are internal semantic boundaries and may be collapsed where implementation call sites permit.

The English and Chinese PR descriptions were updated to match. prettier --check and git diff --check pass, and two final open-ended audit passes found no further actionable issues. The PR remains Draft.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@github-actions github-actions Bot removed the review/self-reported The linked issue was opened by the PR author (self-reported) label Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

Final implementation plan is now reflected in commit 6283d081a4 and in the bilingual PR description.

The update keeps the reviewed dependency order (#8691 → transactional WebUI switching → selective restore → checkpoint) and keeps selective restore as one end-to-end daemon slice. It accepts the scope concern behind the proposed split, but does not split early pagination from the projection because that would leave the default pre-materialization I/O and downstream runtime consumers unbounded.

The remaining implementation decisions are now explicit: one full index scan plus bounded selected seeks; one-record peak aggregation; active-chain side-task/artifact semantics; non-clobbering cache admission; one-shot Config handoff; same-id preparation reservation; pre-publication provisional teardown; envelope validation before runtime file-history hydration; post-publication validation/autonomous work; exact v1 anchor, coalescing shape, 32 MiB/10,000-update boundaries; typed ACP/REST mapping; and targeted race/failure/benchmark acceptance tests.

Both documents pass Prettier and git diff --check, and the updated diff completed two consecutive clean broad-audit passes. The PR remains Draft for review.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Updated the finalized design in commit 0cb33ec after two clean broad-audit passes.

This round closes three lifecycle gaps: pending Goal checkpoints receive a bounded evidence window from the single projection and activate only after publication; process-global attribution is applied only in the final no-await commit; and the complete ACP success response is built before the Session is published. The design and acceptance plan now also gate every autonomous or session-visible callback until publication and cover response-builder, attribution, checkpoint, and teardown failures.

Validation: both design documents pass Prettier and git diff checks. Delivery prerequisites are unchanged: #8691 is still open with changes requested, and transactional WebUI switching has not landed. This PR remains docs-only and Draft; runtime implementation has not started.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Updated the docs-only Draft at c26a063 after the final audit. This revision makes Goal preparation and activation separately memoized with explicit early-activation and disposal terminal behavior; builds the complete ACP response before FileHistory hydration or provisional Session construction; validates final reservation ownership before commit-time attribution; documents the #8691 late-abandoned attribution limitation; and specifies receiver-first, producer-last post-publication activation with independent failure isolation. The design and plan now carry matching acceptance tests. Validation completed: Prettier check, git diff check, and two consecutive clean broad-audit passes. Runtime implementation remains intentionally blocked on #8691 and transactional WebUI switching and is not included in this PR.

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

After rechecking the current design head (c26a063cbc) against the current prerequisite implementation, I think the runtime plan should be narrowed in three concrete ways before implementation.

1. Reuse the existing child-side session-start reservation

The ACP agent already has startingSessionIds / reserveStartingSessionId(), and newSession, cold loadSession, and cold resumeSession hold that reservation from before configuration/session startup through each handler's terminal finally. Adding a separate preparingSessions registry would create two ownership state machines for the same session id, with new ordering and cleanup invariants but no additional admission guarantee.

Please update the design to reuse and, only if necessary, extend the existing reservation. The required invariant is that one child-side owner holds the id until success or complete provisional teardown; it does not require a second registry.

2. Keep publication changes targeted to side effects introduced by selective restore

The proposed general activateAfterPublication() framework—covering every background receiver/producer, shell/workflow/MCP/cron/title path—is a broad child lifecycle refactor rather than a prerequisite for bounded transcript hydration. It substantially increases the core/CLI scope and creates new ordering behavior unrelated to the incident.

A smaller safe boundary is sufficient for this PR:

  • finish the fresh index validation, selected reads, replay-envelope validation, Goal bootstrap generation, and all fallible response-input preparation before createAndStoreSession();
  • hydrate restored file snapshots only after the replay envelope is known to be valid, and defer validateRestoredSnapshots() until successful Session creation because validation may append records;
  • prepare Goal state during projection, but start autonomous checkpoint/continuation work only after successful Session creation;
  • prepare the attribution snapshot provisionally and apply it after successful Session creation through an isolated non-throwing/best-effort step, so an attribution failure cannot turn an already-created Session into a failed restore.

Existing direct-child publication semantics are pre-existing lifecycle debt and should remain out of scope unless the selective path demonstrably worsens them. With #8824, the WebUI also retains the old session until the target restore returns, so user-visible switching safety does not depend on introducing a universal child-side atomic-publication framework here.

3. Make restore coalescing compare the exact normalized replay shape

The bridge currently stores and compares action, historyReplay, and hideInheritedHistory, but InFlightRestore does not store historyPageSize. Consequently, concurrent recent(100) and recent(500) loads for the same id can incorrectly coalesce and one caller can receive the other caller's replay shape.

Please normalize each request before admission to an exact discriminated shape such as all, recent(limit), or none (with inherited-history policy included where relevant), store that shape in InFlightRestore, and coalesce only when the full normalized shape matches. Tests should cover exact-shape coalescing plus mismatched explicit limits, omitted-vs-recent, load-vs-resume, and inherited-history differences; mismatches should receive the existing restore-in-progress conflict rather than sharing a result.

These changes preserve the end-to-end selective-restore PR while removing a redundant state machine, avoiding an unrelated lifecycle refactor, and closing a concrete response-shape concurrency bug.

doudouOUC and others added 2 commits August 10, 2026 10:43
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Thanks for the concrete recheck. I validated all three points against the current prerequisite code and updated the design accordingly.

  1. The plan now explicitly reuses startingSessionIds / reserveStartingSessionId() from before settings/existence I/O through the existing creation attempt and handler finally. It does not add preparingSessions, reservation-to-map conversion, or a second publication protocol.

  2. I accepted the scope concern and removed the proposed universal atomic-publication / activateAfterPublication() refactor, capture-only callback framework, and map-independent provisional teardown. The selective path now completes the fresh index checks, selected reads, replay-envelope limits, Goal bootstrap, and full ACP response construction before createAndStoreSession(). It preserves that function's current early map insertion and guarded stored-session rollback. File snapshots hydrate only after the envelope and response are valid; after the existing fallible setup and installRewriter(), one narrow non-throwing finalizer runs before cron/commands to isolate attribution application, Goal activation, and FileHistory validation. Existing Session callback timing, UI telemetry replay timing, reporter behavior, and unrelated cleanup edges remain unchanged.

  3. The bridge shape is fixed as the exact normalized discriminated replay mode (all, recent(limit), or none) plus action, response/stream mode, and inherited-history policy. Only exact matches coalesce; omitted-vs-explicit, unequal limits, load-vs-resume, and inherited-policy mismatches retain restore_in_progress behavior.

The design, implementation checklist, and bilingual PR description are synchronized. Prettier and git diff --check pass, followed by two consecutive clean broad-audit passes.

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Review notes from checking this design against current main (post-#8691) and the v0.21.6 load path. One in-scope question for this phase, plus forward requirements for the deferred checkpoint phase that seemed worth recording while this design is fresh.

In-scope for this phase: bounding event-loop blockage during the one full index scan

The design keeps "exactly one sequential full transcript index scan" on the ACP child and lists event-loop lag during the scan as benchmark evidence ("evidence, not a latency gate"). That measures the problem but does not bound it. The stream gives natural yield points at chunk boundaries, but parse/validate per chunk is unbounded CPU between I/O waits, and a single ~2 MiB record (present in the incident transcript) is one indivisible JSON.parse block. On a shared child, that is a stall window for live sibling sessions — the same class of cross-session impact this phase otherwise works hard to avoid (sibling continuity is even a benchmark row). If the 80 MiB fixture shows meaningful lag with a live sibling, consider explicit cooperative yields inside the scan loop (e.g. setImmediate every N records / M source bytes). It is cheap, has no protocol surface, and keeps "one scan" semantics intact. If the intent is to defer this to the checkpoint phase, stating that explicitly would close the gap.

Forward requirements for the checkpoint follow-up

The non-goals defer the durable sidecar/checkpoint. When that design starts, these constraints fall out of the current code and this phase's infrastructure:

  1. Schema version + discard-and-rebuild. Give the sidecar an explicit version field and drop-and-rebuild on mismatch rather than migrating. This composes with the legacy bootstrap path (sessions without a checkpoint get one built during/after their first successful load) since both are "build from a trusted full scan".
  2. Reuse existing atomic-publish and identity machinery. Publish with the repo's established write-then-rename pattern (bridgeFileSystem's BSA0D-style write, plus directory fsync) and bind the checkpoint to the transcript with SessionTranscriptReader's existing fileIdentity { dev, ino } + snapshot size rather than inventing a new identity scheme. This document's own residual-risk note — only a cooperative writer protocol closes the same-identity/same-mtime rewrite race — applies verbatim to sidecar publication; last-writer-wins rename plus validation-at-load is the pragmatic floor.
  3. Persist the uuid→{offset, length} index, not just snapshots. The reader's index is exactly what lazy /rewind reads need. Shipping it (or deltas of it) in the sidecar turns rewind-beyond-the-tail into O(1) seeks and keeps "unresolved parent outside the checkpoint" an exceptional fallback instead of the common post-rewind path.
  4. State the checkpoint invariant explicitly. Checkpoint = index covering [0, byteOffset) with active leaf ∈ index. Tail advance must resolve parentUuid against the checkpoint index, not only within the tail: after a rewind, new records append at the file tail with parents in mid-checkpoint territory. Writing this as an invariant up front prevents an implementation that scans "from the leaf" instead of "from the offset".
  5. Bound sidecar write amplification. The index portion of a 26k-record transcript is MB-scale. Publishing the full sidecar at every completed-turn / compression / rewind boundary is per-turn megabyte writes; the design needs incremental index append or index truncation to stay proportional to the tail.
  6. Make the fallback full scan cooperative too. The fallback streaming scan for legacy/corrupt/missing checkpoints has the same event-loop property as the in-scope question above; whatever yield policy this phase adopts should apply there from day one, since the fallback path is precisely where the largest transcripts land.

Already well covered (verified, no action)

  • The replay.kind mapping — bulk-with-historyPageSizerecent, bulk-without → all, legacy streamed → all, resume → none — matches current acpAgent behavior and correctly preserves unbounded visible replay for ACP clients that omit the field. The explicit "omitted vs explicit page size → restore_in_progress, no cross-shape coalescing" rule is the right call.
  • The goal-bootstrap split-brain analysis (recent page starting after the state-determining goal record) matches how goal_state records are actually reduced at load; requiring the bootstrap to match full HistoryReplayer precedence rather than inventing a parallel rule is the correct constraint.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Thanks for the careful follow-up. I agree with the in-scope scheduling concern and updated the design in 646002b6d7.

The selective reader now requires cooperative event-loop yielding in the shared full-scan primitive and in selected dispatch when cumulative selected work can also be transcript-proportional. It uses fixed internal source-byte and elapsed-processing budgets and yields with setImmediate only after a complete physical line or selected aggregate, so scan count, ordering, snapshot semantics, and production reducers do not change. Functional coverage must prove queued scheduler/sibling work progresses before a large restore settles; the 80 MiB benchmark tunes the internal budgets and reports event-loop lag as evidence rather than introducing a machine-dependent CI latency gate.

The limitation you identified is now explicit: cooperative yielding cannot preempt the synchronous parse/validation of the current physical record, so the approximately 2 MiB incident record remains one indivisible interval. Worker-thread parsing or a streaming JSON parser is intentionally out of scope for this slice.

I also recorded the checkpoint points as forward constraints without expanding this PR into a checkpoint design. The follow-up owns the exact versioned schema, transcript-prefix validation, persisted-index/incremental format, active-leaf/tail-parent invariant, bounded write amplification, and atomic publication. Existing file identity plus snapshot size is documented as a useful minimum rather than a complete defense against same-inode in-place rewrites, and legacy/corrupt/missing checkpoint fallback must reuse the cooperative scan policy.

The replay-kind/coalescing and Goal-bootstrap sections remain unchanged except for the already-agreed ingress/caller clarifications. The two design documents and bilingual PR description are synchronized; Prettier and git diff --check pass, followed by two consecutive clean broad-audit passes. The PR remains docs-only and Draft.

doudouOUC and others added 2 commits August 10, 2026 11:55
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

设计基线更新与审计结论

已在 commit 7791a21d2f 更新设计,并同步 PR body。本轮以 #8882 最新 head a6cdc44e6358929a1895762bbb0f1dbe96f0ac77 为代码基线,而不是继续依赖已关闭的 #8824 原型。

关键结论:

审计过程中修正了两项问题:一是最初未限定 #8882 的 modern/legacy capability 边界;二是“rebase onto #8882”可能误导实现直接叠在活跃 PR 上。修正后重新开始 clean-pass 计数,完成两轮连续全面审计,覆盖架构边界、失败路径、兼容性、测试策略、维护性、范围膨胀和更简单替代方案,未发现新的可行动问题。

验证:

  • npx prettier --check docs/design/2026-08-08-selective-session-restore.md docs/plans/2026-08-08-selective-session-restore.md:通过
  • git diff --check:通过
  • 本次提交仅修改上述两份设计/计划文档,无运行时变更。

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Prerequisite update: #8882 has merged. The remaining restore request-shape correctness fix is now isolated in Draft PR #8933, covering exact WebUI mode/page intent identity, page snapshotting across queue/retry, ACP bridge page-aware cold coalescing, ingress validation, and focused real-daemon regression coverage.

This PR remains docs-only and Draft. Commit 6e2446a updates the design, implementation plan, and bilingual PR description to mark #8882 complete, assign the shape fix to #8933, and keep projection mapping, limits, reader/cache, Goal/FileHistory/artifact, lifecycle, and validation work in the future selective implementation.

Next gate: merge #8933, then create the selective implementation Draft from fresh main containing both #8882 and #8933.

doudouOUC and others added 3 commits August 11, 2026 20:02
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Final broad-audit follow-up: commits e11bd51 and 1d3163b close two implementation ambiguities found while checking the design against the current production Goal evidence and ACP lifecycle code. Pending-checkpoint recovery now uses a two-stage shared selector/accumulator: bounded active-chain hints reproduce the production catalog and its malformed-context/turn-reentry fail-closed errors, then only selected evidence UUIDs are materialized. This prevents an implementer from choosing all active payloads or introducing a second scan. The selective finalizer now explicitly catches both synchronous invocation failures and asynchronous rejections for Goal activation and FileHistory validation, so neither can become an unhandled rejection or suppress the other action. The design, plan, and bilingual PR body are synchronized; Prettier and diff checks pass. After these fixes, two independent broad audit passes found no further actionable issue. The PR remains docs-only and Draft.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@yiliang114

Copy link
Copy Markdown
Collaborator

I've completed my review of this documentation-only PR. Here's my assessment:


Review Summary

PR #8743docs(design): Plan selective session restore

Verdict: No blockers. This is a well-structured, comprehensive design document and implementation plan. As a docs-only draft, there's no runtime code to verify.

What this PR does

Adds two new documentation files:

  • docs/design/2026-08-08-selective-session-restore.md (~1500 lines) — architecture design for replacing daemon cold-load full materialization with a selective projection
  • docs/plans/2026-08-08-selective-session-restore.md (~580 lines) — 5-phase implementation plan with a detailed acceptance checklist

Strengths

Observations (non-blocking)

  1. Density. The design doc is ~1500 lines without a TL;DR at the top. A 3-4 sentence summary in the header section would help future readers quickly understand the core idea (one cold projection + one live projection, cooperative scheduling, bounded replay envelopes).

  2. Maintainer sign-off gates. The design requires maintainer approval for the 256 MiB transcript cap and 32 MiB transformed-replay cap. The acceptance checklist tracks these ([ ]), but the implementation PR should make these gates explicit in its description so they're not overlooked during code review.

  3. Draft status. The PR is appropriately marked as Draft since it's a design doc awaiting review before implementation begins. The plan states the implementation branch should be created from fresh main containing fix(serve): Keep restore request shapes distinct #8933 — this is consistent with the draft state.

Verdict

No blockers. The design is thorough, boundaries are crisp, and the acceptance checklist provides a clear path to verifying the implementation when it arrives.

@doudouOUC

Copy link
Copy Markdown
Collaborator Author

Thanks for the thorough review. Agreed there are no blockers.

I’m leaving the docs unchanged in this round: the opening Scope and Context sections already provide the short orientation, and this Draft has been through several review cycles, so a density-only rewrite would add churn without changing the contract. The maintainer gates are already explicit in the design goals and implementation acceptance checklist; the implementation PR will also call out the 256 MiB transcript cap and 32 MiB transformed-replay cap in its description and request explicit sign-off.

@doudouOUC
doudouOUC marked this pull request as ready for review August 13, 2026 01:54
@doudouOUC
doudouOUC enabled auto-merge August 13, 2026 01:54
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: grounded, not theoretical. This is the design/plan PR for the next slice of #8678, and the underlying problem — the daemon cold path materializing the full transcript (twice when recording + writer lease are both on) before historyPageSize ever applies, plus synchronous whole-record parsing starving sibling sessions on the shared ACP child — is the same observed behavior the four merged prerequisite PRs (#8691, #8833, #8882, #8933) grew out of. The design's claims about current code are spot-checked in the review comment that follows this one.

Direction: aligned. Session restore cost is squarely inside the daemon/ACP core, and committing the design before the implementation is exactly what docs/design/ + docs/plans/ are for. All four stated prerequisites are verified merged (#8933 as 962dc8e, matching the body's claim). The doc describes future protocol surface (anchorRecordId, page limits) but adds none — and it explicitly defers the 256 MiB / 32 MiB compatibility caps to maintainer sign-off on the implementation PR, which is the right place for that decision.

Size: not applicable — docs-only, 2084 lines across two new markdown files, zero production logic lines. No core paths touched.

Approach: scope feels right for a plan PR — one design doc plus one implementation plan, implementation explicitly deferred to its own PR, no drive-by changes. One honest observation: the plan is exceptionally detailed, which is a strength for review now but means the implementation PR must be held to exactly these stated boundaries — the doc itself asks for that, including reporting its production-logic line count for maintainer scope review before proceeding.

Risk: no elevated risk signals — only docs/design/ and docs/plans/ files, none of the revert-correlated paths.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:有依据,不是理论性的。这是 #8678 下一个切片的设计/计划 PR,其底层问题——daemon 冷路径在 historyPageSize 生效前就全量物化 transcript(recording 与 writer lease 同时开启时会物化两次),以及共享 ACP child 上同步整记录解析饿死 sibling 会话——正是已合入的四个前置 PR(#8691#8833#8882#8933)所要解决的同一观测行为。设计中对现有代码的论断已在随后的审查评论中抽查核实。

方向:对齐。会话恢复成本完全在 daemon/ACP 核心范围内,而在实现前提交设计正是 docs/design/ + docs/plans/ 的用途。四个声明的前置均已核实合入(#8933 的 merge commit 为 962dc8e,与 PR 描述一致)。文档描述了未来的协议面(anchorRecordId、分页上限),但本 PR 不新增任何协议面——并且明确把 256 MiB / 32 MiB 兼容性上限留给实现 PR 的 maintainer sign-off,这个决定放那里是对的。

规模:不适用——纯文档,两个新增 markdown 文件共 2084 行,生产逻辑行数为零,不触及核心路径。

方案:作为计划 PR 范围合理——一份设计文档加一份实施计划,实现明确推迟到单独 PR,无顺手改动。一点坦率观察:计划细致得非同寻常,这对当前审查是优点,但也意味着实现 PR 必须严格对照这些声明的边界——文档本身也这样要求,包括在推进前报告生产逻辑行数以供 maintainer 范围审查。

风险:无升级风险信号——仅 docs/design/docs/plans/ 文件,未触及任何与 revert 相关的路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max

Reviewed at 4427b212b1dea1c1f713d97a5da91ce350e49f7a · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Code review

For a docs-only PR the review question is whether the design is sound and whether its claims about the current code are true. I spot-checked both.

The approach matches what the problem asks for: push paging down into the reader (one sequential index scan plus selected-record seeks instead of materialize-then-slice), keep the wire surface compatible (omitted historyPageSize stays full replay, envelope stays version 1 with an optional anchorRecordId), bound replay after transformation, and reuse #8691's existing reservation and rollback lifecycle rather than inventing a second ownership machine. Cooperative yielding uses fixed internal byte/time budgets at record boundaries instead of machine-dependent latency thresholds, which is the right call for CI. The doc is unusually disciplined about what it does not claim — the ~2 MiB single-record parse stays an explicit indivisible interval, lease-off identity races stay documented residuals, and the two compatibility caps (256 MiB cold restore, 32 MiB explicit-page replay) are flagged as intentional changes requiring maintainer sign-off on the implementation PR, not smuggled in here.

Claims about current code verified against main:

  • All referenced production symbols exist: SessionTranscriptReader, buildApiHistoryFromConversation(), recoverGoalFromRecords(), computeInitialTurnFromHistory(), estimateIndexCacheBytes(), reserveStartingSessionId(), createAndStoreSession()/discardStoredSessionIfCurrent(), buildGoalEvidenceCheckpointWindow(), readActiveTranscriptChain(), supersedeUnrestorableGoal, restoreGoalFromHistory(), activateChatRecording(), getGoalRuntimeReady(), validateRestoredSnapshots(). The proposed readRestoreProjection() is correctly absent (new API).
  • Numeric claims all check out: 256 MiB index cap, 4 MiB soft page budget, 16 MiB expansion ceiling, 64 KiB read chunks (session-transcript-reader.ts); MAX_BULK_REPLAY_UPDATES = 10_000 and LOAD_REPLAY_VERSION = 1 (acp-bridge); the 32 MiB REST response cap is indeed 2 × SESSION_TRANSCRIPT_MAX_EXPANDED_PAGE_BYTES in the transcript route.
  • The central problem claim holds: loadCliConfig() calls SessionService.loadSession() before Config construction, and Config performs a second authoritative loadSession() in the lease path — the duplicate full materialization is real.
  • ACP error codes -32010/-32011/-32012 and the transcript_too_large/transcript_page_too_large REST mappings already exist as described; invalid_transcript_limit and the fix(serve): Keep restore request shapes distinct #8933 bridge ingress validation of historyPageSize are where the doc says they are.

No critical blockers, no convention violations — the two files land in docs/design/ and docs/plans/ with the date-prefixed naming used by neighboring plans, and the implementation is explicitly deferred to its own PR with a delivery rule against landing an unused projection API.

Test evidence

CI on the reviewed commit, fetched via API (this run never executes PR code):

Final CI results for 4427b21 (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Classify PR ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Test (ubuntu-latest, Node 22.x) ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。

The repo's CI classifier routes same-repo docs-only PRs to a docs_only profile that skips the full build/lint/test matrix by design, so the skips above are expected, not a red flag — the ubuntu job ran and is green, as are both Desktop Shell builds. Remaining in-progress checks are bot orchestration (this triage and the review job), not PR CI.

Not verified: Prettier formatting of the two new markdown files. The docs_only profile does not run the prettier step, and this static review does not execute tools against the PR tree; the author states npx prettier --check passes locally (author's claim, not independently re-run). The diff's wrapping is consistent with the repo style, so this is a nit at most.

Real-scenario testing: N/A — documentation-only, nothing user-visible, and unattended runs do not drive the product.

中文说明

代码审查

对纯文档 PR,审查重点是设计本身是否合理、以及它对现有代码的论断是否属实。两点都做了抽查。

方案与问题所需一致:把分页下推到读取层(一次顺序索引扫描加 selected-record seek,而不是先全量物化再切片),保持协议兼容(省略 historyPageSize 仍是完整 replay,envelope 保持 version 1 仅新增可选 anchorRecordId),在变换后约束 replay 大小,并复用 #8691 已有的 reservation 与 rollback 生命周期而不是再造第二套 ownership 机制。协作式让出使用固定内部字节/时间预算且只在记录边界生效,而非机器相关的延迟阈值——对 CI 来说是正确的选择。文档对自己"不声明"什么异常克制:约 2 MiB 的单条记录 parse 保持明确不可分割区间,lease-off 身份竞态保持为已文档化的残余,两个兼容性上限(256 MiB 冷恢复、32 MiB 显式分页 replay)被标为需要在实现 PR 获得 maintainer sign-off 的有意变更,而不是在本 PR 里偷偷生效。

对现有代码的论断已在 main 上核实:

  • 所有引用的生产符号都存在:SessionTranscriptReaderbuildApiHistoryFromConversation()recoverGoalFromRecords()computeInitialTurnFromHistory()estimateIndexCacheBytes()reserveStartingSessionId()createAndStoreSession()/discardStoredSessionIfCurrent()buildGoalEvidenceCheckpointWindow()readActiveTranscriptChain()supersedeUnrestorableGoalrestoreGoalFromHistory()activateChatRecording()getGoalRuntimeReady()validateRestoredSnapshots()。提议的 readRestoreProjection() 正确地尚不存在(新 API)。
  • 数字论断全部吻合:256 MiB 索引上限、4 MiB 软分页预算、16 MiB 扩展上限、64 KiB 读取块(session-transcript-reader.ts);MAX_BULK_REPLAY_UPDATES = 10_000LOAD_REPLAY_VERSION = 1acp-bridge);32 MiB REST 响应上限确实是 transcript 路由中的 2 × SESSION_TRANSCRIPT_MAX_EXPANDED_PAGE_BYTES
  • 核心问题论断成立:loadCliConfig() 在构造 Config 前调用 SessionService.loadSession()Config 在 lease 路径还会做第二次权威 loadSession()——重复全量物化确实存在。
  • ACP 错误码 -32010/-32011/-32012 与 transcript_too_large/transcript_page_too_large REST 映射已如文档所述存在;invalid_transcript_limitfix(serve): Keep restore request shapes distinct #8933 的 bridge 入口 historyPageSize 校验也在文档所述位置。

无关键阻塞项,无约定违规——两个文件落在 docs/design/docs/plans/,采用与相邻计划一致的日期前缀命名,实现明确推迟到单独 PR,并附有禁止落地未使用 projection API 的交付规则。

测试证据

被审查提交上的 CI,通过 API 获取(本审查从不执行 PR 代码)——见上方英文表格。仓库 CI 分类器将同仓库纯文档 PR 路由到 docs_only 档位,按设计跳过完整 build/lint/test 矩阵,所以上述 skipped 属预期而非异常信号——ubuntu 作业已运行且为绿,两个 Desktop Shell 构建也为绿。其余进行中的检查是 bot 编排作业(本 triage 与 review 作业),不是 PR CI。

未验证:两个新 markdown 文件的 Prettier 格式。docs_only 档位不运行 prettier 步骤,本静态审查也不对 PR 树执行工具;作者声明 npx prettier --check 本地通过(作者声明,未独立复核)。diff 的换行风格与仓库一致,因此至多是个 nit。

真实场景测试:N/A——纯文档,无用户可见变化,无人值守运行不驱动产品。

Qwen Code · qwen3.8-max

Reviewed at 4427b212b1dea1c1f713d97a5da91ce350e49f7a · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 5/5 — clean across every stage; the design's claims verify against the code, and the only verification gap (prettier) is a property of the docs_only CI profile, not this PR.

Stepping back: this is what a plan PR should look like. Before reading the diff, my own sketch for this problem was "push paging into the reader with one index scan plus selected seeks, keep the wire compatible, yield cooperatively at record boundaries, reuse the existing reservation lifecycle" — the design matches that on every point and then goes further than I would have in pinning down the ugly corners: the Goal pending-checkpoint evidence window, the legacy Goal migration write racing a later replay overflow, the process-global attribution singleton that cannot be rolled back safely, and the parent/child publication gap it explicitly declines to fix here. The alternatives-considered section rejects each simpler-sounding path for a stated reason, and each rejection holds up (post-load paging doesn't fix the cold path; defaulting every client to a recent page would silently change ACP semantics; a full-loader fallback would route the worst input through the least bounded path).

Every specific claim I checked against main is accurate — symbols, constants, error codes, and the double full-materialization that motivates the whole slice. The doc is dense, but that density is the point: it exists so the implementation PR can be held to falsifiable boundaries, and it builds its own gates in (production-logic line count reporting, maintainer scope review, explicit sign-off on both compatibility caps). Merging it commits the repo to nothing except a well-argued plan; the hard decisions are correctly deferred to the implementation PR.

If I had to maintain this in six months, I'd thank whoever wrote it before starting the implementation — the acceptance checklist alone is worth the merge.

Approving, pinned to the reviewed commit. ✅

中文说明

置信度:5/5 —— 每个阶段都干净;设计对现有代码的论断均已核实,唯一的验证缺口(prettier)是 docs_only CI 档位的属性,不是本 PR 的问题。

退一步看:这是一份计划 PR 应有的样子。在读 diff 之前,我自己对这个问题的方案是"把分页下推到读取层,一次索引扫描加 selected seek,保持协议兼容,在记录边界协作式让出,复用现有 reservation 生命周期"——设计与我的方案在每一点上一致,并且在棘手角落上比我考虑得更深:Goal pending-checkpoint 证据窗口、legacy Goal 迁移写入与后续 replay 溢出的竞态、无法安全回滚的进程级 attribution 单例,以及它明确声明不在本切片修复的 parent/child 发布缺口。备选方案一节对每条看似更简的路径都给出了拒绝理由,且每条都站得住(load 之后分页修不了冷路径;默认所有客户端 recent 分页会悄悄改变 ACP 语义;回退全量 loader 会让最坏输入走最不设防的路径)。

我对照 main 抽查的每一个具体论断都准确——符号、常量、错误码,以及驱动整个切片的双重全量物化。文档很密,但这正是重点:它的存在就是为了让实现 PR 可以被对照可证伪的边界来审查,而且它自带了门(报告生产逻辑行数、maintainer 范围审查、两个兼容性上限的显式 sign-off)。合入它不代表仓库承诺任何东西,只是一份论证充分的计划;艰难的决定被正确地推迟到实现 PR。

如果六个月后我要维护它,我会在开始实现前感谢写下它的人——光是验收清单就值得这次合入。

批准,钉在被审查的提交上。✅

Qwen Code · qwen3.8-max

Reviewed at 4427b212b1dea1c1f713d97a5da91ce350e49f7a · re-run with @qwen-code /triage

@qwen-code-ci-bot qwen-code-ci-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, looks ready to ship. ✅

@qwen-code-ci-bot qwen-code-ci-bot added the type/documentation Documentation improvements or additions label Aug 13, 2026
@doudouOUC doudouOUC changed the title docs(design): Plan selective session restore docs(design): Define selective session restore Aug 13, 2026

@yiliang114 yiliang114 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved — docs-only design contract, verified against current main.

Consistency with the merged series (checked against code):

  • Prerequisite claims hold: #8691, #8833, #8882 merged; #8933 merged as 962dc8e exactly as the doc states.
  • Every numeric limit cited matches main: 256 MiB SESSION_TRANSCRIPT_MAX_INDEX_BYTES, 4 MiB page budget, 16 MiB expansion ceiling (session-transcript-reader.ts), the 32 MiB REST serializer cap (WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 2 * 16 MiB), and the bridge MAX_BULK_REPLAY_UPDATES = 10_000 validated post-transport as the doc describes.
  • Error contract matches merged code: ACP -32010/-32011/-32012 with transcript_snapshot_unavailable / transcript_too_large / transcript_page_too_large, REST 409/413 mapping, and 400 invalid_transcript_limit all exist as referenced.
  • #8933 semantics are represented correctly: historyReplay omission defaults to 'stream', in-flight coalescing compares shapes, non-identical shapes conflict with restore_in_progress, superseded raw results are permanently fenced while same-shape timeout retry survives. The design consumes these boundaries rather than re-declaring them, and keeps the fail-closed direction throughout (no fallback to the old loader, no empty-fallback degradation, typed limit errors bypass the partial/replayError downgrade).
  • All ~19 referenced identifiers (computeInitialTurnFromHistory, recoverGoalFromRecords, reserveStartingSessionId, discardStoredSessionIfCurrent, createAndStoreSession, estimateIndexCacheBytes, validateRestoredSnapshots, supersedeUnrestorableGoal, etc.) exist in current main; the loadCliConfig() pre-Config full load and the live write-barrier full reload in acpAgent.ts are accurately described.

Doc quality: internally consistent — projection acquisition modes, one-shot release discipline, consumer migration table, and failure-semantics table agree with each other; acceptance criteria are measurable (exact 32 MiB / 10,000-update boundary tests, one-scan assertions, deterministic cooperative-scheduling tests) and disclosure channels are named. Shipped vs planned work is cleanly separated, and both intentional compatibility changes (256 MiB cold-restore cap, 32 MiB transformed-replay cap) are explicitly gated on maintainer sign-off.

Nit (non-blocking): the status snapshot (head 2026-08-12T02:18Z) predates #8939 and #8955 (merged later that day) and doesn't note #8883 already merged. No contradiction — those touch WebUI refresh / prompt-admission surfaces this design explicitly disclaims, and the delivery rule already requires branching from fresh main — but worth refreshing the prerequisite-status line when implementation starts.

CI: 59/59 checks green/skipped on head sha.

@doudouOUC
doudouOUC added this pull request to the merge queue Aug 13, 2026
Merged via the queue into main with commit abfd443 Aug 13, 2026
76 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.21.11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/documentation Documentation improvements or additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants