Skip to content

test: add session memory summary replay framework - #249

Open
trickyzerg664 wants to merge 5 commits into
trpc-group:mainfrom
trickyzerg664:feat/session-memory-summary-replay
Open

test: add session memory summary replay framework#249
trickyzerg664 wants to merge 5 commits into
trpc-group:mainfrom
trickyzerg664:feat/session-memory-summary-replay

Conversation

@trickyzerg664

Copy link
Copy Markdown

Summary

新增 Session / Memory / Summary 跨后端回放一致性框架。10 条标准轨迹覆盖对话、工具调用、State、Memory、Summary、事件截断和失败重试,默认比较 InMemory 与 SQLite,并支持可选 Redis/SQL 集成测试。

Changes

  • 统一驱动多个后端并重新读回数据,规范化时间戳、自动 ID、序列化顺序和 Memory 顺序。
  • 严格比较 Summary 的 Session 归属、版本和覆盖关系;
  • 生成可定位 Case、Session、Event/Summary 和字段路径的 JSON 差异报告。
  • 为 10 条轨迹注入不一致并验证全部检出;Redis 不可达时明确跳过,服务可用时执行真实集成测试。

Testing

在项目根目录激活虚拟环境:

source .venv/bin/activate

运行完整 Replay 测试:

python -m pytest \
  tests/sessions/test_replay_consistency.py \
  tests/sessions/test_replay_injections.py \
  tests/sessions/test_replay_unit.py \
  tests/sessions/test_replay_harness_consistency.py \
  -q

运行 Redis 测试:

redis-server --port 6389 --bind 127.0.0.1 --save "" --appendonly no --daemonize yes
redis-cli -u redis://127.0.0.1:6389/15 ping
TRPC_REPLAY_REDIS_URL=redis://127.0.0.1:6389/15 \
python -m pytest \
  tests/sessions/test_replay_harness_consistency.py::test_optional_redis_integration \
  tests/sessions/test_replay_injections.py::TestEndToEndRedisInjection \
  -v
redis-cli -p 6389 shutdown nosave

Copilot AI review requested due to automatic review settings July 29, 2026 02:06
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.20000% with 11 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@81c798a). Learn more about missing BASE report.

Files with missing lines Patch % Lines
trpc_agent_sdk/sessions/_session_summarizer.py 90.00000% 5 Missing ⚠️
trpc_agent_sdk/sessions/_redis_session_service.py 82.60870% 4 Missing ⚠️
trpc_agent_sdk/sessions/_summarizer_manager.py 90.00000% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main        #249   +/-   ##
==========================================
  Coverage        ?   87.87129%           
==========================================
  Files           ?         482           
  Lines           ?       45248           
  Branches        ?           0           
==========================================
  Hits            ?       39760           
  Misses          ?        5488           
  Partials        ?           0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a cross-backend “replay consistency” framework for Session / Memory / Summary semantics, and updates the session services and summarization pipeline so persisted summary events become the recovery source of truth and backend replays converge across InMemory/SQLite (with opt-in Redis/SQL integration runs).

Changes:

  • Add a reusable replay harness + 10 standard JSONL traces that execute operations, reread from storage, normalize volatile fields, inject faults, and produce a JSON diff report.
  • Make event appends idempotent (Event ID as session-scoped key) and add “failed write retry” repair behavior across InMemory / Redis / SQL backends.
  • Persist structured, versioned Summary metadata as a summary anchor event (with ordering gap for SQL timestamp rounding) and recover summary cache from persisted summary events.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
trpc_agent_sdk/sessions/_summarizer_manager.py Rebuild summary cache from persisted summary events; enforce session ownership checks.
trpc_agent_sdk/sessions/_sql_session_service.py Idempotent append_event with SQL-side existence checks; align active/historical windows and scoped state writes.
trpc_agent_sdk/sessions/_session_summarizer.py Add structured, versioned summary event metadata + recovery helper; ordering timestamp gap logic for SQL.
trpc_agent_sdk/sessions/_redis_session_service.py Idempotent append_event + retry repair; fix multi-field HSET by using redis-py mapping; decode bytes hash state.
trpc_agent_sdk/sessions/_in_memory_session_service.py Idempotent append_event + retry repair; store deep-isolated session snapshots on update_session.
trpc_agent_sdk/sessions/_base_session_service.py Centralize session-scoped idempotency via _append_event_to_session returning appended status + filtered events.
trpc_agent_sdk/sessions/init.py Export public replay-facing summary metadata key + recovery helper.
trpc_agent_sdk/memory/_sql_memory_service.py Treat store_session as complete snapshot replacement (delete stale rows in-scope).
tests/sessions/test_summarizer_manager.py Add tests for cache recovery from persisted summary event + ownership rejection.
tests/sessions/test_session_summarizer.py Test that ordering gap survives SQL float→datetime rounding.
tests/sessions/test_replay_unit.py Verify normalizer keeps Summary semantics while normalizing only volatile metadata fields.
tests/sessions/test_replay_harness_consistency.py New tests for harness invariants, lightweight mode, summary fault localization, optional Redis/SQL integration.
tests/sessions/test_replay_consistency.py Remove known drift list (now expected consistent).
tests/sessions/test_redis_session_service.py Tests for HSET mapping writes and bytes→str hash decoding behavior.
tests/sessions/test_in_memory_session_service.py Test ensuring update_session does not share event list with storage (no duplicate append).
tests/sessions/test_base_session_service.py Test Event-ID idempotency at BaseSessionService level.
tests/sessions/session_memory_summary_diff_report.json Update expected sample report to reflect fixed consistency (no mismatches).
tests/sessions/replay/normalizer.py Normalize only volatile summary metadata fields using exported key.
tests/sessions/replay_harness.py New replay harness implementation: run cases, reread storage, normalize/compare, inject faults, emit report.
tests/sessions/replay_cases/standard_cases.jsonl New catalog of 10 standard replay traces.
tests/memory/test_sql_memory_service.py Test SQL memory snapshot replacement deletes stale rows and avoids duplicates.
session_memory_summary_diff_report.json New generated root-level report output for the replay suite.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +270 to 274
# This is either the normal first write or recovery of a write that
# stopped after local mutation; both paths append exactly once here.
# 此处既处理首次写入,也补偿“本地已改、存储未写”的失败,且只追加一次。
storage_session.events.append(event)

Comment on lines +197 to +215
# Prefer replay metadata while retaining safe defaults for legacy events.
# 优先使用回放元数据,同时为旧事件保留安全的字段回退值。
version = metadata.get("version", event.version or 1)
original_event_count = metadata.get("original_event_count", 0)
compressed_event_count = metadata.get("compressed_event_count", 0)
summary_timestamp = metadata.get("summary_timestamp", event.timestamp)
replaces_summary_id = metadata.get("replaces_summary_id")

return SessionSummary(
summary_id=event.id,
session_id=session_id,
summary_text=summary_text,
version=int(version),
replaces_summary_id=replaces_summary_id if isinstance(replaces_summary_id, str) else None,
original_event_count=int(original_event_count),
compressed_event_count=int(compressed_event_count),
summary_timestamp=float(summary_timestamp),
metadata=metadata,
)
@helloopenworld

Copy link
Copy Markdown
Contributor

AI Code Review

我已完整审查 pr.diff(22 个文件,跨后端 Session/Memory/Summary 回放框架 + 生产代码幂等性/摘要版本化修复),并结合仓库上下文(_sql_session_service.py_redis_session_service.py_session_summarizer.pystorage/_redis.pystorage/_sql.pyevents/_event.pyrunners.py、既有 tests/sessions/replay/ 框架)验证了关键调用链。下面是结论。

发现的问题

🚨 Critical

无。

⚠️ Warning

无。

💡 Suggestion

  • session_memory_summary_diff_report.json:1(仓库根,新增 3826 行):该文件是回放框架的生成产物,且 replay_harness.py:56DEFAULT_REPORT_PATH 指向仓库根,CLI 每次运行都会重写该文件,造成 git 噪音与合并冲突。建议将其移入 tests/sessions/(与既有报告产物一致)并加入 .gitignore,或在提交前以固定 baseline 方式管理,避免把可重新生成的 JSON 纳入版本控制。

  • tests/sessions/replay_harness.py:1011stale_summary_version 故障注入用 max(0, mutated["summary"]["version"] - 1),对 version=1 的摘要会得到 0(无效版本,正常版本从 1 起),而非一个"陈旧但仍合法"的版本。当前测试恰好只对 v2 用例触发该变异所以未出错,但若日后复用到 v1 场景,注入值语义不准确。建议改为 mutated["summary"]["version"] = max(1, version - 1) 或直接置为更小的合法版本,使变异保持"陈旧版本"的真实语义。

总结

未发现明显阻塞问题。本 PR 的核心改动(Event ID 幂等追加、Redis HSET 改用 mapping、Hash bytes 解码、InMemory 深拷贝隔离、SQL Memory stale 行删除、版本化摘要锚点与持久化恢复)逻辑自洽,与既有存储/事件/会话上下文一致,并配有针对性的单元测试与跨后端回放断言;仅有两条维护性层面的可选优化。

测试建议

暂无额外测试建议。现有测试已覆盖幂等重试、摘要版本/覆盖链恢复、归属校验、SQL 时间戳排序间隔等高风险路径;如后续将 stale_summary_version 变异复用到 v1 摘要场景,建议补一条对应的检出断言。

@trickyzerg664

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

Rook1ex added a commit to trpc-group/cla-database that referenced this pull request Jul 29, 2026
@helloopenworld

Copy link
Copy Markdown
Contributor

AI Code Review

Redis 会立即进行序列化,因此别名(aliasing)没有危害。很好。

我已经完成了审查。该 diff 非常稳健,测试覆盖率极佳,未发现严重或警告级别的问题。让我来写最终结论。

发现的问题

未发现 Critical 或 Warning 级别的阻塞问题。本 PR 的生产代码改动(SQL Memory 快照替换语义、InMemory/Redis/SQL 的 append_event 幂等与补偿写入、版本化摘要锚点与持久化恢复、Redis HSET mapping 修复)逻辑自洽,且均配有针对性回归测试(幂等重试、窗口镜像、bytes state 解码、摘要版本/归属恢复等)。pr.diff 中相关上下文(MemStorageEvent/SessionStorageEvent 主键作用域、_get_session 返回存储对象引用、Redis _set_session 即时序列化)均能验证改动正确性。

💡 Suggestion

  • trpc_agent_sdk/memory/_sql_memory_service.py:225-238store_session 现在在每次写入时都会额外执行一次同 save_key/session_id 作用域的全量 query 以计算 stale 行。对于事件数较多的会话,这是一笔额外的范围查询开销;可考虑仅在确实发生摘要压缩(事件数减少)时触发清理,或在 upsert 循环中复用已读出的已有行避免二次查询,降低高频 store_session 的成本。

  • trpc_agent_sdk/sessions/_session_summarizer.py:543,516:摘要事件复用 Event.version 字段承载"会话内单调摘要版本"语义(该字段原义为兼容性版本)。当前仓库内除摘要逻辑外无其他消费方,安全;但语义复用长期存在误用风险,建议在字段注释或 SessionSummary 文档中显式说明此约定,便于后续维护者区分两种 version 含义。

总结

整体风险低,未发现必须修复的问题;生产代码的关键正确性改动均有配套测试覆盖,回放框架与报告产物迁移(artifacts/ + .gitignore)一致完整。

测试建议

暂无额外测试建议。现有测试已覆盖幂等重试、跨后端窗口一致性、摘要版本/归属/覆盖链恢复、Redis 可达性探测与凭据不泄露等关键风险路径。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants