Skip to content

fix(openclaw): retain from plugin copies OpenClaw never started - #5517

Merged
nicoloboschi merged 2 commits into
mainfrom
fix/openclaw-retain-unstarted-copy
Oct 12, 2026
Merged

nicoloboschi merged 2 commits into
mainfrom
fix/openclaw-retain-unstarted-copy

Conversation

@nicoloboschi

Copy link
Copy Markdown
Collaborator

Closes #4828, #4721, #4537.

Bug: OpenClaw re-evaluates the plugin module for every plugin registry it loads, but calls service.start() only on the first. On 2026.9.x the agent_end hook runs in a later copy whose serviceAbortController is null, so runRetain returned at its lifecycle guard without logging anything. Recall kept working through its pre-start lifetime, which hid the loss.

Fix

Tests: retain-registry-reload.test.ts loads two separate module copies, starts only the first, and drives agent_end through the second. It checks the retain is sent, a failed retain is queued, and a stopped copy stays silent. The first two fail on main.

Verified on real OpenClaw 2026.9.6 (local Hindsight API, 2 turns each with a unique code word):

plugin where agent_end ran code words saved
0.13.0 (npm) copy without service.start 0 / 2, nothing logged
this branch copy without service.start (started=false, from temporary probe logs) 2 / 2

On OpenClaw 2026.10.2 agent_end is dispatched to the started copy, so retain already worked there. Recall still runs in an unstarted copy on 10.2, so the shared lifecycle keeps both paths consistent.

OpenClaw re-evaluates the plugin module for each plugin registry it loads
but only calls service.start() on the first. On 2026.9.x the agent_end hook
runs in a later copy, where serviceAbortController is null, so runRetain
returned at its lifecycle guard with no log line. Recall kept working
through its pre-start lifetime, which hid the loss.

- Recall and retain now share one lifecycle snapshot (captureHookLifecycle):
  the started service's, or the pre-start one in a never-started copy.
  An explicit stop() still turns hooks off.
- lazyReinit opens the retain queue in a never-started copy, so a failed
  retain is replayed instead of dropped.

Verified on OpenClaw 2026.9.6: before, retains never landed; after, agent_end
runs in an unstarted copy and every turn is retained.

Closes #4828
Closes #4721
Closes #4537
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openclaw plugin: auto-retain silently does nothing after OpenClaw reloads the plugin registry (recall keeps working)

1 participant