fix(memory): resolve memoryFlush 0/0 guard blocking flush on never-flushed sessions (#47143)#83015
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 1, 2026, 12:21 AM ET / 04:21 UTC. Summary PR surface: Source +21, Tests +26, Docs +1. Total +48 across 3 files. Reproducibility: yes. at source level: current main's helper returns true for a numeric 0 matching the defaulted compaction count of 0, and 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:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land the narrow Do we have a high-confidence way to reproduce the issue? Yes, at source level: current main's helper returns true for a numeric 0 matching the defaulted compaction count of 0, and Is this the best way to solve the issue? Yes, with proof and cleanup caveats: Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 5a5913a98b03. Label changesLabel justifications:
Evidence reviewedPR surface: Source +21, Tests +26, Docs +1. Total +48 across 3 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
|
6b89e48 to
30f7153
Compare
|
ClawSweeper PR egg 🎁 Pass real behavior proof to wake the egg and unlock a hatchable treat. Where did the egg go?
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
…ushed sessions hasAlreadyFlushedForCurrentCompaction incorrectly returns true when both compactionCount and memoryFlushCompactionCount are 0, preventing the memory flush from running on sessions that have grown past the token threshold but have never actually been flushed. Root cause: the equality guard (lastFlushAt === compactionCount) produces a false positive when both sides are 0 — this state is ambiguous between: 1. A legacy / never-flushed row whose field was written as 0 (or defaulted) 2. A real cycle-0 flush (compacted, then flushed before any second compaction) Fix: require memoryFlushAt to be present when compactionCount === 0 before treating the 0/0 row as already flushed. Fresh sessions always clear memoryFlushAt on creation, so they will never be falsely gated. Sessions where a real cycle-0 flush ran will have memoryFlushAt set and continue to be deduped correctly. Expand the Pick<> in both the helper signature and shouldRunMemoryFlush entry type to include memoryFlushAt. Update tests: the existing 'treats missing compactionCount as 0' case now also passes memoryFlushAt to represent a real cycle-0 flush, and two new cases verify the legacy 0/0 path returns false. Fixes openclaw#47143
30f7153 to
2ca229f
Compare
|
@Bartok9 thanks for the PR. ClawSweeper is still waiting on real behavior proof before this can move forward. Useful proof can be a screenshot, short video, terminal output, copied live output, linked artifact, or redacted logs that show the changed behavior after the fix. Please redact private tokens, phone numbers, private endpoints, customer data, and anything else sensitive. Once proof is added to the PR body or a comment, ClawSweeper or a maintainer can re-check it. |
|
Thanks @clawsweeper — real behavior proof is already present and the repo's own "Real behavior proof" CI check is passing on the current head (green in the checks list above), alongside the full test suite and security gates. Recap of the proof already in the PR body:
Line 1 is exactly the reported bug: a never-flushed @clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix(memory): resolve memoryFlush 0/0 guard blocking flush on never-flushed sessions (#47143) This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
Summary
Fixes #47143 —
memoryFlushnever triggers for sessions where bothcompactionCountandmemoryFlushCompactionCountare0but no flush has actually run.Root cause
hasAlreadyFlushedForCurrentCompactionuses a simple equality guard:When both values are
0this produces a false positive — the session is treated as already flushed even ifmemoryFlushAthas never been set. This blocks every memory flush for sessions in this state.The ambiguity arises because
0can mean either:0by an older code path or defaulted before the column existedmemoryFlushCompactionCount: 0Fix
Require
memoryFlushAtto be present when both counters are0before treating the row as already flushed:Why this is safe:
memoryFlushAtat creation (session.ts:717) — they will never be falsely gatedmemoryFlushAtset — once-per-cycle deduplication is preserved for themcompactionCount > 0are unaffected — the equality guard alone is unambiguous for thoseChanges
src/auto-reply/reply/memory-flush.ts— addmemoryFlushAtto thePick<>type and the zero-counter guardsrc/auto-reply/reply/reply-state.test.ts— update the existing0/0test to passmemoryFlushAt(correctly represents real cycle-0 flush), add two new cases for legacy/never-flushed rowsTest verification
Acceptance criteria from ClawSweeper review:
node scripts/run-vitest.mjs src/auto-reply/reply/reply-state.test.ts src/auto-reply/reply/agent-runner-memory.test.tspnpm exec oxfmt --check --threads=1 src/auto-reply/reply/memory-flush.ts src/auto-reply/reply/reply-state.test.ts✅ passesReal behavior proof
Behavior or issue addressed:
memoryFlush0/0 guard incorrectly blocks flushes on legacy/never-flushed sessions (issue #47143). Fix insrc/auto-reply/reply/memory-flush.tsrequires explicitmemoryFlushAtbefore treating a 0/0 row as already flushed.Real environment tested:
fix/47143-memory-flush-zero-compaction-guard@30f7153eec8Exact steps or command run after this patch:
Evidence after fix:
Observed result after fix:
All 42 tests in
reply-state.test.tspass, including the sixhasAlreadyFlushedForCurrentCompactioncases that exercise the new guard. Critically, the two new legacy-row cases ("returns false for persisted 0/0 rows with no memoryFlushAt" and "returns false for 0/0 row where memoryFlushAt is explicitly undefined") both pass — these would have returnedtruebefore the patch (false positive that blocked all flushes on never-flushed sessions). The cycle-0 real-flush case ("treats missing compactionCount as 0 when memoryFlushAt confirms a real flush") still correctly returnstrue, preserving once-per-cycle deduplication.What was not tested:
agent-runner-memory.test.tsfile referenced in the original ClawSweeper acceptance criteria — onlyreply-state.test.tswas rerun for this proof. The PR's logic change is fully covered by the file rerun above.Update 2026-06-13 — rebased onto current main
Rebased onto
upstream/main@340c2456bb(single commit2ca229fe32, Bartok9 authorship preserved) to re-trigger fresh CI and clear the stale late-May failures. The rebase was clean (no conflicts);memoryFlushAtalready exists onSessionEntryin current main (src/config/sessions/types.ts:385), so the guard change applies directly.Re-verified on the rebased branch (real output):
node scripts/run-vitest.mjs run src/auto-reply/reply/reply-state.test.ts→ 42/42 passedoxlinton the two touched source files → 0 warnings, 0 errorscheck-changelog-attributions→ exit 0Direct function-level repro of the
0/0guard (callshasAlreadyFlushedForCurrentCompactiondirectly, real output):Line 1 is the bug this PR fixes: before the change, a never-flushed session with the ambiguous
0/0counter state returnedtrue(flush silently blocked forever); now it returnsfalseso the flush proceeds. Line 2 confirms a session that genuinely flushed in cycle 0 (memoryFlushAtset) is still correctly treated as already-flushed — no double-flush regression.