Skip to content

fix(compaction): make compaction guard content-aware to prevent false cancellations in heartbeat sessions#42119

Merged
jalehman merged 7 commits into
openclaw:mainfrom
samzong:fix/compaction-guard-boilerplate-aware
Mar 21, 2026
Merged

fix(compaction): make compaction guard content-aware to prevent false cancellations in heartbeat sessions#42119
jalehman merged 7 commits into
openclaw:mainfrom
samzong:fix/compaction-guard-boilerplate-aware

Conversation

@samzong

@samzong samzong commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #40727

The compaction safeguard (compaction-safeguard.ts) and the embedded-runner compaction path (compact.ts) both used a naive role check to decide whether a session contains real conversation worth summarising:

// before
function isRealConversationMessage(message: AgentMessage): boolean {
  return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
}

In long-running heartbeat sessions, nearly every message satisfies this check by role alone, yet the content is boilerplate: heartbeat polls produce empty or HEARTBEAT_OK user turns and NO_REPLY assistant turns. The guard therefore never fires, the session grows past the 200 K ceiling, and the agent goes silent.

Root cause

isRealConversationMessage / hasRealConversationContent checked role only; it never inspected the text content of the message.

Fix

Replace the role-only predicate with a content-aware one in both files:

  • user / assistant messages are real only when their text content is non-empty and is not a pure boilerplate sentinel (HEARTBEAT_OK or NO_REPLY). Non-text blocks (images, attachments) always count as real.
  • toolResult messages are real only when a meaningful (non-boilerplate) user message appears in the previous 20 messages of the window, so tool output triggered by a real human ask still counts toward keeping the session alive.

The change is additive: sessions with real human messages continue to compact exactly as before.

Tests

Added in compaction-safeguard.test.ts:

  • Tool result linked to a HEARTBEAT_OK user turn → not real → compaction cancelled
  • Tool result linked to a meaningful user ask → real → compaction proceeds

Added in compact.hooks.test.ts:

  • Boilerplate-only session (HEARTBEAT_OK + tool output) → skips compaction with reason no real conversation messages
  • Meaningful user ask + tool result → compaction runs as expected

All 74 affected tests pass.

Checklist

  • Bug fix (non-breaking change that fixes an issue)
  • Tests added / updated
  • No documentation changes

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M labels Mar 10, 2026
@greptile-apps

greptile-apps Bot commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a false-negative in the compaction guard and embedded-runner compaction path by replacing a naive role-only predicate (role === "user" || role === "assistant" || role === "toolResult") with a content-aware one. The new predicate filters out empty messages and known boilerplate sentinels (HEARTBEAT_OK, NO_REPLY) for user/assistant turns, and uses a 20-message lookback to decide whether a tool result is anchored to a real human ask. The fix correctly addresses the root cause: heartbeat-only sessions no longer defeat the guard.

Key observations:

  • The entire implementation of hasMeaningfulConversationContent, BOILERPLATE_REPLY_TEXT, and TOOL_RESULT_REAL_CONVERSATION_LOOKBACK is duplicated verbatim across compact.ts and compaction-safeguard.ts. These should be extracted to a shared module to prevent them from drifting apart when new sentinels need to be added.
  • The integration test "keeps compaction enabled when tool output follows a meaningful user request" in compact.hooks.test.ts does not actually exercise the toolResult lookback path in hasRealConversationContent, because messages.some() returns true on the user message at index 0 before reaching the tool result. The unit tests in compaction-safeguard.test.ts cover the lookback logic directly, but there is no equivalent integration-level coverage for the compact.ts path.
  • Non-text content blocks (e.g. images, file attachments) in assistant messages are always treated as "real" via sawNonTextBlock, which seems intentional — this keeps the guard from firing mid-session on multimodal exchanges.

Confidence Score: 4/5

  • Safe to merge; the fix correctly targets the root cause and the negative test case provides solid regression coverage.
  • The logic is sound and the boilerplate-filtering predicate handles all described edge cases (empty strings, sentinel strings, non-text blocks). The main risks are the duplicated constants/function that could silently diverge in a future change, and a test gap in the integration path for the toolResult lookback. Neither is a runtime bug in the current change.
  • The duplicated helpers in compact.ts and compaction-safeguard.ts deserve attention — any future boilerplate sentinel additions must be made in both files.

Last reviewed commit: a613363

Comment thread src/agents/pi-embedded-runner/compact.ts Outdated
Comment thread src/agents/pi-embedded-runner/compact.hooks.test.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a613363973

ℹ️ 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".

Comment thread src/agents/pi-extensions/compaction-safeguard.ts Outdated
@samzong

samzong commented Mar 10, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the review suggestions in 8a8c943:

  • extracted the shared predicate/constants into src/agents/compaction-real-conversation.ts so the two compaction paths stay in sync
  • tightened the logic so assistant messages containing only toolCall / toolUse / functionCall blocks do not count as meaningful conversation
  • replaced the weak integration-style lookback check with direct coverage of compact.ts via __testing.hasRealConversationContent(...), so the tool-result lookback branch is exercised explicitly

Re-ran the targeted tests:

  • src/agents/pi-extensions/compaction-safeguard.test.ts
  • src/agents/pi-embedded-runner/compact.hooks.test.ts

Result: 76 tests passed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8a8c943163

ℹ️ 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".

Comment thread src/agents/pi-extensions/compaction-safeguard.ts Outdated
@jalehman jalehman self-assigned this Mar 12, 2026
@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch from 8a8c943 to 62c013c Compare March 12, 2026 23:20

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 62c013c5bf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +702 to +704
!preparation.messagesToSummarize.some((message, index, messages) =>
isRealConversationMessage(message, messages, index),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include split-turn prefix in real-conversation gate

The early cancel check only scans preparation.messagesToSummarize, so split-turn runs can be cancelled even when the actual user request is present in preparation.turnPrefixMessages and would be summarized later in this same handler. Fresh evidence in this commit is that the new content-aware gate at messagesToSummarize.some((message, index, messages) => isRealConversationMessage(...)) was added here, while split-turn prefix handling still occurs later (preparation.isSplitTurn path), which can now incorrectly skip compaction and let history keep growing in heartbeat-heavy sessions.

Useful? React with 👍 / 👎.

@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch 2 times, most recently from 245581a to 73877ef Compare March 12, 2026 23:36

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73877ef9d6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +702 to +704
!preparation.messagesToSummarize.some((message, index, messages) =>
isRealConversationMessage(message, messages, index),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include split-turn prefix in the real-conversation gate

This cancellation check only scans preparation.messagesToSummarize, but split-turn compaction later summarizes preparation.turnPrefixMessages as well, so a real user request living in the prefix can be ignored here. In heartbeat-heavy windows where messagesToSummarize is boilerplate, this now returns cancel: true and skips compaction even though meaningful content exists in the same compaction operation, which lets session history keep growing instead of being summarized.

Useful? React with 👍 / 👎.

Comment on lines +37 to +41
if (type !== "text") {
if (typeof type === "string" && TOOL_ONLY_BLOCK_TYPES.has(type)) {
continue;
}
sawMeaningfulNonTextBlock = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore reasoning-only blocks when classifying meaningful turns

This branch treats every non-text block except tool-call variants as meaningful, so assistant turns that only contain provider reasoning/thinking metadata are counted as “real conversation.” Because transcript sanitization preserves thinking blocks for most providers by default (dropThinkingBlocks is usually false), heartbeat/NO_REPLY sessions on reasoning-capable models can still bypass this safeguard and continue compacting on non-conversational traffic.

Useful? React with 👍 / 👎.

@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch from 73877ef to dd5de49 Compare March 13, 2026 01:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dd5de4913f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +702 to +704
!preparation.messagesToSummarize.some((message, index, messages) =>
isRealConversationMessage(message, messages, index),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include turnPrefixMessages in real-conversation gate

The new cancellation guard only checks preparation.messagesToSummarize, so split-turn compactions can now be cancelled even when the actual user request lives in preparation.turnPrefixMessages. This is a regression because the same handler later summarizes prefix messages when preparation.isSplitTurn is true (see the turnPrefixMessages summarization path), so heartbeat-heavy windows in messagesToSummarize will incorrectly return { cancel: true } and skip compaction despite meaningful content being part of the current compaction run.

Useful? React with 👍 / 👎.

@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch 2 times, most recently from eafa81c to fa82b87 Compare March 13, 2026 01:44

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa82b870c8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +13 to +16
if (isSilentReplyText(trimmed)) {
return false;
}
const heartbeat = stripHeartbeatToken(trimmed, { mode: "message" });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Strip markup before checking NO_REPLY sentinel

hasMeaningfulText rejects silent turns only through isSilentReplyText(trimmed), but that matcher is exact-token only and does not handle wrapped forms like **NO_REPLY** or <b>NO_REPLY</b>. In heartbeat sessions where models format the sentinel, these assistant turns are misclassified as meaningful conversation, so the new guard still allows compaction on boilerplate traffic instead of canceling. This path already normalizes markup for HEARTBEAT_OK, so silent-token detection needs the same normalization to keep behavior consistent.

Useful? React with 👍 / 👎.

@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch from fa82b87 to 99d33bc Compare March 13, 2026 05:31
@samzong

samzong commented Mar 13, 2026

Copy link
Copy Markdown
Contributor Author

@jalehman Are you fixing this PR?

@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch from 99d33bc to 4a2a27f Compare March 13, 2026 05:51

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a2a27fcdb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +702 to +704
!preparation.messagesToSummarize.some((message, index, messages) =>
isRealConversationMessage(message, messages, index),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include split-turn prefix messages in real-conversation gate

This early-cancel check only scans preparation.messagesToSummarize, but the same handler later summarizes preparation.turnPrefixMessages when preparation.isSplitTurn is true. In split-turn sessions where the meaningful user request is in the prefix and the summarize window contains heartbeat boilerplate (HEARTBEAT_OK/NO_REPLY), this condition now returns { cancel: true } and skips compaction even though real conversation is present in the current compaction operation, allowing history growth instead of summarization.

Useful? React with 👍 / 👎.

@jalehman jalehman left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes Requested

Thank you for this contribution! We've reviewed this PR and have some feedback before it can move forward.

Markdown-wrapped heartbeat boilerplate still counts as real conversation

The new helper still treats markdown-wrapped sentinel content like **HEARTBEAT_OK** and **NO_REPLY** as meaningful history. That means heartbeat-only sessions can still reach the false-cancellation path this PR is trying to prevent.

Please update the real-conversation check so it normalizes message text before deciding whether a turn is meaningful, using the same heartbeat/silent-reply handling that the rest of the compaction path relies on. The important part is that lightweight formatting around boilerplate tokens should not make them count as real conversation.


Once this is addressed, we'll re-review. Feel free to ask questions if anything is unclear.

@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch from 4a2a27f to ee04354 Compare March 20, 2026 14:13

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee04354692

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +971 to +975
if (
!session.messages.some((message, index, messages) =>
hasRealConversationContent(message, messages, index),
)
) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Let safeguard mode write its fallback compaction boundary

When agents.defaults.compaction.mode is safeguard, buildEmbeddedExtensionFactories() always registers compactionSafeguardExtension, and that handler deliberately returns a minimal compaction result instead of cancelling when there is no real conversation because otherwise _checkCompaction re-triggers in a loop (src/agents/pi-extensions/compaction-safeguard.ts:711-723). This new early return skips session.compact() entirely for heartbeat-only histories, so the safeguard never gets a chance to write that boundary, and overflow recovery later treats the result as a failed compaction. In safeguard-mode heartbeat sessions, this reintroduces the stuck/retrigger behavior the extension was added to prevent.

Useful? React with 👍 / 👎.

Comment on lines +37 to +41
if (type !== "text") {
if (typeof type === "string" && TOOL_ONLY_BLOCK_TYPES.has(type)) {
continue;
}
sawMeaningfulNonTextBlock = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Ignore Anthropic toolResult blocks in meaningful-content checks

Anthropic transcript repair keeps tool results inside role: "user" messages as content[].type === "toolResult" (src/agents/pi-embedded-helpers/turns.ts:49-58), but this branch treats every non-text block other than tool-call variants as meaningful. That means Claude sessions whose "user" turns are only tool-result payloads still count as real conversation, so the new guard will keep compacting heartbeat/tool-only traffic instead of skipping it. toolResult blocks need to be excluded here the same way tool-call blocks are.

Useful? React with 👍 / 👎.

samzong and others added 4 commits March 21, 2026 12:12
…conversation

Fixes openclaw#40727

The compaction safeguard and the embedded-runner compaction path both
used a naive role check (user | assistant | toolResult) to decide
whether a session contains real conversation worth summarising.  In
long-running heartbeat sessions nearly every message satisfies that
check, yet the *content* is boilerplate: heartbeat polls produce empty
or HEARTBEAT_OK user turns and NO_REPLY assistant turns.  The guard
therefore never fires, the session grows past the 200K ceiling, and
the agent goes silent.

Fix: replace the role-only predicate with a content-aware one:

  isRealConversationMessage / hasRealConversationContent (two separate
  copies – safeguard.ts and compact.ts – each get the same treatment)

Rules:
  • user / assistant messages are real only when their text content is
    non-empty AND not a pure boilerplate sentinel (HEARTBEAT_OK or
    NO_REPLY).  Non-text blocks (images, attachments) are always real.
  • toolResult messages are real only when a meaningful user message
    appears in the previous 20 messages of the window, so tool output
    that was triggered by a real human ask still counts.

Both predicates are exported via __testing / direct export so the
existing and new unit tests can cover them without mocks.

Tests added:
  compaction-safeguard.test.ts – two new cases:
    • tool result linked to HEARTBEAT_OK user turn → not real
    • tool result linked to meaningful user ask → real
  compact.hooks.test.ts – two new integration cases:
    • boilerplate-only session → skips compaction (reason: no real
      conversation messages)
    • meaningful user ask + tool result → compaction runs
@jalehman jalehman force-pushed the fix/compaction-guard-boilerplate-aware branch from ee04354 to 3429643 Compare March 21, 2026 19:21

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3429643315

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +74 to +78
const start = Math.max(0, index - TOOL_RESULT_REAL_CONVERSATION_LOOKBACK);
for (let i = index - 1; i >= start; i -= 1) {
const candidate = messages[i];
if (!candidate || candidate.role !== "user") {
continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Link tool results to summarized asks, not only in-window users

After one compaction cycle, the original user ask is no longer present as a message entry (session-truncation.ts removes summarized messages before firstKeptEntryId). A later tool-only span from that same task therefore has no role === "user" inside this lookback, so every toolResult here is misclassified as non-conversational. In compact.ts that turns overflow recovery into compacted: false, and in safeguard mode it falls back to previousSummary, dropping the new tool output from future context. Any long-running task that compacts once before the assistant replies can now lose state or fail overflow recovery.

Useful? React with 👍 / 👎.

Comment on lines +42 to +46
const type = (block as { type?: unknown }).type;
if (type !== "text") {
// Tool-call metadata and internal reasoning blocks do not make a
// heartbeat-only transcript count as real conversation.
if (typeof type === "string" && NON_CONVERSATION_BLOCK_TYPES.has(type)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat input/output_text blocks as textual content

OpenAI session history already accepts input_text and output_text blocks as normal message text (openai-ws-stream.ts handles both in contentToText()/contentToOpenAIParts()), but this classifier only recognizes literal type === "text". A boilerplate message like [{type:"output_text", text:"NO_REPLY"}] or [{type:"input_text", text:"HEARTBEAT_OK"}] therefore falls into the non-text branch and counts as real conversation, so the new safeguard still compacts boilerplate-only OpenAI/Responses transcripts instead of skipping them.

Useful? React with 👍 / 👎.

@jalehman jalehman merged commit 5c05347 into openclaw:main Mar 21, 2026
37 checks passed
MaheshBhushan pushed a commit to MaheshBhushan/openclaw that referenced this pull request Mar 22, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
frankekn pushed a commit to artwalker/openclaw that referenced this pull request Mar 23, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
furaul pushed a commit to furaul/openclaw that referenced this pull request Mar 24, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
… cancellations in heartbeat sessions (openclaw#42119)

Merged via squash.

Prepared head SHA: 3429643
Co-authored-by: samzong <13782141+samzong@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(compaction): count human-linked tool activity as real conversation to prevent false cancellations

2 participants