Skip to content

fix: compaction safeguard summary budget#27727

Merged
jalehman merged 14 commits intoopenclaw:mainfrom
Pandadadadazxf:fix/compaction-safeguard-summary-budget
Mar 21, 2026
Merged

fix: compaction safeguard summary budget#27727
jalehman merged 14 commits intoopenclaw:mainfrom
Pandadadadazxf:fix/compaction-safeguard-summary-budget

Conversation

@Pandadadadazxf
Copy link
Copy Markdown
Contributor

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: compaction-safeguard can append large file operation lists (read-files / modified-files) and other metadata to the compaction summary, which can make the summary itself too large.
  • Why it matters: Oversized compaction summaries reduce the effectiveness of compaction and can consume context budget that should be preserved for future turns.
  • What changed: Added bounded formatting for file operation sections (with ...and N more) and a final compaction summary length cap with a truncation marker; added tests for both behaviors.
  • What did NOT change (scope boundary): No changes to compaction triggering, token estimation, summarization model selection, or pruning strategy logic.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #

User-visible / Behavior Changes

  • Compaction summaries now truncate oversized file operation sections and may include ...and N more.
  • Compaction summaries now include a truncation marker when the final summary exceeds the configured internal size budget.
  • No config/default changes exposed to users.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS (local dev machine)
  • Runtime/container: local Node binary (.tools/node-v22.22.0-darwin-arm64)
  • Model/provider: N/A (unit tests only)
  • Integration/channel (if any): N/A
  • Relevant config (redacted): N/A

Steps

  1. Modify src/agents/pi-extensions/compaction-safeguard.ts to cap file-op summary size and final compaction summary length.
  2. Add tests in src/agents/pi-extensions/compaction-safeguard.test.ts covering file-op truncation and summary truncation marker.
  3. Run PATH="$PWD/.tools/node-v22.22.0-darwin-arm64/bin:$PATH" npm exec vitest run src/agents/pi-extensions/compaction-safeguard.test.ts.

Expected

  • File operation summary output is bounded and includes ...and N more when truncated.
  • Final compaction summary is capped and ends with a truncation marker when oversized.
  • Test file passes.

Actual

  • Behavior matches expected.
  • compaction-safeguard test file passes (24 tests).

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: Ran src/agents/pi-extensions/compaction-safeguard.test.ts locally after changes; confirmed new tests pass and existing tests remain green.
  • Edge cases checked: Very large file-op lists trigger truncation; oversized summary gets capped and appends truncation marker.
  • What you did not verify: End-to-end compaction flow against a live provider/model; impact on real long-running sessions.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert commit afc741b (or revert the PR commit) to restore previous compaction summary behavior.
  • Files/config to restore: src/agents/pi-extensions/compaction-safeguard.ts, src/agents/pi-extensions/compaction-safeguard.test.ts
  • Known bad symptoms reviewers should watch for: Missing file-op metadata in compaction summaries when lists are unexpectedly small; malformed truncation marker placement; over-aggressive truncation of summaries.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk: Truncation budget may cut off useful compaction context in edge cases with unusually dense metadata.
    • Mitigation: File-op sections and final summary use separate caps; truncation is explicit via marker / ...and N more, and core compaction logic is unchanged.
  • Risk: New formatting helper could produce malformed section tags if the budget is too small.
    • Mitigation: Added unit tests for bounded file-op formatting and final summary capping behavior.

@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S labels Feb 26, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 26, 2026

Greptile Summary

Adds bounded formatting for file operation lists and a final compaction summary length cap to prevent oversized summaries from consuming excessive context budget.

Key Changes:

  • Implements formatBoundedFileList helper that truncates long file lists with ...and N more indicators
  • Adds capCompactionSummary function to enforce a hard cap (16,000 chars) on the final compaction summary
  • Multi-layer budgeting: individual lists capped at 900 chars, combined file-ops section at 2,000 chars, and total summary at 16,000 chars
  • Refactors post-compaction-audit.ts to support both legacy tool_use and newer toolCall formats for better forward compatibility
  • Adds comprehensive test coverage for truncation behaviors

Implementation Notes:

  • The formatBoundedFileList logic uses lookahead to ensure space for overflow indicators, which is conservative but correct
  • Constants are well-sized: two file lists at 900 chars each plus separators (~1,804 chars) fit comfortably under the 2,000 char section limit
  • capCompactionSummary can truncate mid-tag in edge cases, but this is documented as an acceptable trade-off for the safeguard

Confidence Score: 4/5

  • This PR is safe to merge with low risk - it adds defensive truncation logic with comprehensive test coverage
  • Score reflects well-tested implementation with correct logic, though the formatBoundedFileList function is complex and has one redundant condition check. The documented risk of mid-tag truncation in edge cases is acceptable for a safeguard mechanism. The post-compaction-audit refactoring is backward compatible and defensive.
  • No files require special attention - the changes are localized and well-tested

Last reviewed commit: afc741b

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

const overflowLine = remaining > 0 ? `...and ${remaining} more\n` : "";
const projected = usedChars + line.length + overflowLine.length;
if (projected > maxChars) {
if (remaining >= 0) {
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.

redundant condition - remaining >= 0 is always true in this loop since remaining = files.length - i - 1 and i < files.length

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-extensions/compaction-safeguard.ts
Line: 163

Comment:
redundant condition - `remaining >= 0` is always true in this loop since `remaining = files.length - i - 1` and `i < files.length`

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

@Pandadadadazxf Pandadadadazxf force-pushed the fix/compaction-safeguard-summary-budget branch from 7fc5c07 to d10502d Compare February 26, 2026 17:41
Copy link
Copy Markdown

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

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: d10502d8c6

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

if (workspaceContext) {
summary += workspaceContext;
}
summary = capCompactionSummary(summary);
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 Preserve workspace rules when enforcing summary cap

Apply the size cap before appending workspace-critical rules, not after: this line truncates from the front-preserving prefix (capCompactionSummary uses summary.slice(0, budget)), so whenever historySummary is already near 16k chars, the trailing <workspace-critical-rules> block (Session Startup/Red Lines) gets cut off. In long sessions this removes the very post-compaction guardrails this extension is trying to restore, which can change agent behavior after compaction.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — this was a real truncation-order issue.

I updated the compaction safeguard summary capping so the main summary body is capped first and the <workspace-critical-rules> suffix is preserved within the final budget. I also added a regression test to ensure the workspace rules block survives summary truncation.

@jalehman jalehman self-assigned this Mar 3, 2026
Copy link
Copy Markdown
Contributor

@jalehman jalehman left a comment

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.

Support existing toolUse read entries in the audit parser

The audit-side parser change still misses valid read operations recorded as type: "toolUse". Right now extractReadPaths handles tool_use and toolCall, so post-compaction audits can still emit false warnings when transcripts use the camelCase form the repo already preserves. Please update the parser and tests so all currently emitted read block variants are covered.

Split the audit parser change from the summary-budget fix

The bounded summary-budget work in compaction-safeguard looks like the novel part of this PR, but the post-compaction-audit parser update overlaps with narrower open PRs that are already under maintainer triage. Keeping both changes bundled makes review and merge intent unclear. Please drop the audit-parser portion from this PR, or move it into a separate PR, so this change stays focused on the safeguard budget fix.


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

@Pandadadadazxf Pandadadadazxf force-pushed the fix/compaction-safeguard-summary-budget branch from b12c361 to a7e23da Compare March 13, 2026 14:08
Copy link
Copy Markdown

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

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: a7e23da29d

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

if (workspaceContext) {
summary = appendSummarySection(summary, workspaceContext);
}
summary = capCompactionSummaryPreservingSuffix(summary, workspaceContext);
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 Cap main summary before appending diagnostic suffix sections

When summaries approach the 16k cap, this call truncates from the front-preserved prefix (capCompactionSummary uses slice(0, budget)), so the sections appended just before it (tool failures and file operations) are the first content dropped in long sessions. That silently removes exactly the high-signal diagnostics this extension adds, which can reduce continuity after compaction. Applying the cap to the main history body before appending those sections (or preserving them in a reserved suffix budget) would keep them reliably present.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Useful: slice(0, budget) keeps the beginning and trims the end, causing tool failures and file ops to be dropped first—though these are the most valuable diagnostics for compaction.

@Pandadadadazxf
Copy link
Copy Markdown
Contributor Author

Hi @jalehman,

Please re-review and feel free to ask questions and request changes.

Copy link
Copy Markdown

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

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: b9582fa2a6

ℹ️ 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 on lines +1028 to +1030
const diagnosticSuffix = appendSummarySection(
appendSummarySection("", toolFailureSection),
fileOpsSummary,
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 Preserve section separators when building reserved suffix

Building diagnosticSuffix from appendSummarySection("", toolFailureSection) strips the leading \n\n from the first suffix block, and capCompactionSummaryPreservingSuffix later concatenates body and suffix directly (${cappedBody}${suffix}). When the summary body does not end with a newline (for example buildStructuredFallbackSummary), this merges content like ...## Exact identifiers## Tool Failures or ...<workspace-critical-rules> into the prior line, which degrades heading/tag structure and can make the preserved diagnostics/rules less reliably interpreted after compaction.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: 033387929d

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

// ends without newline from buildStructuredFallbackSummary: "...## Exact identifiers## Tool Failures").
const normalizedSuffix =
reservedSuffix && !/^\s/.test(reservedSuffix) ? `\n\n${reservedSuffix}` : reservedSuffix;
summary = capCompactionSummaryPreservingSuffix(summary, normalizedSuffix);
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 Preserve recent-turn suffix when capping compaction summary

summaryWithPreservedTurns is built earlier in this function by appending ## Recent turns preserved verbatim to the end of the model summary, but this new cap path truncates the body with a prefix-preserving slice(0, budget) before adding the reserved suffix. In sessions where the summary exceeds the 16k budget, the tail is dropped first, so the “preserved recent turns” block can disappear even though it was explicitly extracted for continuity; this regression only appears on long summaries but directly weakens the compaction handoff.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: b9eace0c1a

ℹ️ 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 on lines +268 to +269
if (suffix.length >= maxChars) {
return suffix.slice(0, maxChars);
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 Preserve tail sections when reserved suffix exceeds cap

When suffix.length >= maxChars, this branch returns suffix.slice(0, maxChars), which keeps only the start of the reserved suffix and drops everything at the end. In this code path the suffix is ordered as preserved turns → tool failures → file ops → <workspace-critical-rules>, so long preserved-turn blocks can still cut off the workspace rules and diagnostics the safeguard is meant to guarantee. Fresh evidence is the new capCompactionSummaryPreservingSuffix branch itself: it reintroduces tail-loss even after moving critical sections into the suffix.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: 7832f8d114

ℹ️ 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 on lines +255 to +257
if (budget <= 0) {
return marker.slice(0, maxChars);
}
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 Keep body prefix when truncation marker cannot fit

When maxChars is smaller than SUMMARY_TRUNCATED_MARKER.length, this branch returns a sliced marker instead of any summary content. In the capCompactionSummaryPreservingSuffix path, this happens whenever the reserved suffix consumes almost the entire 16k budget, so the remaining body budget can be tiny and you end up dropping the body entirely even though some body characters could still fit. In long compactions this can erase top-level sections (decisions/constraints) and replace them with a partial marker fragment.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: bbc0f0088e

ℹ️ 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 on lines +1055 to +1057
summary = capCompactionSummaryPreservingSuffix(
lastSummaryWithoutPreservedTurns,
normalizedSuffix,
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 Preserve split-turn context in the capped summary suffix

This cap now truncates lastSummaryWithoutPreservedTurns with a prefix-preserving slice before appending the reserved suffix, which means the tail of the body is dropped first when over budget. In split-turn compactions, the **Turn Context (split turn):** block is appended at the end of summaryWithoutPreservedTurns, so long summaries can silently lose that split-turn context while keeping earlier body text; that regresses continuity specifically for preparation.isSplitTurn sessions. Consider reserving suffix budget for the split-turn block (or moving it into the preserved suffix set) so it is not the first content removed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: f571e6efef

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

fullReservedSuffix && !/^\s/.test(fullReservedSuffix)
? `\n\n${fullReservedSuffix}`
: fullReservedSuffix;
summary = capCompactionSummaryPreservingSuffix(lastHistorySummary, normalizedSuffix);
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 Honor last successful summary after retry failure

When a quality-guard retry fails after at least one successful attempt, the catch block sets summary = lastSuccessfulSummary and breaks, but the final assignment here unconditionally rebuilds summary from lastHistorySummary plus suffix. In split-turn sessions this is especially problematic because lastSplitTurnSection is reset before the failing prefix summarization call, so the returned summary can silently drop split-turn context and ignore the intended fallback-to-last-successful behavior under transient model/API errors.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: b0137553e2

ℹ️ 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 on lines +1068 to +1072
const bodyToCap = usedLastSuccessfulSummary ? summary : lastHistorySummary;
const suffixToUse = usedLastSuccessfulSummary
? (() => {
const diag = appendSummarySection(
appendSummarySection("", toolFailureSection),
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 Preserve retry-fallback tail context during summary capping

In the usedLastSuccessfulSummary branch, the cap is applied to the entire prior summary body while the reserved suffix only includes diagnostics/workspace data, so split-turn context and ## Recent turns preserved verbatim remain in the cap-truncated body tail. Because capCompactionSummary keeps the prefix and drops the end, long fallback summaries (for example after a retry error on attempt 2+) can still lose those continuity sections even though they were explicitly preserved earlier; this is fresh evidence in the new retry-fallback branch, not the normal path.

Useful? React with 👍 / 👎.

@jalehman jalehman force-pushed the fix/compaction-safeguard-summary-budget branch from 54088b5 to 05a7d77 Compare March 21, 2026 14:47
jalehman added a commit to Pandadadadazxf/openclaw that referenced this pull request Mar 21, 2026
Regeneration-Prompt: |
  Prepare PR openclaw#27727 for the unique compaction-safeguard budget fix only, leaving the overlapping post-compaction audit parser work out of scope. Fix the retry-fallback path in the compaction safeguard so when a quality-regeneration retry fails after one successful attempt, the final capped summary is rebuilt from the last successful history body plus the full reserved suffix, preserving split-turn context and preserved recent turns instead of only diagnostics and workspace rules. Replace the weak regression with one that forces capped fallback truncation and proves both suffix sections survive, then append the required changelog entry in Unreleased Fixes with (openclaw#27727) thanks @Pandadadadazxf.
jalehman added a commit to Pandadadadazxf/openclaw that referenced this pull request Mar 21, 2026
Regeneration-Prompt: |
  Prepare PR openclaw#27727 for the unique compaction-safeguard budget fix only, leaving the overlapping post-compaction audit parser work out of scope. Fix the retry-fallback path in the compaction safeguard so when a quality-regeneration retry fails after one successful attempt, the final capped summary is rebuilt from the last successful history body plus the full reserved suffix, preserving split-turn context and preserved recent turns instead of only diagnostics and workspace rules. Replace the weak regression with one that forces capped fallback truncation and proves both suffix sections survive, then append the required changelog entry in Unreleased Fixes with (openclaw#27727) thanks @Pandadadadazxf.
@jalehman jalehman force-pushed the fix/compaction-safeguard-summary-budget branch from 05a7d77 to 653c022 Compare March 21, 2026 14:52
Copy link
Copy Markdown

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

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: 653c022642

ℹ️ 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 +230 to +234
const readSection = formatBoundedFileList("read-files", readFiles, MAX_FILE_OPS_LIST_CHARS);
const modifiedSection = formatBoundedFileList(
"modified-files",
modifiedFiles,
MAX_FILE_OPS_LIST_CHARS,
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 Let one file-op list consume the full section budget

In read-only or edit-only compactions, formatFileOperations caps the populated list at MAX_FILE_OPS_LIST_CHARS (900) before the 2000-character section budget is applied. Because formatBoundedFileList already counts its tags inside that 900-character limit and sections.join("\n\n") adds at most four more characters, the outer capCompactionSummary(..., MAX_FILE_OPS_SECTION_CHARS) is unreachable here; a single non-empty list therefore drops roughly half of the available file-path budget even when the overall summary is still well under the cap.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: 909654af81

ℹ️ 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 +1087 to +1088
const bodyToCap = lastHistorySummary || summary;
summary = capCompactionSummaryPreservingSuffix(bodyToCap, normalizedSuffix ?? "");
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 Guard the summary fallback against suffix duplication

If summarizeInStages() comes back with an empty string while recent-turn preservation or split-turn context is active, lastHistorySummary stays falsy and this fallback uses summary as the body even though summary already includes lastSplitTurnSection / preservedTurnsSection from the loop. reservedSuffix is then appended a second time, so the final compaction summary duplicates the preserved-turn or split-turn blocks and can blow past the budget again. This is reachable because summarizeChunks() returns summary ?? DEFAULT_SUMMARY_FALLBACK in src/agents/compaction.ts, so a blank model response is preserved as "" instead of being normalized.

Useful? React with 👍 / 👎.

jalehman added a commit to Pandadadadazxf/openclaw that referenced this pull request Mar 21, 2026
Regeneration-Prompt: |
  Prepare PR openclaw#27727 for the unique compaction-safeguard budget fix only, leaving the overlapping post-compaction audit parser work out of scope. Fix the retry-fallback path in the compaction safeguard so when a quality-regeneration retry fails after one successful attempt, the final capped summary is rebuilt from the last successful history body plus the full reserved suffix, preserving split-turn context and preserved recent turns instead of only diagnostics and workspace rules. Replace the weak regression with one that forces capped fallback truncation and proves both suffix sections survive, then append the required changelog entry in Unreleased Fixes with (openclaw#27727) thanks @Pandadadadazxf.
jalehman added a commit to Pandadadadazxf/openclaw that referenced this pull request Mar 21, 2026
Regeneration-Prompt: |
  During PR openclaw#27727 prepare, rebasing onto current main exposed a pnpm check failure in extensions/telegram/src/setup-surface.test.ts because telegramSetupWizard.prepare is optional and the test accessed prepared.cfg without proving the result exists. Keep runtime behavior unchanged. Add the smallest test-side assertion/helper needed to narrow the optional prepare result before reading cfg, then rerun the full prepare gates on the refreshed prep branch.
@jalehman jalehman force-pushed the fix/compaction-safeguard-summary-budget branch from 909654a to 5777cb7 Compare March 21, 2026 16:20
@openclaw-barnacle openclaw-barnacle bot added the channel: telegram Channel integration: telegram label Mar 21, 2026
Pandadadadazxf and others added 14 commits March 21, 2026 09:20
Cap main history body before appending tool failures and file ops so
these high-signal diagnostics survive truncation. Truncation keeps the
prefix (slice(0, budget)), so sections appended at the end would be
dropped first; moving them into the reserved suffix preserves them.

Made-with: Cursor
appendSummarySection('', section) strips leading newlines via trimStart.
When body does not end with newline (e.g. buildStructuredFallbackSummary),
concatenation could merge content like '...## Exact identifiers## Tool Failures'.
Ensure reserved suffix has leading separator so headings/tags stay distinct.

Made-with: Cursor
Include preservedTurnsSection in the reserved suffix so it survives truncation.
Truncation keeps the prefix (slice(0, budget)), so the tail is dropped first;
the 'preserved recent turns' block was in the body and could disappear on long
summaries. Move it into the suffix with diagnostics and workspace rules.

Made-with: Cursor
When suffix.length >= maxChars, slice(0, maxChars) kept the head (preserved
turns) and dropped the tail (workspace rules, diagnostics). Use slice(-maxChars)
to preserve the critical tail instead.

Made-with: Cursor
When body budget is tiny (suffix consumes almost entire 16k), budget <= 0
and we returned marker.slice(0, maxChars)—a useless fragment. Prefer
summary.slice(0, maxChars) to retain at least Decisions/Constraints prefix.

Made-with: Cursor
The split-turn block is appended at the end of summaryWithoutPreservedTurns,
so truncation (prefix-preserving slice) drops it first. Move it into the
reserved suffix so preparation.isSplitTurn sessions retain turn context.

Made-with: Cursor
Regeneration-Prompt: |
  Prepare PR openclaw#27727 for the unique compaction-safeguard budget fix only, leaving the overlapping post-compaction audit parser work out of scope. Fix the retry-fallback path in the compaction safeguard so when a quality-regeneration retry fails after one successful attempt, the final capped summary is rebuilt from the last successful history body plus the full reserved suffix, preserving split-turn context and preserved recent turns instead of only diagnostics and workspace rules. Replace the weak regression with one that forces capped fallback truncation and proves both suffix sections survive, then append the required changelog entry in Unreleased Fixes with (openclaw#27727) thanks @Pandadadadazxf.
Regeneration-Prompt: |
  During PR openclaw#27727 prepare, rebasing onto current main exposed a pnpm check failure in extensions/telegram/src/setup-surface.test.ts because telegramSetupWizard.prepare is optional and the test accessed prepared.cfg without proving the result exists. Keep runtime behavior unchanged. Add the smallest test-side assertion/helper needed to narrow the optional prepare result before reading cfg, then rerun the full prepare gates on the refreshed prep branch.
@jalehman jalehman force-pushed the fix/compaction-safeguard-summary-budget branch from 5777cb7 to a7ab64e Compare March 21, 2026 16:21
@jalehman jalehman merged commit 2fe0efc into openclaw:main Mar 21, 2026
38 checks passed
Copy link
Copy Markdown

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

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: a7ab64e394

ℹ️ 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 +1087 to +1088
const bodyToCap = lastHistorySummary || summary;
summary = capCompactionSummaryPreservingSuffix(bodyToCap, normalizedSuffix ?? "");
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 Return the validated split-turn summary instead of rebuilding it

For split-turn compactions, summaryWithoutPreservedTurns is built with a \n\n---\n\n divider before **Turn Context (split turn):**, and that combined text is what auditSummaryQuality() checks. This new return path throws that string away and reconstructs the summary from lastHistorySummary plus lastSplitTurnSection, so every split-turn summary now loses the divider even when it is well under 16k. That folds the prefix context back into the trailing structured section instead of keeping it as a distinct handoff block, which weakens continuity for any preparation.isSplitTurn session.

Useful? React with 👍 / 👎.

mrosmarin added a commit to mrosmarin/openclaw that referenced this pull request Mar 21, 2026
* main: (516 commits)
  fix: use content hash for memory flush dedup instead of compactionCount (openclaw#30115) (openclaw#34222)
  fix(tts): add matrix to VOICE_BUBBLE_CHANNELS (openclaw#37080)
  feat(memory): pluggable system prompt section for memory plugins (openclaw#40126)
  fix: detect nvm services from installed command (openclaw#51146)
  fix: handle Linux nvm CA env before startup (openclaw#51146) (thanks @GodsBoy)
  refactor: route Telegram runtime through plugin sdk (openclaw#51772)
  refactor: route iMessage runtime through plugin sdk (openclaw#51770)
  refactor: route Slack runtime through plugin sdk (openclaw#51766)
  refactor(doctor): extract provider and shared config helpers (openclaw#51753)
  Fix Discord `/codex_resume` picker expiration (openclaw#51260)
  fix(ci): remove duplicate embedding default export
  fix(ci): restore embedding defaults and plugin boundaries
  fix: compaction safeguard summary budget (openclaw#27727)
  web UI: fix context notice using accumulated inputTokens instead of prompt snapshot (openclaw#51721)
  fix(status): skip cold-start status probes
  refactor(doctor): extract telegram provider warnings (openclaw#51704)
  fix(telegram): default fresh setups to mention-gated groups
  docs(changelog): note telegram doctor first-run guidance
  fix(doctor): add telegram first-run guidance
  fix(doctor): suppress telegram fresh-install group warning
  ...
JohnJAS pushed a commit to JohnJAS/openclaw that referenced this pull request Mar 22, 2026
Merged via squash.

Prepared head SHA: a7ab64e
Co-authored-by: Pandadadadazxf <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
pholpaphankorn pushed a commit to pholpaphankorn/openclaw that referenced this pull request Mar 22, 2026
Merged via squash.

Prepared head SHA: a7ab64e
Co-authored-by: Pandadadadazxf <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
frankekn pushed a commit to artwalker/openclaw that referenced this pull request Mar 23, 2026
Merged via squash.

Prepared head SHA: a7ab64e
Co-authored-by: Pandadadadazxf <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman
Interstellar-code pushed a commit to Interstellar-code/operator1 that referenced this pull request Mar 24, 2026
Merged via squash.

Prepared head SHA: a7ab64e
Co-authored-by: Pandadadadazxf <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

(cherry picked from commit 2fe0efc)
furaul pushed a commit to furaul/openclaw that referenced this pull request Mar 24, 2026
Merged via squash.

Prepared head SHA: a7ab64e
Co-authored-by: Pandadadadazxf <[email protected]>
Co-authored-by: jalehman <[email protected]>
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 channel: telegram Channel integration: telegram extensions: openai size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants