Skip to content

feat(session): add transcript store and read-only stream - #34

Closed
ZeroPointSix wants to merge 2 commits into
mainfrom
h15002710886/zer-670-w3-transcript-store
Closed

feat(session): add transcript store and read-only stream#34
ZeroPointSix wants to merge 2 commits into
mainfrom
h15002710886/zer-670-w3-transcript-store

Conversation

@ZeroPointSix

@ZeroPointSix ZeroPointSix commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes ZER-670

Review Contract

Goal

Provide a read-only, per-session transcript contract that preserves real ACP tool payloads for W4 consumers while retaining one shared SSE cursor for lifecycle and transcript events.

Non-goals

This PR does not implement the W4 transcript UI, persist transcript data across process restarts, or redesign the existing lifecycle SSE endpoint beyond adding transcript events to its shared cursor.

Accepted Residual Risks

Transcript and stream histories are bounded in memory. A client that reconnects behind the retained cursor must handle the existing history-gap/cursor-reset response by refetching a snapshot; long streaming replies still duplicate accumulated text within the bounded replay history.

Acceptance Criteria

  • tool_call and tool_call_update retain raw ACP fields, including tool input, output, terminal data, and file-diff payloads, under a stable toolCallId.
  • Assistant chunk revisions include a stable entry_id, distinct from the per-session mutation cursor, so clients can upsert revisions.
  • GET /api/v1/sessions/{session_id}/transcript?after=<sequence> and GET /api/v1/sessions/events retain their snapshot, replay, history-gap, and Last-Event-ID contracts.
  • Transcript retention configuration does not alter lifecycle event-history capacity.

Follow-ups

W4 will render the preserved tool payloads as Terminal and FileDiff cards. W5 can optimize long-output memory behavior and decide whether transcript persistence is required. Rebase against PR #33 before merging if its overlapping session/SSE changes land first.

Summary

  • Preserve complete ACP tool_call and tool_call_update objects during classification and upsert them by toolCallId into the read-only transcript.
  • Add a stable entry_id for assistant and tool revisions; sequence remains the snapshot mutation cursor and SSE events keep their separate global cursor.
  • Keep transcript retention independent from lifecycle and unified-SSE history capacity.
  • Add a JSON-RPC classifier-to-transcript regression test covering raw input, output, and file-diff payloads.

Validation

  • cargo clippy --workspace -- -D warnings
  • cargo test -p openab-core --no-default-features — 542 passed
  • cargo test -p openab-gateway --test admin_api_integration --no-default-features — 13 passed

A full cargo test --workspace run was started after the strict Clippy check but was stopped locally after prolonged high memory use during final test binary linking; targeted core and gateway coverage above completed successfully.

@linear-code

linear-code Bot commented Aug 12, 2026

Copy link
Copy Markdown

ZER-670

ZeroPointSix commented Aug 12, 2026

Copy link
Copy Markdown
Owner Author

复审 Context fact card(上下文事实卡)

Target

  • 仓库:ZeroPointSix/openab-plus
  • PR:feat(session): add transcript store and read-only stream #34 feat(session): add transcript store and read-only stream
  • 目标:复核上一审阻塞项是否已修复,并判断当前可合并性
  • Base:main @ a03d9de5dd1853bf9efcce6e999374d8f2ab09ef
  • 当前 head:3b3bf604b95ac3c3d24ef63d01e1078cee73dcbc

Verified facts

  • 相对上一审 head baf08bd86f1a007d1b0bff2a37dd2e6cde872450 新增 1 个修复 commit:fix(session): preserve transcript tool payloads
  • ACP classifier 现在在 ToolStart / ToolDone 中携带完整 raw update payload,不再只压缩成 {id,title,status};adapter 也把该 payload 传入 transcript store。
  • assistant streaming entry 现在有稳定 entry_id;tool entry 以稳定 toolCallId upsert。
  • transcript、lifecycle event bus、unified stream history 的 capacity 已解耦,不再共用 transcript capacity。
  • TranscriptEntryDraft 等重构已解决上一审 clippy too_many_arguments 问题。
  • PR body 已补齐 Review Contract;exact-head Review Contract 为 success。
  • fix: repair session detail history and source links #33 当前仍 open、未合并,因此本轮尚不存在“fix: repair session detail history and source links #33 已进 main 但 feat(session): add transcript store and read-only stream #34 未 rebase”的额外阻塞。

Relevant code and tests

  • crates/openab-core/src/acp/protocol.rstool_call / tool_call_update 现在保留完整 ACP update payload。
  • crates/openab-core/src/adapter.rs:新增 record_acp_event_transcript,真实 classifier → adapter → store 路径已覆盖测试。
  • crates/openab-core/src/transcript.rs:tool payload 会浅合并进 tool_call;终态时另外生成/合并 tool_result
  • 已新增真实 ACP notification 回归测试,覆盖 initial tool call + completed update 同时携带 result/terminal/diff 的场景。

CI/CD and validation entrypoints

  • exact-head CI:success;其中 cargo check --workspace、两套 clippy(含 unified)、cargo test --workspace、ACP gateway tests、cargo build --features unified 均通过。
  • Review Contract:success。
  • Docker Smoke Test:success。
  • Docker Smoke Test (Unified):当前仍 in progress。

Assumptions not allowed

  • 不能假设 ACP 的最终 tool_call_update 一定重复发送此前所有 result/content 字段。
  • 仓库 ACP schema 明确规定:ToolCallUpdatesessionIdtoolCallIdsessionUpdate 外其余字段均可选,调用方只需要发送“本次发生变化的字段”。因此“中间 update 带 output/diff,最终 completed update 只带 status”是合法协议输入。

Risks / blockers

  1. 剩余阻塞:合法的 sparse tool_call_update 序列下,tool_result 仍可能丢失此前已经收到的结果内容。
    • 合法序列示例:
      1. tool_call:包含 rawInput
      2. tool_call_update(status=in_progress):包含 terminal/result/diff content;
      3. tool_call_update(status=completed):只包含 status
    • 当前实现中,第 2 步 payload 会累计进 entry.tool_call,但不会进入 entry.tool_result;第 3 步终态时,tool_result 只从第 3 步 payload 开始创建/合并。因此最终 tool_call 仍有完整聚合数据,但 tool_result 可能只剩 {status:"completed", ...},而此前的 terminal/result/diff 不在 tool_result 中。
    • 这与 W3 暴露独立 tool_call / tool_result 字段的语义不一致,也会让按 tool_result 消费结果的 W4 adapter 丢数据。
    • 现有回归测试没有覆盖这个协议允许的形状:测试把 completed 与 result/terminal/diff 放在同一个最终 update 中,所以无法发现该缺口。

Proposed change scope

  • 继续维护一个跨 tool update 的 result payload accumulator,或在 terminalize 时从已经完整合并的 tool aggregate 中构造 tool_result,而不是仅从最终 update 构造。
  • 增加 classifier → adapter → transcript store 的端到端回归:tool_call(rawInput)in_progress(result/terminal/diff)completed(status-only);断言最终 tool_result 仍包含此前结果内容。
  • 修复后重跑当前 CI 契约;如果 fix: repair session detail history and source links #33 届时已合并,再 rebase 并确认保留 fix: repair session detail history and source links #33 的 fresh SSE replay 语义。

Execution summary

Problem

  • 上一审三个主要 blocker 中,payload 主路径、clippy、Review Contract 已修;本轮发现 ACP 增量更新语义下 tool_result 的聚合仍不完整。

Root cause / verified facts

  • ACP ToolCallUpdate 是 patch-like:终态 update 可以只携带 status。
  • store 当前始终把每次 payload 合入 tool_call,但只有 completed=true 时才开始/继续合并 tool_result
  • 因而终态 status-only update 不会把先前 non-terminal update 的 result payload 自动带入 tool_result

Solution

  • tool_result 跨非终态与终态 update 保留结果相关 payload,并补 sparse-update 端到端测试。

Files changed

  • 本次仅审查,无代码修改。

Validation

  • 代码路径复核:classifier → adapter → transcript store。
  • ACP schema 复核:确认 update 字段除 ID/类型字段外均可选,只需发送变化字段。
  • exact-head 主 CI 已完成 success。

CI/CD

  • CI:success。
  • Review Contract:success。
  • Docker Smoke Test:success。
  • Docker Smoke Test (Unified):in progress。

Remaining risks / follow-ups

@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