Skip to content

feat(web): add AionUi-inspired session activity feed (ZER-671) - #32

Closed
ZeroPointSix wants to merge 2 commits into
mainfrom
fix/zer-671-aionui-activity-feed
Closed

feat(web): add AionUi-inspired session activity feed (ZER-671)#32
ZeroPointSix wants to merge 2 commits into
mainfrom
fix/zer-671-aionui-activity-feed

Conversation

@ZeroPointSix

@ZeroPointSix ZeroPointSix commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

This PR implements the W4 presentation layer for the session activity stream with a fixed mock transcript, without waiting for the W3 transport implementation. The session detail view now uses a continuous Coding Agent-style stream rather than a conventional left/right chat bubble timeline.

The implementation adapts AionUi's Apache-2.0 tool-call normalization pattern to Ant Design, adds expandable read-only tool cards, terminal output, and bounded file-diff hunks, and regenerates the tracked web build assets.

Review Contract

Goal

Provide a usable, source-adapted W4 activity-feed renderer in the session detail page. It must render a fixed transcript containing user and assistant text, collapsed thinking, plans, turn boundaries, tool calls, terminal output, errors, and file diffs. Tool-call cards must expose status, summary, input, output, duration, and every ACP diff item without hiding changes in large files.

Non-goals

This PR does not implement the ZER-670 W3 snapshot API, the SSE transport, a W3-to-ActivityEntry adapter, any session mutation controls, permission approval, terminal termination, input composition, or AionUi's Electron and local-file-system integrations. It does not attempt a general-purpose full diff engine; snapshots are rendered as bounded readable hunks.

Accepted Residual Risks

The page remains mock-backed until W3 exposes a stable transcript contract, so production transcript payload compatibility cannot yet be verified end to end. The typed ActivityEntry boundary and ACP normalizer isolate this risk; if the W3 contract differs, the follow-up adapter can translate at that boundary without changing the rendered components. Extremely large single replacements are deliberately bounded to 240 changed lines to protect browser responsiveness; the preview keeps both leading and trailing changed lines and clearly reports omitted material, while the complete source remains available from the originating tool result.

Acceptance Criteria

  1. The fixed mock transcript renders all required W4 entry types and uses a continuous activity stream rather than traditional chat bubbles.
  2. Tool cards render pending/running/completed/error/canceled state, concise summaries for supported tool kinds, expandable inputs and outputs, terminal output, and one or more file diffs.
  3. ACP update.content arrays containing one or more diff items normalize into visible diff models.
  4. A 500-line file with a change at line 400 retains that changed line in the preview; bounded previews do not allocate a full line-by-line LCS matrix.
  5. Apache-2.0 source attribution and OpenAB Plus modification notices remain in each adapted source file.
  6. pnpm lint, pnpm test, pnpm build, and git diff --check pass.

Follow-ups

ZER-670 will supply the live snapshot and SSE contract plus a W3-to-ActivityEntry adapter. A later product decision may add an explicit deep-diff viewer or artifact download for cases where bounded preview output is insufficient.

Validation

Command Result
pnpm lint Passed
pnpm test Passed: 8 files, 38 tests
pnpm build Passed; tracked web assets regenerated
git diff --check Passed

Review follow-up addressed

The latest review identified two concrete defects and a contract validation failure. The update now preserves every diff item in real ACP update.content arrays and renders all of them in the tool card. FileDiff now builds a bounded common-prefix/common-suffix hunk rather than constructing an O(n×m) LCS matrix or slicing away remote edits. Regression tests cover ACP multi-diff input, a 500-line change at line 400, new files, and oversized replacements. This description now includes the required Review Contract sections.

@linear-code

linear-code Bot commented Aug 12, 2026

Copy link
Copy Markdown

ZER-671

Copy link
Copy Markdown
Owner Author

Context fact card(上下文事实卡)

Target

Verified facts

  • ZER-671 明确允许 W4 先用固定 mock transcript,不必等待 W3 实现;真实 snapshot/SSE 接入属于后续步骤,因此“当前页面仍是 mock”本身不是本次阻塞项。
  • 当前 head:896392aadfa9c51cdace62a334a2ebc9575749d2,相对 main ahead 1 / behind 0。
  • Admin Web workflow 已成功,覆盖 type-check、Vitest、profile schema smoke、build、生成资产一致性检查以及 Gateway embedding test。
  • 但 exact-head 的 Review Contract 当前为 failure;PR body 缺少仓库要求的 ## Review Contract### Goal### Non-goals### Accepted Residual Risks### Acceptance Criteria### Follow-ups

Relevant code and tests

  • 重点检查:normalizeToolCall.tsAcpToolCallCard.tsxFileDiff.tsxTerminalOutput.tsxSessionActivityFeed.tsxmockTranscript.tsSessionDetailPage.tsx
  • 当前新增测试只覆盖 status/摘要、直接 output diff 对象,以及 ACP 文本输出;没有覆盖 ACP update.content 中的 diff 数组,也没有覆盖长文件 diff。

CI/CD and validation entrypoints

  • 仓库入口:pnpm --dir web lintpnpm --dir web testpnpm --dir web test:profile-schemapnpm --dir web build、生成资产 diff 检查、cargo test -p openab-gateway web_admin
  • 远端 Admin Web 已通过;本地执行环境无法解析 github.com,因此没有重复 clone/执行完整仓库测试。下面两个问题通过代码路径和最小复现确认。

Assumptions not allowed

  • 不把 AionUi 的 content.update 消息形状视为已经等同于 W3 的 TranscriptEntry;ZER-670 仍需要独立的 W3 → ActivityEntry adapter。
  • 不以 mock 能显示 diff 推断真实 ACP diff 路径也能显示。

Risks / blockers

  1. 阻塞:ACP diff 在 normalizer 路径被丢失。 normalizeAcpToolCall()update.content(AionUi 中是数组)传给 normalizeToolCall(),但 diffFromContent() 只接受单个对象。结果真实 { type: 'diff', path, old_text, new_text } item 只会被 outputFromContent() 转成 [diff] path 文本,tool.diff 仍为 undefined,而 AcpToolCallCard 只有 tool.diff 存在时才渲染 <FileDiff />。mock 之所以正常,是因为它走的是 output 直接为 diff 对象的另一条路径。建议补 ACP diff 测试并把 diff item 真正归一化进模型;同时考虑 AionUi content 可含多个 diff,而当前模型只有单个 diff?: FileDiffPayload
  2. 阻塞:FileDiff 的 280 行截断会隐藏真正修改。 当前算法保留所有 unchanged context,然后直接 lines.slice(0, 280)。最小复现:500 行文件只修改第 400 行时,首个 changed entry 位于结果 index 399,前 280 行全部是 context,UI 会显示“预览仅显示前 280 行”,但用户完全看不到改了什么。AionUi 原实现生成 unified diff 并只保留变更附近 context;这里应改成 hunk/context 形式,截断时必须保留变更行。
  3. 性能风险(与 2 同源): buildLineDiff() 在截断之前先构造 (oldLines+1) × (newLines+1) 的完整 Uint16 LCS 矩阵,时间/内存均为 O(n×m)。仅 10k×10k 行矩阵本体约 190.8 MiB,还不含 JS/DOM 开销。长会话接真实文件编辑后有明显卡死风险,建议避免全矩阵 LCS,或在计算前做严格上限/分块,并优先采用 unified hunks。
  4. 流程阻塞:Review Contract 失败。 需要补齐 PR body 的必需章节(或由维护者明确使用 exemption label),编辑 PR body 会触发该 workflow 重新验证。

Proposed change scope

  • 修正 ACP diff normalization,并增加对应单测(至少覆盖单 diff;若模型支持多 diff,则覆盖多项)。
  • 重做 FileDiff 为以变更 hunk 为中心的有限上下文预览,避免“先全量 LCS、后截断”。
  • 补一个“500 行、修改第 400 行仍能看到 changed line”的测试,以及空文件/新建文件边界测试。
  • 补齐 Review Contract。

Execution summary

Problem

  • 当前 PR 的 UI 主体方向符合 ZER-671,但真实 diff 数据路径和长文件 diff 展示存在可复现缺口,且仓库 Review Contract 未通过。

Root cause / verified facts

  • mock 使用直接 diff object,绕开了 ACP 数组路径。
  • FileDiff 使用完整 LCS + 全 context + 前 280 行切片,截断策略与 diff 语义不匹配。

Solution

  • 建议修完上述 1/2 两个代码阻塞项并补测试,再处理 Review Contract 后合并。

Files changed

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

Validation

  • Admin Web:success。
  • 最小复现:ACP diff array → diff 未生成、仅得到 [diff] path;500 行文件修改第 400 行 → 前 280 行无任何 changed entry。

CI/CD

  • Admin Web:通过。
  • Review Contract:失败(PR body 缺必需章节)。

Remaining risks / follow-ups

  • ZER-670 的 W3 → ActivityEntry adapter 仍需单独实现;当前 AionUi normalizer 不应被视为已完成 W3 contract 对接。
  • 结论:暂不建议合并

ZeroPointSix commented Aug 12, 2026

Copy link
Copy Markdown
Owner Author

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

Target

Verified facts

Relevant code and tests

  • web/src/components/activity/FileDiff.tsx 当前仍使用:
    1. 全局 common prefix;
    2. 全局 common suffix;
    3. 将二者之间全部内容拼成 removed[] + added[]
    4. 超过 MAX_CHANGED_LINES = 240 时只保留该数组前 120 / 后 120。
  • 这不是 multi-hunk diff:两个真实修改之间的大段 unchanged 行也被当成 changed region,占用 240 行预算。
  • FileDiff.test.ts 仍只覆盖:单个远端修改、新文件、整段大 replacement;没有 sparse multi-hunk 回归测试。

CI/CD and validation entrypoints

  • Admin Web:success。
  • Review Contract:success。
  • 由于 head 未变化,没有新的代码可供 CI 验证 sparse multi-hunk 场景;现有测试本身缺该 case。

Assumptions not allowed

  • 不能因为单个 line-400 回归测试通过,就推断多个相距很远的修改都会保留。
  • 不能把 boundedChanges() 的“首尾各保留一半”理解为“每个真实 changed region 都被保留”。

Risks / blockers

  1. [阻塞] sparse multi-hunk 仍会隐藏真实修改。

    • fresh reproduction:构造 1000 行文件,只修改第 100、500、900 行。
    • 当前 buildHunkPreview() 结果:
      • 第 100 行:removed 可见,但对应 added 不可见;
      • 第 500 行:removedadded 都不可见
      • 第 900 行:added 可见,但对应 removed 不可见。
    • 同时 UI 生成 … 1362 changed lines omitted from preview,尽管实际只有 3 个稀疏位置发生修改。
    • 根因仍是全局 prefix/suffix 把第一个修改到最后一个修改之间所有 unchanged 行都塞进 changed 数组,再按数组首尾截断。
    • 这与 PR Review Contract 中“every ACP diff item without hiding changes in large files”的目标不一致。
  2. [非阻塞 follow-up] no-op snapshot 仍不 bounded。

    • old_text === new_text 时直接 pairedContext(..., before.length) 返回整文件 context;如果上游产生超大 no-op diff,预览仍可能很大。建议和 multi-hunk 修复一起加边界。

Proposed change scope

  • FileDiff 改为真正的 multi-hunk / changed-region 预览:每个分离的修改区域保留有限 context;总输出仍可 bounded,但必须确保每个真实 changed region 至少有可见修改。
  • 补至少一个 1000 行、修改 100/500/900 三处且三处均可见的 regression test。
  • 建议再补 no-op 大文件 bounded test。
  • 不需要回退已经正确修复的 ACP diffs[] normalization、Review Contract 或 O(n×m) LCS 移除。

Execution summary

Problem

  • 三审唯一代码 blocker 在当前 head 上仍存在;本次没有新提交可以改变该结论。

Root cause / verified facts

  • buildHunkPreview() 只保留 global prefix/suffix,不识别多个独立 hunk;boundedChanges() 对被夸大的 changed region 做首尾截断,导致中间真实修改消失。
  • 现有测试没有覆盖 sparse multi-hunk。

Solution

  • 本次仅复审,无代码修改。建议实现真正的 bounded multi-hunk preview 并补 sparse regression test 后再复审。

Files changed

  • 无;review-only。

Validation

  • fresh minimal reproduction:1000 行只改 100/500/900,line 500 的 removal/addition 均不在 preview,且显示 1362 changed lines omitted
  • Admin Web exact-head:success。
  • Review Contract exact-head:success。

CI/CD

  • Admin Web run 31581234370:success,所有 verify steps 通过。
  • Review Contract:success。

Remaining risks / follow-ups

四审结论:Request Changes / 暂不建议合并。当前只剩一个明确代码 blocker:sparse multi-hunk diff 必须保证每个真实修改区域可见。

@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