Skip to content

fix(session): recover transcript streams and virtualize activity feed (ZER-673) - #45

Closed
ZeroPointSix wants to merge 7 commits into
mainfrom
h15002710886/zer-673-w5-recovery-long-session
Closed

fix(session): recover transcript streams and virtualize activity feed (ZER-673)#45
ZeroPointSix wants to merge 7 commits into
mainfrom
h15002710886/zer-673-w5-recovery-long-session

Conversation

@ZeroPointSix

@ZeroPointSix ZeroPointSix commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Restore the session detail feed in the required order: transcript snapshot, tail replay, then live SSE.
  • Capture the snapshot and unified SSE cursor atomically so the hand-off cannot lose events; stable entry_id values upsert streamed text and tool revisions.
  • Render long session activity through react-virtuoso, expose end-to-end SSE latency, and surface cursor resets, history gaps, and stream lag as explicit recovery states.
  • Clear all visible transcript state before a session route changes, so a failed or slow B snapshot never displays A's activity under B's metadata.

Review Contract

Goal

Deliver ZER-673's resilient session transcript recovery and long-session activity feed: snapshots must resume safely into replay/live SSE, and transcript rendering must remain responsive for 1,000+ entries.

Non-goals

This PR does not change agent execution semantics, transcript retention capacity, authentication policy, or the server-side protocol beyond exposing the atomic shared-stream cursor already required by the recovery hand-off. It does not introduce write or mutation controls to the read-only session feed.

Accepted Residual Risks

The activity feed remains dependent on the bounded server replay history. When a cursor reset, history gap, or stream lag is detected, the UI intentionally stops live processing and asks the operator to reload a full snapshot instead of silently reconstructing uncertain state. The current production bundle-size warning is pre-existing/non-blocking and is not addressed here.

Acceptance Criteria

  • Session details restore in the order full transcript snapshot, transcript tail, then live SSE using the snapshot's generation-qualified stream cursor.
  • A streamed transcript revision or tool lifecycle update replaces the matching stable entry_id instead of appending a duplicate row.
  • cursor_reset, event-history gaps, and stream lag show an explicit recovery action rather than silently omitting history.
  • Changing from session A to B clears A's transcript, latency observation, and recovery state before B's snapshot is displayed; a B snapshot failure cannot resurrect A's content.
  • The activity list uses virtualization for long transcripts.
  • Regression coverage includes transcript upsert/parsing, session switch reset behavior, and concurrent lifecycle publish with replay/subscribe completion under a timeout.

Follow-ups

  • Observe recovery alerts and end-to-end SSE latency in staging with long-running real sessions.
  • Consider a dedicated browser-level route-transition test once the web test environment includes DOM rendering support.
  • Review client-bundle code splitting separately from this resilience and correctness scope.

Verification

  • pnpm test — 43 tests passed.
  • pnpm lint
  • pnpm build
  • cargo test -p openab-core --no-default-features transcript::tests
  • cargo test -p openab-core --no-default-features session_event::tests
  • cargo test -p openab-gateway --no-default-features session_admin::tests

Closes ZER-673.

@linear-code

linear-code Bot commented Aug 13, 2026

Copy link
Copy Markdown

ZER-673

Copy link
Copy Markdown
Owner Author

Context fact card

Target

Verified facts

  • PR 当前 open、非 draft、mergeable,27 个文件,+3679/-371。
  • 实现新增 per-session transcript ring buffer、统一 session/transcript SSE cursor、snapshot/tail/live 恢复链,以及 react-virtuoso 活动流。
  • transcript snapshot 会原子捕获 shared stream generation/next sequence;前端使用 stable entry_id upsert streamed text/tool revisions。

Relevant code and tests

  • Core: session_event.rs, transcript.rs, adapter.rs
  • Gateway: session_admin.rs + admin integration tests。
  • Web: useSessionTranscript.ts, transcript.ts, SessionActivityFeed.tsx, SessionDetailPage.tsx
  • 已有测试覆盖 transcript chunk/tool upsert、history overflow、cursor capture、前端 entry upsert/解析;当前未看到并发锁顺序或 session A→B 切换时旧 transcript 清理的覆盖。

CI/CD and validation entrypoints

  • CI run #120: success。
  • Admin Web run #62: success。
  • Docker Smoke Test run #136: success。
  • Docker Smoke Test (Unified) run #143: 当前仍在运行。
  • Review Contract run #185: failure;PR 描述缺少 ## Review Contract 及 Goal / Non-goals / Accepted Residual Risks / Acceptance Criteria / Follow-ups 必需章节。

Assumptions not allowed

  • 不能因为单线程单测通过就假设 lifecycle publish 与 SSE replay/subscribe 不会并发。
  • 不能假设路由切换时新 session transcript 一定比 session metadata 更快返回。

Risks / blockers

  • 已发现 SessionEventBus 的 stream-history / lifecycle-history 锁获取顺序反转,存在并发死锁风险。
  • 正在确认 session 切换期间旧 transcript 暂留问题及其用户可见影响。
  • Review Contract 当前硬失败;Unified Docker Smoke 尚未完成。

Proposed change scope

  • 本轮仅审查,不修改实现;代码 blocker、验收缺口和 CI 状态会以中文 review 同步到本 PR。

@ZeroPointSix ZeroPointSix left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

审查结论:当前不建议合并

整体方案方向正确:transcript snapshot + tail + live SSE 的恢复顺序、shared stream cursor、stable entry_id upsert,以及 react-virtuoso 长列表虚拟化都覆盖了 ZER-673 的主要目标;CIAdmin Web、普通 Docker Smoke Test 也已通过。

但当前有两个代码 blocker,外加一个合并门禁 blocker:

  1. [高] SessionEventBus 存在锁顺序反转,可能并发死锁。

    • publish() 先通过 stream.publish_session() 获取 SessionStreamHistory mutex,释放后再获取 lifecycle SessionEventHistory mutex;更关键的是 publish 路径与 transcript/cursor 路径建立了 stream→history 的顺序。
    • subscribe_after() / replay_after() 当前先持有 lifecycle history mutex,再调用 self.stream.next_sequence() 获取 stream history mutex,即 history→stream。
    • 在并发 lifecycle publish 与 replay/subscribe 时形成 ABBA 锁顺序,存在请求/SSE 建连卡死风险。现有 session_event::tests 都是串行功能测试,没有并发锁顺序覆盖。
    • 建议不要在持有 lifecycle history 锁时调用 stream.next_sequence();先获取 next sequence 后再锁 lifecycle history,或统一所有路径的锁顺序,并补并发回归测试(带 timeout)。
  2. [中] session A→B 路由切换时会保留旧 transcript,可能短暂展示错误会话内容。

    • useSessionTranscript() 只有 sessionId 为空时才清 entries;非空 A 切到非空 B 时,effect 开始恢复 B,但旧的 entriesRef/current entries 保持到 B 的 transcript snapshot 返回。
    • SessionDetailPage 的 session metadata 与 transcript 是独立请求;如果 B 的 metadata 先完成,页面会渲染 B 的标题/元数据,同时活动流仍是 A 的内容,直到 transcript 请求完成。若 B transcript 请求失败,旧内容还可能一直留在 recovery banner 下。
    • 建议 sessionId 变化后、发起 snapshot 前立即清空 entries/latency,并增加 A→B 切换与 snapshot failure 的 hook/component 测试。
  3. [门禁] Review Contract 当前失败。

    • run #185 明确报缺少 ## Review Contract### Goal### Non-goals### Accepted Residual Risks### Acceptance Criteria### Follow-ups
    • PR 描述目前只有 Summary / Verification,因此即使代码问题修复,也还不能满足仓库合并门禁。

CI 状态

  • CI #120: success
  • Admin Web #62: success
  • Docker Smoke Test #136: success
  • Review Contract #185: failure
  • Docker Smoke Test (Unified) #143: in progress

验收缺口

  • 需要补统一 stream 的并发 publish + subscribe/replay 无死锁测试。
  • 需要补 session A→B 切换时旧 transcript 不可见、B snapshot 失败也不会保留 A 内容的测试。
  • Review Contract 需补齐后重新过门禁。
  • 最终合并前还需要等待 Unified Docker Smoke 完成并确认绿色。

因此当前结论是:先修上述两个代码 blocker + Review Contract,再复审;暂不合并。

Copy link
Copy Markdown
Owner Author

Execution summary

Problem

  • 审查 ZER-673 transcript 恢复、统一 SSE cursor、长会话活动流虚拟化实现。

Root cause / verified facts

  • 统一 stream 接入后,SessionEventBus 的 publish 与 replay/subscribe 路径存在 lifecycle history / stream history 锁顺序反转,带来并发死锁风险。
  • useSessionTranscript() 在非空 sessionId A→B 切换时不会先清空旧 entries;metadata 与 transcript 独立加载时可能把 A 的活动流短暂显示在 B 页面,snapshot 失败时旧内容可能继续残留。
  • 当前 Review Contract run #185 失败,PR 描述缺少全部必需 Review Contract 章节。

Solution

  • 本轮仅审查,未修改代码。
  • 建议统一 mutex 获取顺序,并增加并发 publish + subscribe/replay timeout 回归测试。
  • 建议 sessionId 变化时在 snapshot 前立即清空 transcript/latency,并增加 A→B 与 snapshot failure 测试。
  • 补齐 PR Review Contract。

Files reviewed

  • Core: session_event.rs, transcript.rs, adapter.rs, ACP protocol/profile pool 相关变更。
  • Gateway: session_admin.rs 与 admin API integration。
  • Web: useSessionTranscript.ts, transcript.ts, SessionActivityFeed.tsx, SessionDetailPage.tsx 及相关测试。

Validation

  • PR 自报:pnpm test 42 passed;pnpm lintpnpm build;Core transcript/session_event tests;Gateway session_admin tests。
  • GitHub Actions:CI #120 success,Admin Web #62 success,Docker Smoke Test #136 success。

CI/CD

  • Review Contract #185: failure
  • Docker Smoke Test (Unified) #143: in progress(本次复核时)。

Remaining risks / follow-ups

  • 两个代码 blocker 修复并补回归测试后需复审。
  • Review Contract 必须转绿。
  • Unified Docker Smoke 完成并转绿后再考虑合并。

当前结论:不建议合并。 Review 4922739281 已提交。

ZeroPointSix pushed a commit that referenced this pull request Aug 13, 2026
Combine transcript recovery and virtualized activity feeds with the all-open-PR session validation branch.
@ZeroPointSix

Copy link
Copy Markdown
Owner Author

已由 #46 的干净 ZER-404 W1–W5 只读工作台整合替代。#46 从最新 main 按依赖顺序重建,保留本 PR 的有效能力并补齐跨包冲突、活动流接线、恢复链与最新回归修复;原分支保留供历史追溯。

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant