fix(config/sessions): narrow reply-session initialization revision to identity fields#98835
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 2, 2026, 1:58 PM ET / 17:58 UTC. Summary PR surface: Source +110, Tests +538. Total +648 across 4 files. Reproducibility: yes. for the source path: current main hashes the full persisted session entry shape, so non-identity metadata drift can invalidate the snapshot before commit. I did not run tests in this read-only review, but the PR adds focused tests that exercise the same accessor race. 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. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this accessor-boundary source fix after required checks and maintainer session-state review, keep v2026.6.11 package parity under #98416, and treat #99048 as a companion retry mitigation rather than a replacement. Do we have a high-confidence way to reproduce the issue? Yes for the source path: current main hashes the full persisted session entry shape, so non-identity metadata drift can invalidate the snapshot before commit. I did not run tests in this read-only review, but the PR adds focused tests that exercise the same accessor race. Is this the best way to solve the issue? Yes. The fix is at the shared accessor boundary, narrows the false conflict predicate to session identity, and preserves safe concurrent metadata without replacing it with a broader retry-only workaround. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 55ed57a4e39b. Label changesLabel justifications:
Evidence reviewedPR surface: Source +110, Tests +538. Total +648 across 4 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
|
|
Addressed the ClawSweeper review feedback from the latest review:
Ready for re-review. |
|
Updated the fix to address the CI regression in
Verification:
The two remaining failures from the last CI run ( |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@openclaw-mantis visual task: verify repeated main-session messages no longer hit reply session initialization conflicted while session metadata changes concurrently. |
… identity fields The initialization guard compared the full persisted session entry, so background touches to updatedAt, heartbeat timestamps, context-budget metadata, etc. produced false-positive stale-snapshot conflicts and the "reply session initialization conflicted" error. Only sessionId and sessionFile matter for detecting a session rotation. Narrow the revision to those identity fields and add a regression test. Fixes openclaw#98672
What Problem This Solves
Fixes #98672. Users observed
reply session initialization conflicted for agent:main:mainerrors that broke ongoing sessions until the gateway was restarted. The error came from the guarded reply-session initialization path comparing the full persisted session entry between snapshot and commit.Why This Change Was Made
The initialization guard only needs to detect whether another initializer rotated the session, meaning
sessionIdorsessionFilechanged. Comparing the entire entry included volatile fields such asupdatedAt, heartbeat metadata, pending-delivery metadata, and other fields that can legitimately change while a reply-session initialization is in flight.The guard is narrowed to the identity fields
sessionIdandsessionFile. When that identity-only guard passes, the commit path carries forward metadata that changed since the snapshot viamergeConcurrentReplySessionMetadata. Fields the prepared turn entry explicitly modified relative to the snapshot still win, so/newand/resetcontinue to clear recovered auto-fallback provider/model overrides, runtime model caches, and context-budget state as before.The merge also treats an absent field and an own
undefinedfield as equivalent when deciding whether the prepared entry left the snapshot unchanged. That prevents incidental optionalundefinedproperties from overwriting concurrent same-session additions.User Impact
reply session initialization conflictedwhen same-session background activity touches metadata during reply initialization./new,/reset) is preserved.Evidence
Behavior proof: same-session concurrent metadata write
This branch adds
src/config/sessions/session-accessor.reply-init-concurrency.test.ts, a deterministic two-process behavior proof for the affected race window:agent:main:mainin a real temporarysessions.jsonstore.loadReplySessionInitializationSnapshotand waits with that snapshot held.updateSessionEntrywrite that changes same-session metadata after the snapshot.commitReplySessionInitializationwith the held revision and snapshot.ok: true; astale-snapshotresult would reproduce the user-visible conflict class.This is a deterministic multi-process proof at the production session-store/accessor boundary where the conflict is created and resolved.
Local real-gateway proof, not committed
I also verified the same race through an actual spawned OpenClaw gateway process. This was an exploratory local proof only; the temporary test hook and e2e harness were removed and are not part of this PR.
Methodology:
loadReplySessionInitializationSnapshot()insrc/auto-reply/reply/session.ts.createOpenClawTestInstance.chat.sendforagent:main:main.sessions.jsonfrom the parent process with productionupdateSessionEntry, changing heartbeat metadata after the snapshot.chat.sendACK started successfully, the final session entry preserved the concurrent heartbeat metadata, and gateway logs did not containreply session initialization conflicted.Proof commands and results:
Focused regression coverage
Local quality gates
Autoreview
Structured autoreview was run against the current branch diff after the optional-
undefinedmerge fix:CI
Current head:
455615bd04a01fbaccc806581139805a91dcb7af.gh pr checks 98835is green for the active check set. Relevant passing checks include:Real behavior proofcheck-session-accessor-boundarycheck-test-typescheck-lintcheck-prod-typescheck-dependenciescheck-shrinkwrapQA Smoke CIbuild-artifactsOpenGrep OSSSecurity High (core-auth-secrets)Security High (channel-runtime-boundary)Security High (network-ssrf-boundary)Security High (mcp-process-tool-boundary)Security High (process-exec-boundary)Security High (plugin-trust-boundary)Security High (actions)PR merge state is
CLEANat the current head.