Skip to content

fix(compaction): only zero usage for pre-compaction messages (#50795)#50845

Closed
Hollychou924 wants to merge 6 commits into
openclaw:mainfrom
Hollychou924:fix/compaction-context-usage-zeroed-50795
Closed

fix(compaction): only zero usage for pre-compaction messages (#50795)#50845
Hollychou924 wants to merge 6 commits into
openclaw:mainfrom
Hollychou924:fix/compaction-context-usage-zeroed-50795

Conversation

@Hollychou924

Copy link
Copy Markdown
Contributor

Problem

The 📚 Context counter in the TUI always shows 0/1.0m (0%) after any compaction because clearStaleAssistantUsageOnSessionMessages() unconditionally zeros out all assistant message usage — including messages created after the compaction that contain accurate, fresh usage data from the LLM API.

Root Cause

// BEFORE (broken): clears ALL assistant usage
for (const message of messages) {
  if (candidate.role !== "assistant") continue;
  candidate.usage = makeZeroUsageSnapshot(); // ← nukes post-compaction messages too
}

The function is called after every non-retried compaction (line 62). It correctly identifies that pre-compaction usage is stale (reflects the old larger context), but it over-eagerly zeros post-compaction messages which have the correct new context usage.

Fix

Locate the latest compactionSummary message in the session, then only zero usage for assistant messages that are older than (or at the same index as) the compaction summary. Post-compaction messages are left untouched.

// AFTER (fixed): only clears pre-compaction stale usage
// Find latest compactionSummary → only zero messages before it
const staleByTimestamp = latestCompactionTimestamp !== null &&
  messageTimestamp !== null &&
  messageTimestamp <= latestCompactionTimestamp;
const staleByLegacyOrdering = i < latestCompactionSummaryIndex;
if (!staleByTimestamp && !staleByLegacyOrdering) continue; // keep post-compaction
candidate.usage = makeZeroUsageSnapshot();

Added parseMessageTimestamp() helper (same logic as in google.ts) for timestamp-based detection with index-based fallback for messages without timestamps.

Reference

The src/agents/pi-embedded-runner/google.ts runner already uses the correct pattern: stripStaleAssistantUsageBeforeLatestCompaction(). This PR aligns the compaction event handler with that approach.

Fixes #50795

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

greptile-apps Bot commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a real bug where clearStaleAssistantUsageOnSessionMessages() was unconditionally zeroing all assistant message usage after every compaction, including messages created post-compaction that carry accurate token counts. The fix correctly locates the latest compactionSummary message and scopes the zeroing to only messages at or before that cutoff, aligning with the pattern already used in src/agents/pi-embedded-runner/google.ts.

  • The primary fix is sound: the early return when no compactionSummary exists is safe, and the two-pass loop (find cutoff → zero stale messages) is correct for the common case.
  • The new completed: hasResult && !wasAborted field on the compaction end event and the sessionFile/sessionKey additions to the after_compaction hook call are small independent improvements that look correct.
  • parseMessageTimestamp is duplicated verbatim from google.ts; extracting it to a shared utility would prevent future drift.
  • The OR between staleByTimestamp and staleByLegacyOrdering means the index-based check is not a pure fallback — it can override a conclusive post-compaction timestamp when both values are present but disagree (e.g., a message with a later-than-compaction timestamp sitting at an earlier array index). This is the same behaviour as google.ts, so it is at least consistent, but the inline comment ("legacy fallback for messages without timestamps") overstates the exclusivity of the fallback.

Confidence Score: 4/5

  • Safe to merge — the fix correctly scopes usage-zeroing to pre-compaction messages and aligns with the existing google.ts pattern; the two minor concerns (helper duplication and OR vs. fallback semantics) do not affect correctness in the common case.
  • The primary logic is sound and well-tested by comparison with the google.ts reference implementation. The only risk is the OR condition between timestamp- and index-based staleness, which could incorrectly zero a post-compaction message if its array position precedes the compaction summary despite having a later timestamp — an unlikely but non-zero edge case. Code duplication of parseMessageTimestamp is a maintenance concern, not a runtime risk.
  • src/agents/pi-embedded-subscribe.handlers.compaction.ts — the staleByTimestamp || staleByLegacyOrdering OR logic and the duplicated parseMessageTimestamp helper.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-subscribe.handlers.compaction.ts
Line: 94-105

Comment:
**Duplicated helper from `google.ts`**

`parseMessageTimestamp` is an exact copy of the private function defined at line 143 of `src/agents/pi-embedded-runner/google.ts`. Since both files share identical logic, a drift risk is introduced if one is updated without the other. Consider extracting this helper to a shared utility (e.g., `src/agents/message-utils.ts`) and importing it in both locations.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/pi-embedded-subscribe.handlers.compaction.ts
Line: 152-161

Comment:
**Index fallback is not truly a fallback — can override a conclusive timestamp**

The comment on line 149 describes `staleByLegacyOrdering` as a *"legacy fallback for messages without timestamps"*, but the OR logic applies the index check even when both timestamps are available and they conclusively indicate the message is post-compaction (`staleByTimestamp === false` because `messageTimestamp > latestCompactionTimestamp`). In that scenario a message with a later-than-compaction timestamp sitting at an earlier array index would still have its usage zeroed by `staleByLegacyOrdering`.

A truer "timestamp-first, index only when no timestamp" approach would be:

```typescript
const isStale =
  messageTimestamp !== null
    ? staleByTimestamp          // timestamp is available → trust it exclusively
    : staleByLegacyOrdering;   // no timestamp → fall back to array position
```

Note: `google.ts` uses the same OR logic, so this is consistent with the existing codebase — but worth aligning the comment or changing both sites if the intent really is a pure fallback.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: "fix(compaction): onl..."

Comment on lines +94 to +105
function parseMessageTimestamp(value: unknown): number | null {
if (typeof value === "number" && Number.isFinite(value)) {
return value;
}
if (typeof value === "string") {
const parsed = Date.parse(value);
if (Number.isFinite(parsed)) {
return parsed;
}
}
return null;
}

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.

P2 Duplicated helper from google.ts

parseMessageTimestamp is an exact copy of the private function defined at line 143 of src/agents/pi-embedded-runner/google.ts. Since both files share identical logic, a drift risk is introduced if one is updated without the other. Consider extracting this helper to a shared utility (e.g., src/agents/message-utils.ts) and importing it in both locations.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-subscribe.handlers.compaction.ts
Line: 94-105

Comment:
**Duplicated helper from `google.ts`**

`parseMessageTimestamp` is an exact copy of the private function defined at line 143 of `src/agents/pi-embedded-runner/google.ts`. Since both files share identical logic, a drift risk is introduced if one is updated without the other. Consider extracting this helper to a shared utility (e.g., `src/agents/message-utils.ts`) and importing it in both locations.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +152 to +161
const staleByTimestamp =
latestCompactionTimestamp !== null &&
messageTimestamp !== null &&
messageTimestamp <= latestCompactionTimestamp;
const staleByLegacyOrdering = i < latestCompactionSummaryIndex;

if (!staleByTimestamp && !staleByLegacyOrdering) {
// Post-compaction message — preserve its accurate usage data.
continue;
}

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.

P2 Index fallback is not truly a fallback — can override a conclusive timestamp

The comment on line 149 describes staleByLegacyOrdering as a "legacy fallback for messages without timestamps", but the OR logic applies the index check even when both timestamps are available and they conclusively indicate the message is post-compaction (staleByTimestamp === false because messageTimestamp > latestCompactionTimestamp). In that scenario a message with a later-than-compaction timestamp sitting at an earlier array index would still have its usage zeroed by staleByLegacyOrdering.

A truer "timestamp-first, index only when no timestamp" approach would be:

const isStale =
  messageTimestamp !== null
    ? staleByTimestamp          // timestamp is available → trust it exclusively
    : staleByLegacyOrdering;   // no timestamp → fall back to array position

Note: google.ts uses the same OR logic, so this is consistent with the existing codebase — but worth aligning the comment or changing both sites if the intent really is a pure fallback.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-subscribe.handlers.compaction.ts
Line: 152-161

Comment:
**Index fallback is not truly a fallback — can override a conclusive timestamp**

The comment on line 149 describes `staleByLegacyOrdering` as a *"legacy fallback for messages without timestamps"*, but the OR logic applies the index check even when both timestamps are available and they conclusively indicate the message is post-compaction (`staleByTimestamp === false` because `messageTimestamp > latestCompactionTimestamp`). In that scenario a message with a later-than-compaction timestamp sitting at an earlier array index would still have its usage zeroed by `staleByLegacyOrdering`.

A truer "timestamp-first, index only when no timestamp" approach would be:

```typescript
const isStale =
  messageTimestamp !== null
    ? staleByTimestamp          // timestamp is available → trust it exclusively
    : staleByLegacyOrdering;   // no timestamp → fall back to array position
```

Note: `google.ts` uses the same OR logic, so this is consistent with the existing codebase — but worth aligning the comment or changing both sites if the intent really is a pure fallback.

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b2e05eee3

ℹ️ 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 +156 to +158
const staleByLegacyOrdering = i < latestCompactionSummaryIndex;

if (!staleByTimestamp && !staleByLegacyOrdering) {

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.

P2 Badge Zero stale usage for summary-first sessions without timestamps

For sessions whose active branch uses pi-agent-core's summary-first compaction layout, the kept pre-compaction assistant messages come after the compactionSummary marker. Older/imported transcripts can still have assistant messages without a message-level timestamp, so staleByTimestamp stays false and this i < latestCompactionSummaryIndex fallback also stays false for those kept assistants. The result is that their pre-compaction usage survives, and the post-compaction context counter remains inflated for legacy sessions instead of resetting stale usage.

Useful? React with 👍 / 👎.

@Hollychou924

This comment was marked as spam.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dd840fe854

ℹ️ 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 +150 to +154
const staleByTimestamp =
latestCompactionTimestamp !== null &&
messageTimestamp !== null &&
messageTimestamp <= latestCompactionTimestamp;
const staleByLegacyOrdering = i < latestCompactionSummaryIndex;

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.

P2 Badge Handle summary-first compaction transcripts without timestamps

When pi-agent-core stores the latest compactionSummary before the kept messages, stale assistant replies can sit after the summary marker. If one of those assistant entries lacks a parseable timestamp, staleByTimestamp is false and this i < latestCompactionSummaryIndex fallback is also false, so its pre-compaction usage is preserved and the TUI context meter stays inflated after compaction. Fresh evidence: src/agents/pi-embedded-runner.sanitize-session-history.test.ts:507 already codifies this summary-first ordering, so this handler will hit the same layout unless timestamp-less assistants after the summary are also treated as stale.

Useful? React with 👍 / 👎.

@zhuqingxun

Copy link
Copy Markdown

+1 for merging. This is the other half of the streaming usage fix — even when usage data is correctly captured (#50045), the unconditional zeroing in clearStaleAssistantUsageOnSessionMessages() wipes it after compaction.

The two-pass approach (find compaction cutoff → zero only pre-compaction messages) is correct and consistent with the existing google.ts implementation.

Agree with the Greptile review suggestion to extract parseMessageTimestamp to a shared utility to prevent drift.

Combined with #50045, this would fully resolve the compaction failure for non-native OpenAI-compatible providers like Bailian/DashScope.

@jalehman jalehman self-assigned this Mar 21, 2026
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from dd840fe to 9a53c88 Compare March 21, 2026 19:58

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9a53c88dc8

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

@@ -64,11 +64,11 @@ export function handleAutoCompactionEnd(
emitAgentEvent({
runId: ctx.params.runId,
stream: "compaction",
data: { phase: "end", willRetry, completed: hasResult && !wasAborted },
data: { phase: "end", willRetry },

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.

P1 Badge Restore completed on compaction end events

When a compaction succeeds but the embedded run later retries or throws before returning a final result, downstream listeners still rely on evt.data.completed === true to distinguish a real compaction from an aborted one. In this repo, src/auto-reply/reply/agent-runner-execution.ts:443, src/auto-reply/reply/followup-runner.ts:272, and src/auto-reply/reply/agent-runner-memory.ts:565 all treat a missing field as “not completed”, so dropping it here causes successful compactions to be ignored: fallback attempts undercount compactionCount, and memory-flush runs stop updating memoryFlushCompactionCount, which re-enables duplicate flushes for the same compaction cycle. The existing regression tests already codify that strict contract in src/auto-reply/reply/agent-runner-memory.dedup.test.ts:164 and src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts:524.

Useful? React with 👍 / 👎.

@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 9a53c88 to 48a1c64 Compare March 21, 2026 20:03
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 48a1c64 to 9d15415 Compare March 21, 2026 20:08

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d15415b80

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

@@ -64,11 +64,11 @@ export function handleAutoCompactionEnd(
emitAgentEvent({
runId: ctx.params.runId,
stream: "compaction",
data: { phase: "end", willRetry, completed: hasResult && !wasAborted },
data: { phase: "end", willRetry },

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.

P1 Badge Restore completed on compaction end events

Dropping completed from the phase: "end" payload breaks existing listeners that still use the strict evt.data.completed === true contract to recognize a successful compaction. In the current tree, src/auto-reply/reply/agent-runner-execution.ts:443-447, src/auto-reply/reply/followup-runner.ts:272-275, and src/auto-reply/reply/agent-runner-memory.ts:563-566 all ignore end events without that flag, so successful compactions stop incrementing attempt counts and memory-flush dedup no longer latches. Fresh evidence: this commit also updated src/plugins/wired-hooks-compaction.test.ts:145-182 to remove completed from the expected payload, so the regression is now codified instead of caught.

Useful? React with 👍 / 👎.

Comment on lines +150 to +154
const staleByTimestamp =
latestCompactionTimestamp !== null &&
messageTimestamp !== null &&
messageTimestamp <= latestCompactionTimestamp;
const staleByLegacyOrdering = i < latestCompactionSummaryIndex;

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.

P2 Badge Zero stale usage for summary-first entries without timestamps

This logic only clears an assistant snapshot when its timestamp is at or before the latest compaction marker, or when the assistant sits before that marker. In a summary-first transcript, any kept pre-compaction assistant stored after compactionSummary but missing or carrying an unparsable timestamp misses both checks and keeps its stale pre-compaction usage, so the TUI context counter stays inflated on those sessions. Fresh evidence: src/agents/pi-embedded-runner.sanitize-session-history.test.ts:491-542 already codifies summary-first ordering, while this commit's new coverage in src/plugins/wired-hooks-compaction.test.ts:305-335 only exercises timestamped assistants.

Useful? React with 👍 / 👎.

@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 9d15415 to 9621111 Compare March 21, 2026 20:15

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 962111131c

ℹ️ 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 +118 to +122
let latestCompactionSummaryIndex = -1;
let latestCompactionTimestamp: number | null = null;
for (let i = 0; i < messages.length; i += 1) {
const entry = messages[i] as { role?: unknown; timestamp?: unknown } | undefined;
if (entry?.role !== "compactionSummary") {

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.

P1 Badge Don’t key the live compaction reset off a compactionSummary marker

This handler is inspecting ctx.params.session.messages for a { role: "compactionSummary" } cutoff, but in the current tree that role only exists in the type augmentation and test fixtures (src/types/pi-agent-core.d.ts; src/agents/pi-embedded-runner.sanitize-session-history.test.ts), not in any production writer for the live embedded session. Our own compaction harness still models session.compact() by trimming session.messages without inserting such a marker (src/agents/pi-embedded-runner/compact.hooks.harness.ts:217-220), so latestCompactionSummaryIndex stays -1 and we fall back to zeroing every assistant snapshot exactly as before. In that path the TUI context meter can still stick at zero after compaction, so this fix does not address the normal auto-compaction flow.

Useful? React with 👍 / 👎.

@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 9621111 to 93727d1 Compare March 21, 2026 22:06
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 93727d1 to 2e9c70e Compare March 21, 2026 22:07

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e9c70ea78

ℹ️ 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 +138 to +139
if (!candidate.usage || typeof candidate.usage !== "object") {
continue;

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.

P2 Badge Restore zero snapshots for stale assistants without usage

If a kept pre-compaction assistant came from a provider or imported transcript that never populated message.usage, this new guard now skips it entirely instead of restoring the previous zeroed snapshot. The live subscribe path does not normalize assistant usage anywhere else (src/agents/pi-embedded-subscribe.ts:272-285 just records whatever arrives), while src/agents/pi-embedded-runner/google.ts:265-306 and src/agents/pi-embedded-runner.sanitize-session-history.test.ts:386-397 codify the opposite invariant: every assistant should carry at least makeZeroUsageSnapshot() for later context accounting. In those sessions, compaction can now leave stale assistant entries with missing usage again, which reopens the same missing-usage undercounting/crash path this code comment is trying to avoid.

Useful? React with 👍 / 👎.

@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 2e9c70e to 8f998fa Compare March 23, 2026 18:37
@openclaw-barnacle openclaw-barnacle Bot added the cli CLI command changes label Mar 23, 2026
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from 8f998fa to ff823dc Compare March 23, 2026 18:52
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from ff823dc to da82e16 Compare March 23, 2026 18:54

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: da82e16144

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

@@ -64,11 +64,11 @@ export function handleAutoCompactionEnd(
emitAgentEvent({
runId: ctx.params.runId,
stream: "compaction",
data: { phase: "end", willRetry, completed: hasResult && !wasAborted },
data: { phase: "end", willRetry },

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.

P1 Badge Restore completed on compaction end events

Removing completed here breaks existing listeners that still use the strict evt.data.completed === true contract to recognize a successful compaction. In this commit, src/auto-reply/reply/agent-runner-execution.ts:443-447 and src/auto-reply/reply/followup-runner.ts:232-233 will now ignore real compactions, so fallback attempts undercount compaction cycles and downstream dedup/state updates stop latching after a successful compaction.

Useful? React with 👍 / 👎.

Comment on lines +148 to +156
if (latestCompactionSummaryIndex !== -1) {
const messageTimestamp = parseMessageTimestamp(candidate.timestamp);
const staleByTimestamp =
latestCompactionTimestamp !== null &&
messageTimestamp !== null &&
messageTimestamp <= latestCompactionTimestamp;
const staleByLegacyOrdering = i < latestCompactionSummaryIndex;

if (!staleByTimestamp && !staleByLegacyOrdering) {

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.

P2 Badge Don’t key the reset logic off a compactionSummary marker

This branch only narrows the reset when session.messages already contains a { role: "compactionSummary" } entry, but repo-wide search in this commit shows no production writer for that marker—only the type augmentation/tests mention it, while the live compaction harness in src/agents/pi-embedded-runner/compact.hooks.harness.ts:223-225 still models compaction by trimming session.messages directly. In the normal auto-compaction flow latestCompactionSummaryIndex stays -1, so we still fall back to zeroing every assistant snapshot and the TUI context counter remains stuck at zero after compaction.

Useful? React with 👍 / 👎.

@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch 2 times, most recently from 1cc894c to e31a677 Compare March 25, 2026 04:56
@openclaw-barnacle openclaw-barnacle Bot added the app: web-ui App: web-ui label Mar 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e31a677feb

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

@@ -64,11 +64,11 @@ export function handleAutoCompactionEnd(
emitAgentEvent({
runId: ctx.params.runId,
stream: "compaction",
data: { phase: "end", willRetry, completed: hasResult && !wasAborted },
data: { phase: "end", willRetry },

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.

P1 Badge Emit compaction end events with completed status

Dropping completed from the phase: "end" payload breaks existing listeners that still treat success as evt.data.completed === true (for example src/auto-reply/reply/agent-runner-execution.ts:443-447 and src/auto-reply/reply/followup-runner.ts:232-235). When a compaction succeeds but the surrounding run later retries or fails before returning a final result, those listeners now ignore the successful compaction end event, so compaction counts and end-of-compaction callbacks become inaccurate.

Useful? React with 👍 / 👎.

@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from e31a677 to d5dc942 Compare March 25, 2026 05:05
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch 2 times, most recently from 6616164 to c0e2325 Compare March 25, 2026 16:56

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0e2325a40

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

@@ -64,11 +64,11 @@ export function handleAutoCompactionEnd(
emitAgentEvent({
runId: ctx.params.runId,
stream: "compaction",
data: { phase: "end", willRetry, completed: hasResult && !wasAborted },
data: { phase: "end", willRetry },

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.

P1 Badge Include completed on compaction end events

Dropping completed from the emitted phase: "end" payload breaks current auto-reply listeners that still gate on evt.data.completed === true (checked src/auto-reply/reply/agent-runner-execution.ts:443-447 and src/auto-reply/reply/followup-runner.ts:232-235), so successful compactions from this handler are ignored in those paths. This is especially harmful when a compaction succeeds but the attempt later retries/fails before a final result meta is available, because the event is the only signal that increments compaction-aware counters/callbacks for that attempt.

Useful? React with 👍 / 👎.

HollyChou and others added 6 commits March 25, 2026 12:06
…Stale

The clearStaleAssistantUsageOnSessionMessages() function was zeroing ALL
assistant message usage after any compaction, including messages created
AFTER the compaction. This caused the TUI '📚 Context' counter to always
show 0/1.0m (0%) even after successful LLM responses.

Fix: locate the latest compactionSummary message, then only zero usage
for assistant messages that are older than (or at the same index as) the
compaction summary. Post-compaction messages retain their accurate usage
data so the context counter reflects the real post-compaction token count.

The google.ts runner already used the correct pattern
(stripStaleAssistantUsageBeforeLatestCompaction). This brings the
compaction event handler into alignment with that approach.

Added parseMessageTimestamp() helper (mirrors the implementation in
google.ts) for timestamp-based staleness detection with index-based
legacy fallback for messages without timestamps.

Fixes openclaw#50795
…mpactionSummary exists

The previous fix introduced a guard that returned early when no
compactionSummary message was found in the session. This broke the
existing test which exercises the pre-compaction-summary code path
(legacy sessions and in-progress compactions).

Fix: when latestCompactionSummaryIndex === -1, skip the staleness
check entirely and zero out all assistant usage, preserving the
original behaviour from before the over-selective guard was added.
Keep the compaction end event payload at { phase, willRetry } so this usage-accounting fix does not widen the compaction event contract. Add focused coverage for clearing pre-compaction assistant usage while preserving assistant usage created after the latest compaction summary, and record the user-visible fix in the changelog.

Regeneration-Prompt: |
  Prepare PR openclaw#50845 for merge after review. The required maintainer direction was
  to keep the compaction end event payload unchanged for this bug fix and to add
  a direct regression test proving pre-compaction assistant usage is zeroed while
  post-compaction assistant usage is preserved after the latest compactionSummary.
  Keep the scope tight to the compaction subscribe handler, its focused wiring
  test, and the required Unreleased changelog entry. Do not delete the worktree
  or broaden the event contract.
@jalehman
jalehman force-pushed the fix/compaction-context-usage-zeroed-50795 branch from c0e2325 to 8b770dc Compare March 25, 2026 19:21

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8b770dca9d

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

runId: ctx.params.runId,
stream: "compaction",
data: { phase: "end", willRetry, completed: hasResult && !wasAborted },
data: { phase: "end", willRetry },

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.

P1 Badge Include completed flag in compaction end events

Restore completed on the phase: "end" compaction payload; removing it breaks existing consumers that still require evt.data.completed === true to treat a compaction as successful (for example src/auto-reply/reply/agent-runner-execution.ts and src/auto-reply/reply/followup-runner.ts). In runs where compaction succeeds but the attempt later retries or errors before final result metadata is consumed, those listeners now miss the success signal, so compaction-aware counters and end callbacks become inaccurate.

Useful? React with 👍 / 👎.

@jalehman jalehman closed this Mar 26, 2026
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request Jun 16, 2026
…26.6.8) (#1144)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/openclaw/openclaw](https://openclaw.ai) ([source](https://github.com/openclaw/openclaw)) | patch | `2026.6.6` → `2026.6.8` |

---

### Release Notes

<details>
<summary>openclaw/openclaw (ghcr.io/openclaw/openclaw)</summary>

### [`v2026.6.8`](https://github.com/openclaw/openclaw/blob/HEAD/CHANGELOG.md#202668)

[Compare Source](openclaw/openclaw@v2026.6.6...v2026.6.8)

##### Highlights

- Telegram and WhatsApp channel delivery are richer and less brittle: Telegram can send structured rich text with tables, lists, expandable blockquotes, prompt-preserving CLI backend delivery, retired native draft migration, and safer rich-media boundaries, while WhatsApp now honors configured ACP bindings. ([#&#8203;92679](openclaw/openclaw#92679), [#&#8203;84082](openclaw/openclaw#84082), [#&#8203;89421](openclaw/openclaw#89421), [#&#8203;92513](openclaw/openclaw#92513)) Thanks [@&#8203;obviyus](https://github.com/obviyus), [@&#8203;jzakirov](https://github.com/jzakirov), [@&#8203;spacegeologist](https://github.com/spacegeologist), and [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Agent and Gateway recovery is sharper across account-scoped DM sends, generated media completions, restart shutdown aborts, yielded subagent pauses, yielded cron media, heartbeat dedupe, session identity prompts, and unknown OpenAI agent selector rejection. ([#&#8203;92788](openclaw/openclaw#92788), [#&#8203;91246](openclaw/openclaw#91246), [#&#8203;91357](openclaw/openclaw#91357), [#&#8203;92631](openclaw/openclaw#92631), [#&#8203;92146](openclaw/openclaw#92146), [#&#8203;91287](openclaw/openclaw#91287), [#&#8203;92468](openclaw/openclaw#92468), [#&#8203;92510](openclaw/openclaw#92510)) Thanks [@&#8203;yetval](https://github.com/yetval), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;ooiuuii](https://github.com/ooiuuii), [@&#8203;openperf](https://github.com/openperf), [@&#8203;IWhatsskill](https://github.com/IWhatsskill), [@&#8203;ZengWen-DT](https://github.com/ZengWen-DT), and [@&#8203;zhangguiping-xydt](https://github.com/zhangguiping-xydt).
- Provider/model handling expands and tightens with GLM-5.2, Claude Haiku 4.5 catalog rows, OpenRouter and Google Vertex provider-prefix normalization, managed SecretRef auth, bounded model browse discovery, storeless OpenAI Responses replay gating, and Claude 4.5 Copilot tool-streaming safety. ([#&#8203;92796](openclaw/openclaw#92796), [#&#8203;90116](openclaw/openclaw#90116), [#&#8203;92627](openclaw/openclaw#92627), [#&#8203;91218](openclaw/openclaw#91218), [#&#8203;90686](openclaw/openclaw#90686), [#&#8203;92247](openclaw/openclaw#92247), [#&#8203;90706](openclaw/openclaw#90706), [#&#8203;75393](openclaw/openclaw#75393)) Thanks [@&#8203;arkyu2077](https://github.com/arkyu2077), [@&#8203;liuhao1024](https://github.com/liuhao1024), [@&#8203;bymle](https://github.com/bymle), [@&#8203;rohitjavvadi](https://github.com/rohitjavvadi), [@&#8203;samson910022](https://github.com/samson910022), [@&#8203;snowzlm](https://github.com/snowzlm), and [@&#8203;Kailigithub](https://github.com/Kailigithub).
- `/usage` and reply payload hooks now have a native full footer renderer, default template, fixed-decimal formatting, credential-aware limits, better partial-count handling, and warnings for broken templates instead of silent bad output. ([#&#8203;92657](openclaw/openclaw#92657), [#&#8203;89835](openclaw/openclaw#89835), [#&#8203;89629](openclaw/openclaw#89629)) Thanks [@&#8203;Marvinthebored](https://github.com/Marvinthebored).
- UI and mobile flows are steadier: workspace files can collapse and start collapsed, WebChat backscroll survives streaming, the sidebar session picker remains interactive above the desktop workbench, reset soft args survive UI dispatch, stale dashboard session parent lineage is preserved, and iOS reconnects stale foreground gateways. ([#&#8203;92779](openclaw/openclaw#92779), [#&#8203;92622](openclaw/openclaw#92622), [#&#8203;92705](openclaw/openclaw#92705), [#&#8203;91353](openclaw/openclaw#91353), [#&#8203;90658](openclaw/openclaw#90658), [#&#8203;92552](openclaw/openclaw#92552)) Thanks [@&#8203;shakkernerd](https://github.com/shakkernerd), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;NianJiuZst](https://github.com/NianJiuZst), [@&#8203;zhouhe-xydt](https://github.com/zhouhe-xydt), [@&#8203;luoyanglang](https://github.com/luoyanglang), and [@&#8203;Solvely-Colin](https://github.com/Solvely-Colin).
- Memory, state, and diagnostics recover cleaner: oversized OpenAI embedding batches split before 431s, QMD memory search stays available in transient mode, SQLite avoids WAL on NFS state volumes, stuck-session recovery scheduling no longer resets warning backoff, and Infinity chunk limits stay genuinely unbounded. ([#&#8203;92650](openclaw/openclaw#92650), [#&#8203;92618](openclaw/openclaw#92618), [#&#8203;92639](openclaw/openclaw#92639), [#&#8203;91247](openclaw/openclaw#91247), [#&#8203;92752](openclaw/openclaw#92752), [#&#8203;92735](openclaw/openclaw#92735)) Thanks [@&#8203;mushuiyu886](https://github.com/mushuiyu886), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;849261680](https://github.com/849261680), [@&#8203;gnanam1990](https://github.com/gnanam1990), and [@&#8203;yhterrance](https://github.com/yhterrance).

##### Changes

- Providers/models: add GLM-5.2 support and Claude Haiku 4.5 catalog entries while keeping provider-qualified model IDs normalized across OpenRouter and Google Vertex paths. ([#&#8203;92796](openclaw/openclaw#92796), [#&#8203;90116](openclaw/openclaw#90116), [#&#8203;92627](openclaw/openclaw#92627), [#&#8203;91218](openclaw/openclaw#91218)) Thanks [@&#8203;arkyu2077](https://github.com/arkyu2077), [@&#8203;liuhao1024](https://github.com/liuhao1024), and [@&#8203;bymle](https://github.com/bymle).
- Channel plugins: ship Telegram rich-message delivery and WhatsApp ACP binding support, including rich prompt handoff to CLI backends and transport fixtures for richer drafts. ([#&#8203;92679](openclaw/openclaw#92679), [#&#8203;92513](openclaw/openclaw#92513)) Thanks [@&#8203;obviyus](https://github.com/obviyus) and [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Agent commands: support `/btw` in CLI-backed sessions and keep CLI usage-error exits classified as usage failures instead of successful runs. ([#&#8203;92669](openclaw/openclaw#92669), [#&#8203;92162](openclaw/openclaw#92162)) Thanks [@&#8203;joshavant](https://github.com/joshavant) and [@&#8203;Pandah97](https://github.com/Pandah97).
- Usage hooks: add built-in full footer rendering, default footer templates, per-turn usage state, credential-aware limits, and fixed-decimal formatting for usage-bar templates. ([#&#8203;92657](openclaw/openclaw#92657), [#&#8203;89835](openclaw/openclaw#89835), [#&#8203;89629](openclaw/openclaw#89629)) Thanks [@&#8203;Marvinthebored](https://github.com/Marvinthebored).
- Docs and operator guidance: document node config examples, clarify before-install hook scope, correct agent default concurrency comments, refresh ZAI provider docs, and update channel/group docs for current Telegram and WhatsApp behavior. ([#&#8203;92677](openclaw/openclaw#92677), [#&#8203;92766](openclaw/openclaw#92766), [#&#8203;92695](openclaw/openclaw#92695)) Thanks [@&#8203;liuhao1024](https://github.com/liuhao1024), [@&#8203;sallyom](https://github.com/sallyom), and [@&#8203;ArielSmoliar](https://github.com/ArielSmoliar).

##### Fixes

- Onboarding/skills: show the Homebrew install recommendation only on macOS and Linux, so FreeBSD and other unsupported platforms no longer get a misleading brew prompt. Fixes [#&#8203;68893](openclaw/openclaw#68893); carries forward [#&#8203;68894](openclaw/openclaw#68894), [#&#8203;68910](openclaw/openclaw#68910), [#&#8203;68941](openclaw/openclaw#68941), [#&#8203;68943](openclaw/openclaw#68943), [#&#8203;69002](openclaw/openclaw#69002), and [#&#8203;69545](openclaw/openclaw#69545). Thanks [@&#8203;yurivict](https://github.com/yurivict), [@&#8203;Sanjays2402](https://github.com/Sanjays2402), [@&#8203;Eruditi](https://github.com/Eruditi), [@&#8203;JustInCache](https://github.com/JustInCache), [@&#8203;nnish16](https://github.com/nnish16), and [@&#8203;Mlightsnow](https://github.com/Mlightsnow).
- Channels and delivery: preserve account-scoped DM channel send policy, rich Telegram final replies, rich Telegram tables and lists, Telegram thread-create CLI remapping, Slack outbound `message_sent` hooks, contributed message-tool schema optionality, same-channel generated media completions, and channel chunking around surrogate pairs and Infinity limits. ([#&#8203;92788](openclaw/openclaw#92788), [#&#8203;92679](openclaw/openclaw#92679), [#&#8203;89421](openclaw/openclaw#89421), [#&#8203;89943](openclaw/openclaw#89943), [#&#8203;91137](openclaw/openclaw#91137), [#&#8203;91246](openclaw/openclaw#91246), [#&#8203;92735](openclaw/openclaw#92735)) Thanks [@&#8203;yetval](https://github.com/yetval), [@&#8203;obviyus](https://github.com/obviyus), [@&#8203;spacegeologist](https://github.com/spacegeologist), [@&#8203;rishitamrakar](https://github.com/rishitamrakar), [@&#8203;lundog](https://github.com/lundog), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), and [@&#8203;yhterrance](https://github.com/yhterrance).
- Auto-reply/groups: keep ordinary group text replies on automatic final-reply delivery while allowing `message(action=send)` for files, images, and other attachments to the same group or topic. Carries forward [#&#8203;43276](openclaw/openclaw#43276); refs [#&#8203;48004](openclaw/openclaw#48004). Thanks [@&#8203;NayukiChiba](https://github.com/NayukiChiba) and [@&#8203;ShakaRover](https://github.com/ShakaRover).
- Auto-reply/skills: preserve multiline payloads for `/skill` and direct skill slash commands while keeping command-head normalization for aliases, colon syntax, and bot mentions. Fixes [#&#8203;79155](openclaw/openclaw#79155); carries forward [#&#8203;81305](openclaw/openclaw#81305). Thanks [@&#8203;web3blind](https://github.com/web3blind).
- iMessage: normalize leading NUL sent-message echo prefixes while preserving interior NUL bytes and the leading attributedBody marker handling from [#&#8203;73942](openclaw/openclaw#73942). Carries forward [#&#8203;63581](openclaw/openclaw#63581). Thanks [@&#8203;drvoss](https://github.com/drvoss).
- Discord: give generated auto-thread titles a 60-second timeout and 4,096-token reasoning-model output budget, clamped to the selected model output cap. ([#&#8203;64734](openclaw/openclaw#64734)) Thanks [@&#8203;hanamizuki](https://github.com/hanamizuki).
- Agent, cron, and Gateway runtime: mark active main sessions before restart shutdown aborts, pause yielded subagent runs whose terminal also signals abort, preserve yielded media completions, de-duplicate main-session heartbeat events, expose session identity in runtime prompts, reject unknown OpenAI agent selectors, keep generated media completions and slash-command block replies in WebChat, preserve fresh post-compaction usage while clearing stale usage snapshots, and require admin privileges for HTTP session/model override surfaces. ([#&#8203;91357](openclaw/openclaw#91357), [#&#8203;92631](openclaw/openclaw#92631), [#&#8203;92146](openclaw/openclaw#92146), [#&#8203;91287](openclaw/openclaw#91287), [#&#8203;92468](openclaw/openclaw#92468), [#&#8203;92510](openclaw/openclaw#92510), [#&#8203;91246](openclaw/openclaw#91246), [#&#8203;50795](openclaw/openclaw#50795), [#&#8203;50845](openclaw/openclaw#50845), [#&#8203;82874](openclaw/openclaw#82874), [#&#8203;92651](openclaw/openclaw#92651), [#&#8203;92646](openclaw/openclaw#92646)) Thanks [@&#8203;ooiuuii](https://github.com/ooiuuii), [@&#8203;openperf](https://github.com/openperf), [@&#8203;IWhatsskill](https://github.com/IWhatsskill), [@&#8203;ZengWen-DT](https://github.com/ZengWen-DT), [@&#8203;zhangguiping-xydt](https://github.com/zhangguiping-xydt), [@&#8203;Hollychou924](https://github.com/Hollychou924), [@&#8203;leno23](https://github.com/leno23), and [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle).
- Agents/exec: default empty-success background completion notices on only for real chat channels, preserving explicit opt-outs and keeping generic providers silent while carrying forward the narrow UX intent from [#&#8203;39726](openclaw/openclaw#39726) and [#&#8203;46926](openclaw/openclaw#46926). Thanks [@&#8203;Sapientropic](https://github.com/Sapientropic) and [@&#8203;wenkang-xie](https://github.com/wenkang-xie).
- Providers and model replay: preserve storeless OpenAI Responses replay compatibility, avoid eager tool streaming for Claude 4.5 in Copilot, honor profile auth for SecretRef model entries, bound model browsing, strip provider prefixes where runtimes need bare IDs, and surface nested embedding fetch failures. ([#&#8203;90706](openclaw/openclaw#90706), [#&#8203;75393](openclaw/openclaw#75393), [#&#8203;90686](openclaw/openclaw#90686), [#&#8203;92247](openclaw/openclaw#92247), [#&#8203;92627](openclaw/openclaw#92627), [#&#8203;91218](openclaw/openclaw#91218), [#&#8203;92628](openclaw/openclaw#92628)) Thanks [@&#8203;snowzlm](https://github.com/snowzlm), [@&#8203;Kailigithub](https://github.com/Kailigithub), [@&#8203;rohitjavvadi](https://github.com/rohitjavvadi), [@&#8203;samson910022](https://github.com/samson910022), [@&#8203;liuhao1024](https://github.com/liuhao1024), [@&#8203;bymle](https://github.com/bymle), and [@&#8203;mushuiyu886](https://github.com/mushuiyu886).
- Memory, state, diagnostics, and config: split header-too-large embedding batches, keep QMD memory search enabled in transient mode, avoid SQLite WAL on NFS volumes, preserve recovery scheduling outside stuck-session warning backoff, and keep shell environment fallbacks contained in config write tests. ([#&#8203;92650](openclaw/openclaw#92650), [#&#8203;92618](openclaw/openclaw#92618), [#&#8203;92639](openclaw/openclaw#92639), [#&#8203;91247](openclaw/openclaw#91247), [#&#8203;92752](openclaw/openclaw#92752)) Thanks [@&#8203;mushuiyu886](https://github.com/mushuiyu886), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;849261680](https://github.com/849261680), and [@&#8203;gnanam1990](https://github.com/gnanam1990).
- Workspace setup state: store setup completion outside the workspace dot directory using an OpenClaw-named root file, migrate valid legacy state forward, and avoid clobbering generic root `workspace-state.json` files for TigerFS-style dot-path compatibility. This Clownfish replacement carries forward the focused [#&#8203;53326](openclaw/openclaw#53326) fix idea because the original branch was closed and uneditable. ([#&#8203;53326](openclaw/openclaw#53326), [#&#8203;44783](openclaw/openclaw#44783), [#&#8203;39446](openclaw/openclaw#39446)) Thanks [@&#8203;1qh](https://github.com/1qh).
- UI/mobile/TUI: preserve dashboard session parent lineage, WebChat backscroll, reset soft command args, sidebar session picker interactivity, collapsed workspace files, resolved `/model` confirmation refs, and stale foreground iOS Gateway reconnects. ([#&#8203;90658](openclaw/openclaw#90658), [#&#8203;92622](openclaw/openclaw#92622), [#&#8203;91353](openclaw/openclaw#91353), [#&#8203;92705](openclaw/openclaw#92705), [#&#8203;92779](openclaw/openclaw#92779), [#&#8203;92773](openclaw/openclaw#92773), [#&#8203;92552](openclaw/openclaw#92552)) Thanks [@&#8203;luoyanglang](https://github.com/luoyanglang), [@&#8203;TurboTheTurtle](https://github.com/TurboTheTurtle), [@&#8203;zhouhe-xydt](https://github.com/zhouhe-xydt), [@&#8203;NianJiuZst](https://github.com/NianJiuZst), [@&#8203;shakkernerd](https://github.com/shakkernerd), [@&#8203;NarahariRaghava](https://github.com/NarahariRaghava), and [@&#8203;Solvely-Colin](https://github.com/Solvely-Colin).
- TUI: reload the active session after external `/new` or `/reset` session-change events so stale transcript and stream state clear promptly. Fixes [#&#8203;38966](openclaw/openclaw#38966); carries forward [#&#8203;40472](openclaw/openclaw#40472). Thanks [@&#8203;yizhanzjz](https://github.com/yizhanzjz) and [@&#8203;wsyjh8](https://github.com/wsyjh8).
- Control UI: preserve Gateway Access tokens during same-normalized WebSocket URL edits and reload gateway-scoped tokens when switching endpoints. Fixes [#&#8203;41545](openclaw/openclaw#41545); repairs [#&#8203;42001](openclaw/openclaw#42001) with additional source PRs [#&#8203;41546](openclaw/openclaw#41546), [#&#8203;41552](openclaw/openclaw#41552), and [#&#8203;41718](openclaw/openclaw#41718). Thanks [@&#8203;wsyjh8](https://github.com/wsyjh8), [@&#8203;llagy0020](https://github.com/llagy0020), [@&#8203;llagy007](https://github.com/llagy007), [@&#8203;pingfanfan](https://github.com/pingfanfan), and [@&#8203;zheliu2](https://github.com/zheliu2).
- Gateway CLI: tolerate a single transient clean WebSocket close before `hello-ok` so one-shot RPC calls reconnect instead of failing noisily, while repeated clean pre-hello closes still surface. Carries forward source PRs [#&#8203;54475](openclaw/openclaw#54475) and [#&#8203;54774](openclaw/openclaw#54774); [#&#8203;85253](openclaw/openclaw#85253) covered adjacent connect assembly diagnostics. Thanks [@&#8203;ruanrrn](https://github.com/ruanrrn).
- Gateway/Linux: keep root-owned systemd user service lifecycle commands on root's user manager when a stale `SUDO_USER` remains in a root shell with root's user bus environment. Fixes [#&#8203;81410](openclaw/openclaw#81410). Thanks [@&#8203;Ericksza](https://github.com/Ericksza) and [@&#8203;ChuckClose-tech](https://github.com/ChuckClose-tech).
- Release and test reliability: extend slow Gateway/full-suite watchdogs, split local full-suite shards when throttled, stabilize plugin auth marker fixtures, avoid brittle provider-ref error text, and keep QA Lab bootstrap selection assertions aligned with flow-only scenarios. ([#&#8203;92652](openclaw/openclaw#92652))
- macOS Peekaboo bridge: update the embedded Peekaboo package to 3.5.2 and route bundled-skill CLI commands through the OpenClaw app bridge so they inherit its Screen Recording and Accessibility grants.
- Agent routing: route subagent RPC callbacks addressed to an agent-shaped `--to` target to the correct session key instead of falling back to the main session, so WeChat (and other channel) session-key callbacks reach the intended subagent session. ([#&#8203;90231](openclaw/openclaw#90231)) Thanks [@&#8203;zhangguiping-xydt](https://github.com/zhangguiping-xydt).
- Cron: preserve model, fallback, thinking, timeout, light-context, unsafe-content, and tool allow-list overrides on implicit text payloads by promoting them to agent turns, while explicit system events still prune those fields. Fixes [#&#8203;28905](openclaw/openclaw#28905); carries forward [#&#8203;64060](openclaw/openclaw#64060) and [#&#8203;73946](openclaw/openclaw#73946). Thanks [@&#8203;liaoandi](https://github.com/liaoandi).
- QQBot delivery: keep markdown table chunks self-contained across message boundaries by preserving table state across block deliveries, flushing unfinished table-row fragments as plain text, and detecting short pipe-terminated rows by column count so split rows are not sent as malformed markdown. ([#&#8203;92428](openclaw/openclaw#92428)) Thanks [@&#8203;sliverp](https://github.com/sliverp).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19-->

Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/1144
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui cli CLI command changes size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Context token count always shows 0 after compaction

3 participants