Bug type
Behavior bug (incorrect runtime state without crash)
Beta release blocker
No
Summary
Context-engine / LCM maintenance can leave deferred compaction debt stranded in at least two ways:
- A bootstrap/reconcile path can import missing tail messages, create deferred compaction debt, and then immediately block debt execution because the host runtime is still in foreground mode.
- A hot-cache path can record deferred compaction debt even after
rawTokensOutsideTail crosses the configured leaf threshold, but maintenance later skips compaction with reason=hot-cache-budget-headroom / deferred compaction still needed, leaving the debt in place.
These look related to maintenance scheduling and policy, but they may be two distinct bugs.
Expected behavior
- If bootstrap/reconcile imports messages and pushes
rawTokensOutsideTail past the leaf trigger, the runtime should schedule or run a valid background follow-up that is allowed to consume deferred compaction debt.
- If deferred compaction debt is recorded for a session, maintenance should either pay that debt down promptly or make it clear that policy intentionally superseded the debt.
- Crossing the leaf trigger should not leave a session in a repeated
still needed state without a subsequent successful compaction path.
Actual behavior
Case 1: bootstrap/reconcile creates debt that cannot execute
Observed on April 16, 2026 in a user-facing session:
- 08:38:12 EDT: deferred compaction worked normally
compactLeafAsync start
LCM compaction leaf pass (normal): 112071 -> 76263
maintain: deferred compaction completed ... reason=compacted
- 08:41:33 EDT: bootstrap slow-path reconcile imported missing tail messages
reconcileSessionTail ... missingTail=12 importedMessages=12
- then immediately:
maintain: deferred compaction debt pending ... but host runtimeContext.allowDeferredCompactionExecution is disabled
rawTokensOutsideTail=60243
- later
60887, 62169, 62438
maintain: deferred compaction skipped ... reason=deferred compaction still needed
I traced the current main code and found that background deferral only happens for reason === "turn", while allowDeferredCompactionExecution is only true when executionMode === "background":
src/agents/pi-embedded-runner/context-engine-maintenance.ts
const executionMode = params.executionMode ?? "foreground";
const shouldDefer = params.reason === "turn" && ... turnMaintenanceMode === "background";
allowDeferredCompactionExecution: params.executionMode === "background"
That appears to leave bootstrap/reconcile able to create compaction debt in foreground without scheduling the background follow-up needed to consume it.
Case 2: hot-cache policy leaves debt recorded but unpaid
Observed on April 16, 2026 in a background scheduled session:
- 10:01:44 EDT:
rawTokensOutsideTail=40253
threshold=40000
shouldCompact=false
reason=hot-cache-budget-headroom
deferred compaction debt recorded
- 10:01:45 EDT:
- background turn maintenance was queued
- maintenance then logged:
maintain: deferred compaction skipped ... reason=deferred compaction still needed
So this session crossed the configured leaf trigger, recorded debt, and still did not compact because policy/headroom logic won. That may be intentional, but from an operator perspective it looks like debt can remain sticky even when maintenance wakes up successfully.
Steps to reproduce
I do not yet have a synthetic minimized repro, but the observed sequences were:
Reconcile case
- Start a live session with LCM / context-engine maintenance enabled.
- Let the session compact normally at least once.
- Trigger a slow-path bootstrap/reconcile that imports missing session-tail messages.
- Observe
rawTokensOutsideTail jump above the leaf trigger.
- Observe that maintenance reports deferred compaction debt but also says
runtimeContext.allowDeferredCompactionExecution is disabled.
Hot-cache case
- Use a session with large history and hot cache state.
- Let
rawTokensOutsideTail approach and then cross the configured leaf trigger.
- Observe debt recorded.
- Let background turn maintenance queue and run.
- Observe maintenance still skip compaction because
hot-cache-budget-headroom / still needed wins.
OpenClaw version
Not yet confirmed from the affected instance. Observed on April 16, 2026 against a Linux npm-global install. The code path on main as of April 16, 2026 still matches the observed behavior.
Operating system
Linux
Install method
npm global / containerized runtime
Model
Multiple sessions; not isolated to one model. The operator-visible symptom is in context-engine / LCM maintenance.
Provider / routing chain
OpenClaw with lossless-claw
Logs and evidence
Representative log excerpts:
2026-04-16 08:38:12 EDT
[lcm] compactLeafAsync start ...
[lcm] LCM compaction leaf pass (normal): 112071 -> 76263 ...
[lcm] maintain: deferred compaction completed ... reason=compacted
2026-04-16 08:41:33 EDT
[lcm] reconcileSessionTail: slow path ... missingTail=12 importedMessages=12
[lcm] maintain: deferred compaction debt pending ... but host runtimeContext.allowDeferredCompactionExecution is disabled
[lcm] incremental compaction decision: ... rawTokensOutsideTail=60243 ... reason=hot-cache-budget-headroom
[lcm] maintain: deferred compaction skipped ... reason=deferred compaction still needed
2026-04-16 10:01:44 EDT
[lcm] incremental compaction decision: ... rawTokensOutsideTail=40253 threshold=40000 shouldCompact=false ... reason=hot-cache-budget-headroom
[lcm] deferred compaction debt recorded ...
2026-04-16 10:01:45 EDT
[context-engine] deferred turn maintenance queued ...
[lcm] maintain: deferred compaction skipped ... reason=deferred compaction still needed
Bug type
Behavior bug (incorrect runtime state without crash)
Beta release blocker
No
Summary
Context-engine / LCM maintenance can leave deferred compaction debt stranded in at least two ways:
rawTokensOutsideTailcrosses the configured leaf threshold, but maintenance later skips compaction withreason=hot-cache-budget-headroom/deferred compaction still needed, leaving the debt in place.These look related to maintenance scheduling and policy, but they may be two distinct bugs.
Expected behavior
rawTokensOutsideTailpast the leaf trigger, the runtime should schedule or run a valid background follow-up that is allowed to consume deferred compaction debt.still neededstate without a subsequent successful compaction path.Actual behavior
Case 1: bootstrap/reconcile creates debt that cannot execute
Observed on April 16, 2026 in a user-facing session:
compactLeafAsync startLCM compaction leaf pass (normal): 112071 -> 76263maintain: deferred compaction completed ... reason=compactedreconcileSessionTail ... missingTail=12 importedMessages=12maintain: deferred compaction debt pending ... but host runtimeContext.allowDeferredCompactionExecution is disabledrawTokensOutsideTail=6024360887,62169,62438maintain: deferred compaction skipped ... reason=deferred compaction still neededI traced the current
maincode and found that background deferral only happens forreason === "turn", whileallowDeferredCompactionExecutionis only true whenexecutionMode === "background":src/agents/pi-embedded-runner/context-engine-maintenance.tsconst executionMode = params.executionMode ?? "foreground";const shouldDefer = params.reason === "turn" && ... turnMaintenanceMode === "background";allowDeferredCompactionExecution: params.executionMode === "background"That appears to leave bootstrap/reconcile able to create compaction debt in foreground without scheduling the background follow-up needed to consume it.
Case 2: hot-cache policy leaves debt recorded but unpaid
Observed on April 16, 2026 in a background scheduled session:
rawTokensOutsideTail=40253threshold=40000shouldCompact=falsereason=hot-cache-budget-headroomdeferred compaction debt recordedmaintain: deferred compaction skipped ... reason=deferred compaction still neededSo this session crossed the configured leaf trigger, recorded debt, and still did not compact because policy/headroom logic won. That may be intentional, but from an operator perspective it looks like debt can remain sticky even when maintenance wakes up successfully.
Steps to reproduce
I do not yet have a synthetic minimized repro, but the observed sequences were:
Reconcile case
rawTokensOutsideTailjump above the leaf trigger.runtimeContext.allowDeferredCompactionExecution is disabled.Hot-cache case
rawTokensOutsideTailapproach and then cross the configured leaf trigger.hot-cache-budget-headroom/still neededwins.OpenClaw version
Not yet confirmed from the affected instance. Observed on April 16, 2026 against a Linux npm-global install. The code path on
mainas of April 16, 2026 still matches the observed behavior.Operating system
Linux
Install method
npm global / containerized runtime
Model
Multiple sessions; not isolated to one model. The operator-visible symptom is in context-engine / LCM maintenance.
Provider / routing chain
OpenClaw with
lossless-clawLogs and evidence
Representative log excerpts: