Repository navigation
Conversation
Heartbeat-only transcripts fire before_compaction then skip. Observers currently hang because after_compaction never arrives.
…mmarize Queued compaction already notifies observers on a successful no-op. The direct path returned after before_compaction without the matching after event, so plugins synthesized a fake N to N skip while work was still pending.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Codex review: blocked before merge. Reviewed October 6, 2026, 1:32 AM ET / 05:32 UTC (Revision 8). ClawSweeper reviewWhat this changesThe branch completes plugin observers when native compaction skips an empty conversation and gives the bundled notifier a distinct “Nothing to compact” message. Merge readiness⛔ Blocked before merge - 3 items remain This PR remains useful: current main still omits completion for native no-conversation skips. Earlier notifier findings are resolved and real behavior proof is sufficient; native observer compatibility needs an explicit decision, and the branch has merge conflicts. Priority: P2 Review scores
Verification
How this fits togetherCompaction reduces session history before further model work. Its lifecycle hooks notify plugins and feed optional chat notices, including when an attempt finishes without rewriting history. flowchart TD
A[Session transcript] --> B[Native compaction]
B --> C[Before observers]
C --> D{Conversation to summarize?}
D -->|No| E[Skip completion]
D -->|Yes| F[History compaction]
E --> G[After observers and chat notice]
F --> G
Decision needed
Why: This changes callback behavior for third-party native observers; the merged acceptance expressly covered engine-owned attempts. Before merge
Agent review detailsSecurityNone. PR surfaceSource +90, Tests +202. Total +292 across 6 files. View PR surface stats
Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Complete native skip lifecycles without mutation-only side effects, retain the truthful internal skip notice, and explicitly accept and document the native observer contract. Do we have a high-confidence way to reproduce the issue? Yes, from source: a heartbeat-only transcript reaches the native no-conversation return after the before hook, with no matching completion on current main. This review did not execute target code. Is this the best way to solve the issue? Yes, technically: the patch uses the existing hook owner, preserves public payload fields and mutation-only side effects, and distinguishes skips from zero-reduction rewrites. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against d8612ec864bb. LabelsLabel changes: No label changes. Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (7 earlier review cycles)
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Native no-op after_compaction already completes observers with compactedCount: 0. The bundled notifier still claimed context was compacted, so chat surfaces lied about a skip.
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Provider-side rewrites can finish with compactedCount 0 without skipping. Key the bundled notice on compactionOutcome: skipped so a real rewrite still reports Context compacted.
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Extract the no-conversation skip completion helper so compaction-session-execution stays within the line-cap ratchet, and remove an unused vitest import.
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Related: #81925
What Problem This Solves
Fixes plugin compaction observers timing out on a native no-op when the transcript has no real conversation messages. Also makes the bundled compaction-notifier notice truthful for that skip without mislabeling successful zero message-count rewrites.
User Impact
Heartbeat-only or tool-only sessions that skip summarization now emit
after_compactionafterbefore_compaction, so voice and plugin hooks receive a settled lifecycle instead of waiting indefinitely for a fake N→N skip. Chat surfaces that enablecompaction-notifiersay “Nothing to compact” only for an explicit native skip (compactionOutcome: "skipped"), not whenevercompactedCountis 0.Why This Change Was Made
Queued compaction already notifies observers on a successful
compacted: falseresult (#118094). The direct session path still returned afterbefore_compactionwithout the matching after event.ClawSweeper follow-up:
compactedCount === 0is not a skip signal. Provider-side compaction can rewrite an assistant entry without shorteningsession.messages, so the notice must key off an unambiguous internal outcome instead of zero reduction.Real Behavior Proof
61be59c97d68955a2f7dd1208c2ec11ffb9a3fb5compactEmbeddedAgentSessionDirectnatively skips summarization, fires exactly one installedafter_compactionobserver, leaves conversation message history and compaction accounting unchanged, and surfaces the bundled notifier text “Nothing to compact” (not “Context compacted”).compactEmbeddedAgentSessionDirect→executePreparedCompactionSessionnative no-conversation early return; realSessionManager+ SQLite/session store transcript; local pluginafter_compactionobserver; bundledcompaction-notifierviasession:compact:after./mnt/adata/opt/openclaw-worktrees/81925-native-noop-after-compaction, branchfix/81925-native-noop-after-compaction, isolatedcreateOpenClawTestStatehome/state (no live Gateway). Synthetic openai apiKey used only for model prep; no provider network call on the skip path.agent:main:proof-noop-session.<b>HEARTBEAT_OK</b>through realSessionManager.open(...).appendMessage(...)./tmp/oc-150920-proof/observer-plugin/index.cjs) that appends one JSON line onafter_compaction.compaction-notifieronsession:compact:before/session:compact:after.compactEmbeddedAgentSessionDirectwith accounting recorder attached./tmp/oc-150920-proof/result-final.json,/tmp/oc-150920-proof/plugin-after.jsonl,/tmp/oc-150920-proof/notices.json,/tmp/oc-150920-proof/run-proof-head.log(local; not committed).after_compaction; conversation messages unchanged; accounting empty; notifier said “Nothing to compact”. Session prep may append incidental non-message transcript events (thinking_level_change, model-snapshotcustom); those are outside the heartbeat conversation history under test.openclaw sessions compactRPC; Control UI / chat screenshot delivery of the notice; unfixed baseline replay on this host in the same script run.Supporting unit coverage (not a substitute for the above):
compaction-session-execution.noop-hooks.test.ts,compaction-notifier/handler.test.ts.Separate Review Blockers
viimport removed; native skip extracted socompaction-session-execution.tsstays under the line-cap ratchet).src/agents/embedded-agent-runner/run/payloads.test.tsmissingfinalMessageStart— not in this PR’s diff; shared baseline onmain, not fake-greened here.Evidence
Native skip path passes
compactionOutcome: "skipped"into the internalsession:compact:afterevent while preserving plugincompactedCount: 0. Successful after-hooks leavecompactionOutcomeunset.ClawSweeper
compactionOutcome: "skipped".Sources
after_compactionnot emitted whenresult.compacted:false; validation: single-quote delimiter trips tool-caller retries #81925 Bug 1 remaining native skip path22f369c7cae59c768b0d8a17b6aff96fea68c11e(needs real behavior proof)