fix(sessions): prevent delivery-mirror prompt contamination with adjacent dedup and identity fallback (#99470)#99504
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 6, 2026, 6:11 AM ET / 10:11 UTC. Summary PR surface: Source +69, Tests +194, Other +283. Total +546 across 5 files. Reproducibility: yes. source-reproducible: current main lacks marker fallback and adjacent dedup, while the PR proof script exercises the provider-bound replay path for live, stripped, and bare delivery-mirror survivors. I did not execute the script in this read-only review. Review metrics: 1 noteworthy metric.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land this provider-bound defense after session-state owner acceptance of the adjacent-dedup invariant, keeping the merged provenance fix from #99855 as the source-side complement. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: current main lacks marker fallback and adjacent dedup, while the PR proof script exercises the provider-bound replay path for live, stripped, and bare delivery-mirror survivors. I did not execute the script in this read-only review. Is this the best way to solve the issue? Yes, this looks like the narrow maintainable fix shape: source-side provenance from #99855 helps new rows, and this PR covers stripped or bare survivors at the provider boundary without changing transcript persistence. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 7f29380d21e4. Label changesLabel justifications:
Evidence reviewedPR surface: Source +69, Tests +194, Other +283. Total +546 across 5 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (1 earlier review cycle)
|
|
@clawsweeper re-review P1 issues addressed:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
968644f to
72dffc4
Compare
Merge Readiness SummaryThis PR is now proof-complete and CI-green. Here are the merge value points and remaining pre-conditions: Value
Entry Conditions (for maintainer review)
What This Doesn't Touch
Thank you for reviewing! @steipete @cpojer — would appreciate a look when you have a moment. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
72dffc4 to
79a28e5
Compare
|
@vincentkoc Hi! I've rebased this PR onto the latest Our changes are fully compatible with the shared constants you introduced ( How our two PRs work together: Your #99855 fixes the source — ensuring newly written delivery-mirror records carry the correct This PR (#99504) adds defense-in-depth on the consumption side for #99470 — three layers of protection against delivery-mirror entries leaking into model prompts:
Additionally, this PR independently fixes a pre-existing bug in The key insight from the issue reporter's production data for #99470 is that session rebuild / side-branch merge can strip ALL markers from delivery-mirror entries — leaving them completely indistinguishable from real assistant replies to any metadata-based filter. Your #99855 fixes the provenance for new entries, but existing/rebuild-stripped entries need the identity fallback (Layer 1) and the content-level dedup (Layer 2) to be caught. Would love your thoughts on this approach! |
|
Independent real-world validation from a self-hosted OpenClaw deployment (three agents, Reproduction before this fix: hit this bug organically within minutes of connecting a fresh Telegram channel — assistant replies started repeating verbatim turn over turn, including one case where a leaked literal Validation after this fix (cherry-picked onto local Would be a meaningful reliability improvement to land — this was actively corrupting conversation history on a real deployment, not just a theoretical edge case. |
|
@LeoLinksAZ Thank you for taking the time to validate this on a real self-hosted deployment with multiple agents and channels! This is exactly the kind of independent verification that proves the fix works beyond unit tests — your observation of zero adjacent duplicates and zero delivery-mirror leakage in the raw @vincentkoc — wanted to flag that an independent self-hosted operator has now validated this PR on a live production deployment (ollama/qwen2.5:7b, 3 agents, Discord + Telegram). They confirmed:
This validates that #99504 provides real-world defense-in-depth on the replay/consumption side, complementing your provenance fix (#99855) on the source side. Would appreciate your review when you have a moment. |
731265f to
ee0de98
Compare
ee0de98 to
ce448ce
Compare
…cent dedup and identity fallback (openclaw#99470) Two-layer defence against delivery-mirror entries leaking into provider prompts after session rebuild / side-branch merge strips metadata: Layer 1 (identity fallback): isTranscriptOnlyOpenClawAssistantMessage gains an openclawDeliveryMirror field check to catch stripped-metadata survivors that lost provider/model during rebuild. Layer 2 (adjacent dedup): normalizeAssistantReplayContent collapses adjacent byte-identical no-tool-call assistant messages, catching fully-bare {role,content,usage} survivors invisible to any metadata filter. P1 fix: added 'tool_use' (native Anthropic snake_case) to TOOL_CALL_TYPES in extractToolCallsFromAssistant so adjacent dedup never collapses tool-call-bearing turns. Co-Authored-By: Claude Opus 4.8 <[email protected]>
ce448ce to
24fdd95
Compare
|
Merged via squash.
|
…cent dedup and identity fallback (openclaw#99470) (openclaw#99504) * fix(sessions): prevent delivery-mirror prompt contamination with adjacent dedup and identity fallback (openclaw#99470) Two-layer defence against delivery-mirror entries leaking into provider prompts after session rebuild / side-branch merge strips metadata: Layer 1 (identity fallback): isTranscriptOnlyOpenClawAssistantMessage gains an openclawDeliveryMirror field check to catch stripped-metadata survivors that lost provider/model during rebuild. Layer 2 (adjacent dedup): normalizeAssistantReplayContent collapses adjacent byte-identical no-tool-call assistant messages, catching fully-bare {role,content,usage} survivors invisible to any metadata filter. P1 fix: added 'tool_use' (native Anthropic snake_case) to TOOL_CALL_TYPES in extractToolCallsFromAssistant so adjacent dedup never collapses tool-call-bearing turns. Co-Authored-By: Claude Opus 4.8 <[email protected]> * fix(sessions): narrow delivery mirror replay filtering * test(sessions): preserve tool-call replay duplicates --------- Co-authored-by: Claude Opus 4.8 <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
Delivery-mirror transcript receipts could leak into provider-bound replay after historical session rebuilds stripped their normal
provider/modelprovenance. The issue reporter measured adjacent duplicate assistant content in 108 of 323 submitted prompts.Fixes #99470.
Why This Change Was Made
The replay boundary now recognizes all three valid
openclawDeliveryMirrormarker kinds even when provider/model metadata is absent. For the observed older row shape where every marker was lost, it removes only a receipt that immediately follows an identical assistant response, carries an explicit zero-usage snapshot, has a successful stop, and contains no tool calls.The original broad adjacent-content dedup was narrowed during maintainer review. It could delete legitimate repeated model turns and used JSON serialization for equality. The final comparison is structural and preserves ordinary nonzero-usage and tool-call repeats. Current session-tree logic independently keeps new delivery side branches out of prompt-visible paths.
User Impact
Historical delivery receipts no longer teach the model that assistant answers occur twice. Normal repeated assistant turns remain intact.
Evidence
node scripts/run-vitest.mjs src/agents/embedded-agent-runner/replay-history.test.ts --reporter=verbose— 36 tests passed.node scripts/run-vitest.mjs src/agents/sessions/session-manager.test.ts -t 'accepts an unowned side leaf only when it preserves the active branch' --reporter=verbose— 2 tests passed across both shards; 132 skipped.node scripts/check-changed.mjs -- src/shared/transcript-only-openclaw-assistant.ts src/agents/embedded-agent-runner/replay-history.ts src/agents/embedded-agent-runner/replay-history.test.ts— passed in Blacksmith Testbox: https://github.com/openclaw/openclaw/actions/runs/29536678577git diff --check— passed.Regression Test Plan
Coverage locks valid marker-only mirrors, marker-free zero-usage receipts, invalid marker preservation, and ordinary nonzero-usage and tool-call repeated assistant turns. Existing session-manager coverage proves a delivery side leaf preserves the active prompt branch and remains absent from rebuilt session context.
AI Assistance
The contributor used Claude Opus 4.8. Maintainer review rewrote and narrowed the patch. The author and maintainer take responsibility for the final change.