fix: compaction safeguard summary budget#27727
Conversation
Greptile SummaryAdds bounded formatting for file operation lists and a final compaction summary length cap to prevent oversized summaries from consuming excessive context budget. Key Changes:
Implementation Notes:
Confidence Score: 4/5
Last reviewed commit: afc741b |
| const overflowLine = remaining > 0 ? `...and ${remaining} more\n` : ""; | ||
| const projected = usedChars + line.length + overflowLine.length; | ||
| if (projected > maxChars) { | ||
| if (remaining >= 0) { |
There was a problem hiding this comment.
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.7fc5c07 to
d10502d
Compare
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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.
b12c361 to
a7e23da
Compare
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
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.
|
Hi @jalehman,
Please re-review and feel free to ask questions and request changes. |
There was a problem hiding this comment.
💡 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".
| const diagnosticSuffix = appendSummarySection( | ||
| appendSummarySection("", toolFailureSection), | ||
| fileOpsSummary, |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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".
| if (suffix.length >= maxChars) { | ||
| return suffix.slice(0, maxChars); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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".
| if (budget <= 0) { | ||
| return marker.slice(0, maxChars); | ||
| } |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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".
| summary = capCompactionSummaryPreservingSuffix( | ||
| lastSummaryWithoutPreservedTurns, | ||
| normalizedSuffix, |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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".
| const bodyToCap = usedLastSuccessfulSummary ? summary : lastHistorySummary; | ||
| const suffixToUse = usedLastSuccessfulSummary | ||
| ? (() => { | ||
| const diag = appendSummarySection( | ||
| appendSummarySection("", toolFailureSection), |
There was a problem hiding this comment.
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 👍 / 👎.
54088b5 to
05a7d77
Compare
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: | 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.
05a7d77 to
653c022
Compare
There was a problem hiding this comment.
💡 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".
| const readSection = formatBoundedFileList("read-files", readFiles, MAX_FILE_OPS_LIST_CHARS); | ||
| const modifiedSection = formatBoundedFileList( | ||
| "modified-files", | ||
| modifiedFiles, | ||
| MAX_FILE_OPS_LIST_CHARS, |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
💡 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".
| const bodyToCap = lastHistorySummary || summary; | ||
| summary = capCompactionSummaryPreservingSuffix(bodyToCap, normalizedSuffix ?? ""); |
There was a problem hiding this comment.
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 👍 / 👎.
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.
909654a to
5777cb7
Compare
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.
5777cb7 to
a7ab64e
Compare
There was a problem hiding this comment.
💡 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".
| const bodyToCap = lastHistorySummary || summary; | ||
| summary = capCompactionSummaryPreservingSuffix(bodyToCap, normalizedSuffix ?? ""); |
There was a problem hiding this comment.
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 👍 / 👎.
* 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 ...
Merged via squash. Prepared head SHA: a7ab64e Co-authored-by: Pandadadadazxf <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
Merged via squash. Prepared head SHA: a7ab64e Co-authored-by: Pandadadadazxf <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
Merged via squash. Prepared head SHA: a7ab64e Co-authored-by: Pandadadadazxf <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
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)
Merged via squash. Prepared head SHA: a7ab64e Co-authored-by: Pandadadadazxf <[email protected]> Co-authored-by: jalehman <[email protected]> Reviewed-by: @jalehman
Summary
Describe the problem and fix in 2–5 bullets:
compaction-safeguardcan append large file operation lists (read-files/modified-files) and other metadata to the compaction summary, which can make the summary itself too large....and N more) and a final compaction summary length cap with a truncation marker; added tests for both behaviors.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
...and N more.Security Impact (required)
No)No)No)No)No)Yes, explain risk + mitigation:Repro + Verification
Environment
.tools/node-v22.22.0-darwin-arm64)Steps
src/agents/pi-extensions/compaction-safeguard.tsto cap file-op summary size and final compaction summary length.src/agents/pi-extensions/compaction-safeguard.test.tscovering file-op truncation and summary truncation marker.PATH="$PWD/.tools/node-v22.22.0-darwin-arm64/bin:$PATH" npm exec vitest run src/agents/pi-extensions/compaction-safeguard.test.ts.Expected
...and N morewhen truncated.Actual
compaction-safeguardtest file passes (24 tests).Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
src/agents/pi-extensions/compaction-safeguard.test.tslocally after changes; confirmed new tests pass and existing tests remain green.Compatibility / Migration
Yes)No)No)Failure Recovery (if this breaks)
afc741b(or revert the PR commit) to restore previous compaction summary behavior.src/agents/pi-extensions/compaction-safeguard.ts,src/agents/pi-extensions/compaction-safeguard.test.tsRisks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write
None....and N more, and core compaction logic is unchanged.