fix: prevent stale transcript replay#77033
Conversation
|
Codex review: needs changes before merge. Summary Reproducibility: yes. Source-level reproduction is high confidence: current main lacks the persisted-current-inbound compaction retry guard, and the PR head has a clear duplicate-repair path when compaction shrinks the rebuilt context below prePromptMessageCount. Next step before merge Security Review findings
Review detailsBest possible solution: Clamp or recompute the transcript-repair scan boundary against the post-compaction context, add a regression for compaction-shifted message counts, then complete exact-head validation and maintainer review. Do we have a high-confidence way to reproduce the issue? Yes. Source-level reproduction is high confidence: current main lacks the persisted-current-inbound compaction retry guard, and the PR head has a clear duplicate-repair path when compaction shrinks the rebuilt context below prePromptMessageCount. Is this the best way to solve the issue? No as-is. The PR direction is narrow and appropriate, but the repair duplicate-detection window must account for compaction-shifted transcript indexes before this is the best fix. Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 50da306c0a78. |
c40db37 to
19614bd
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19614bd2bd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| typeof params.currentTurnStartIndex === "number" | ||
| ? context.messages.slice(Math.max(0, params.currentTurnStartIndex)) | ||
| : context.messages; |
There was a problem hiding this comment.
Handle compaction-shifted turn start before transcript repair
When currentTurnStartIndex is derived from prePromptMessageCount, a successful in-attempt compaction can shrink context.messages so slice(currentTurnStartIndex) becomes empty even though the just-generated assistant turn is already persisted. In that case alreadyPresent is false and ensureVisibleAssistantTextInSessionTranscript appends a second assistant message for the same answer, reintroducing duplicated transcript turns after overflow-recovery paths. Clamp or recompute the turn start against the post-compaction context before duplicate detection.
Useful? React with 👍 / 👎.
1fb9c8c to
d31a597
Compare
6fe7c5a to
5d200f5
Compare
Summary
Root Cause
The concrete bug fixed here was stale replay after context-overflow compaction. When Pi had already persisted the current inbound channel message, OpenClaw could compact and retry with the original prompt. That made the same external user message appear again in future model context.
The correct boundary is that Pi owns session persistence. OpenClaw should not synthesize assistant JSONL entries from WebChat delivery state or repair Pi transcripts from outside Pi. Earlier repair code was removed before merge; this PR only prevents OpenClaw from re-sending/re-persisting an already-written inbound turn during overflow recovery.
What Changed
src/agents/pi-embedded-runner/run.ts: after overflow compaction, retry from the current transcript and suppress next user-message persistence when the current inbound message was already persisted.src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts: regression for the duplicate persisted-turn replay loop.src/gateway/server-methods/chat.directive-tags.test.ts: guardrails that normal WebChat agent runs do not mirror live assistant delivery into persisted JSONL.CHANGELOG.md: records the user-facing stale replay fix.Verification
pnpm test src/agents/pi-embedded-runner/run.overflow-compaction.loop.test.ts src/gateway/server-methods/chat.directive-tags.test.tsgit diff --check origin/main...HEADFixes #76424.