Skip to content

fix: prevent reflection loop with global cross-instance re-entrant guard#369

Open
ggzeng wants to merge 1 commit intoCortexReach:masterfrom
ggzeng:fix/reflection-loop-global-guard
Open

fix: prevent reflection loop with global cross-instance re-entrant guard#369
ggzeng wants to merge 1 commit intoCortexReach:masterfrom
ggzeng:fix/reflection-loop-global-guard

Conversation

@ggzeng
Copy link
Copy Markdown

@ggzeng ggzeng commented Mar 26, 2026

Problem

Each plugin instance maintained its own re-entrant guard Map. When the runtime re-loaded the plugin during embedded agent turns (e.g. command:new inside a reflection), a new instance would bypass the guard, causing infinite reflection loops.

Solution

Introduce two global guards using Symbol.for + globalThis so all plugin instances share the same state:

  1. Global re-entrant lock — prevents concurrent reflection calls for the same sessionKey across all plugin instances.
  2. Serial loop guard — imposes a 2-minute cooldown per sessionKey between consecutive reflection runs, preventing gateway-level re-triggering chains (session_end → new session → command:new).

Changes

  • Only index.ts modified — no dependency changes.
  • Guards are initialized lazily via Symbol.for keys, safe for multiple loads.
  • Cooldown is configurable via SERIAL_GUARD_COOLDOWN_MS constant (currently 120s).

Previously each plugin instance maintained its own re-entrant guard Map.
When the runtime re-loaded the plugin during embedded agent turns (e.g.
command:new inside a reflection), a new instance would bypass the guard,
causing infinite reflection loops.

This change introduces two global guards using Symbol.for + globalThis
so ALL plugin instances share the same state:

1. **Global re-entrant lock** — prevents concurrent reflection calls for
   the same sessionKey across all plugin instances.
2. **Serial loop guard** — imposes a 2-minute cooldown per sessionKey
   between consecutive reflection runs, preventing gateway-level
   re-triggering chains (session_end → new session → command:new).
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.

1 participant