Skip to content

fix(memoryFlush): guard transcript-size forced flush against repeated runs#32358

Merged
steipete merged 1 commit intoopenclaw:mainfrom
hclsys:fix/memory-flush-compaction-guard
Mar 3, 2026
Merged

fix(memoryFlush): guard transcript-size forced flush against repeated runs#32358
steipete merged 1 commit intoopenclaw:mainfrom
hclsys:fix/memory-flush-compaction-guard

Conversation

@hclsys
Copy link
Copy Markdown
Contributor

@hclsys hclsys commented Mar 3, 2026

Summary

Fixes #32317 — Pre-compaction memory flush fires on every message after v2026.3.1 upgrade.

Root cause: agent-runner-memory.ts:440 — the shouldForceFlushByTranscriptSize path (introduced in d729ab21) is OR'd into the flush decision without the memoryFlushCompactionCount guard. The token-based path in shouldRunMemoryFlush() correctly checks memoryFlushCompactionCount === compactionCount to prevent repeated flushes within the same compaction cycle, but the transcript-size path bypasses this check.

With tool calls and heartbeats, transcript file size grows fast in bytes even at low token counts (reporter shows 49k/200k tokens). Once the 2 MB forceFlushTranscriptBytes default is crossed, forced flush fires on every single message.

Fix: Extract hasAlreadyFlushedForCurrentCompaction() from the inline guard and apply it to both trigger paths.

Changes

File Change
src/auto-reply/reply/memory-flush.ts Extract hasAlreadyFlushedForCurrentCompaction() helper (+14/-3)
src/auto-reply/reply/agent-runner-memory.ts Apply compaction guard to transcript-size flush path (+4/-1)
src/auto-reply/reply/reply-state.test.ts Add 4 tests for hasAlreadyFlushedForCurrentCompaction() (+37)

Test plan

  • vitest run src/auto-reply/reply/reply-state.test.ts: 27/27 pass
  • Build: PASS (tsc --noEmit, pre-existing upstream errors only)
  • Lint: 0 warnings (oxlint)
  • Format: PASS (oxfmt)

lobster-biscuit

… runs

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
@hclsys
Copy link
Copy Markdown
Contributor Author

hclsys commented Mar 3, 2026

@steipete — The forceFlushTranscriptBytes path from d729ab21 bypasses the memoryFlushCompactionCount guard, causing forced flush on every message once transcript exceeds 2 MB. This PR extracts the compaction-cycle check into a shared helper and applies it to both trigger paths. 3 files, +55/-4, 27/27 tests green. Fixes #32317.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR fixes a regression (introduced in d729ab21) where the transcript-size–based forced memory flush fired on every message after the 2 MB forceFlushTranscriptBytes threshold was crossed, because it was OR'd into the flush decision without the compaction-cycle guard that the token-based path already applied.

Changes:

  • Extracts hasAlreadyFlushedForCurrentCompaction() from the inline guard in shouldRunMemoryFlush() into a reusable exported function in memory-flush.ts.
  • Applies the extracted guard to the shouldForceFlushByTranscriptSize path in agent-runner-memory.ts, ensuring the forced flush is suppressed once it has already run within the current compaction cycle.
  • Adds four targeted unit tests for the new helper covering all logic branches (matched, mismatched, undefined, and missing-defaults-to-0 cases).

The fix is minimal, focused, and correctly mirrors the existing compaction-guard semantics. The entry != null defensive check added alongside the guard is technically redundant (since shouldForceFlushByTranscriptSize can only be true when entry was already non-null at shouldCheckTranscriptSizeForForcedFlush evaluation time), but it's harmless and improves explicitness.

Confidence Score: 5/5

  • This PR is safe to merge — it is a well-scoped bug fix with comprehensive tests and no side-effects on existing behaviour.
  • The change is minimal (3 files, ~18 net lines), directly mirrors the existing guard logic already used in shouldRunMemoryFlush, is covered by four new unit tests that all pass, and does not alter any public API contracts. The entry != null defensive check is redundant but harmless.
  • No files require special attention.

Last reviewed commit: 9690ed1

@steipete steipete merged commit 503d395 into openclaw:main Mar 3, 2026
22 of 23 checks passed
@steipete
Copy link
Copy Markdown
Contributor

steipete commented Mar 3, 2026

Landed.

  • Gate: pnpm vitest run src/auto-reply/reply/reply-state.test.ts src/auto-reply/reply/agent-runner.runreplyagent.e2e.test.ts
  • Merge commit: 503d395

Thanks @hclsys!

planfit-alan pushed a commit to planfit/openclaw that referenced this pull request Mar 3, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
(cherry picked from commit 503d395)
dawi369 pushed a commit to dawi369/davis that referenced this pull request Mar 3, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
OWALabuy pushed a commit to kcinzgg/openclaw that referenced this pull request Mar 4, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
AytuncYildizli pushed a commit to AytuncYildizli/openclaw that referenced this pull request Mar 4, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
V-Gutierrez pushed a commit to V-Gutierrez/openclaw-vendor that referenced this pull request Mar 17, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
ephb pushed a commit to ephb-bot/openclaw that referenced this pull request Mar 19, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
lukeg826 pushed a commit to lukeg826/openclaw that referenced this pull request Mar 26, 2026
… runs (openclaw#32358)

The `forceFlushTranscriptBytes` path (introduced in d729ab2) bypasses the
`memoryFlushCompactionCount` guard that prevents repeated flushes within the
same compaction cycle. Once the session transcript exceeds 2 MB, memory flush
fires on every single message — even when token count is well under the
compaction threshold.

Extract `hasAlreadyFlushedForCurrentCompaction()` from the inline guard in
`shouldRunMemoryFlush` and apply it to both the token-based and the
transcript-size trigger paths.

Fixes openclaw#32317

Signed-off-by: HCL <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v2026.3.1 regression: pre-compaction memory flush fires on every message (aggressive compaction threshold)

2 participants