You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[pi-plugin] 0.49.0: agent_end after LKG publication still refuses the dispatch ("the run that owned the latest context pass has ended") #673
On @cortexkit/pi-magic-context0.49.0 (the release that closed #667), a user turn still aborts with:
Error: Magic Context could not safely prepare this turn; send your message again.
stage=provider dispatch (origin=agent_end; context stage=LKG/served publication) elapsed=21556ms
recovery=no managed result; refused
(the run that owned the latest context pass has ended; no managed result for this request)
Resubmitting the same message succeeds. Same host, same repo, omp 18.10.3, Linux.
#667 (fixed in 0.49.0) was the superseded path: a late agent_end from an earlier run ending the current pass, or a pass not current at the fence. This is the other guard, which #667 fix does not reach:
dist/index.jspi.on("before_provider_request"):
if(active.ended){refusalOrigin="agent_end";thrownewError("the run that owned the latest context pass has ended; no managed result for this request");}
The refused message carries context stage=LKG/served publication, i.e. the pass completed and published to LKG before the refusal — the pass was managed and current, then an agent_end (the run ending) set operation.ended = true; operation.ready = false in the agent_end handler between the LKG publication and the run dispatch.
Signature to separate the two: (origin=agent_end; context stage=LKG/served publication) — pass already published, still refused.
Verified in the installed 0.49.0 dist
refusalOrigin = "agent_end": exactly 1 occurrence, in before_provider_request.
refuse() sets stage to `provider dispatch (origin=${refusalOrigin}; ...)`after the active.ended throw, so the stage text comes from this exact branch.
recovery shows no managed result; refused, assigned only in the user-visible arm of refuse() (the !isCurrent() arm returns before assigning it) — so isCurrent() was true; the error reached the user, an agent_end was observed after the pass published.
Occurrences
elapsed=6958ms and elapsed=21556ms, distinct turns, both (origin=agent_end; context stage=LKG/served publication) and recovery=no managed result; refused.
No provider is dispatched on this path; the refusal happens before any upstream call. A subq/opencode-zen proxy is not involved — no upstream call happens here.
Suggested direction
Constraint to preserve (from magic-alfonso in #667): the fence must only let a provider request through if it is the current run's managed result. In this path the pass is managed and published; agent_end arrives after publication, before dispatch. The fence could treat operation.ended alongside an already-completed, LKG-published pass as "run ended after publish" and dispatch its managed result, instead of refusing. Second candidate: the agent_end handler should not set ended for a pass whose LKG slot was served (published and current), analogous to what #667 changed for the earlier-run case.
Repo: cortexkit/magic-context, packages/pi-plugin. Happy to attach the [magic-context][pi] OMP context counts session=... dispatch_fence=... lines plus the exact events if useful.
Thanks for the precise report. The signature you point out (origin=agent_end; context stage=LKG/served publication) is different from issue 667, and the analysis of which branch produced the refusal helps a lot.
I'm reproducing it on a real Oh My Pi 18.9.x host to see exactly which event ends the run and which request arrives after it. The fix depends on that: the dispatch check has to keep sending only the current run's prepared request, so it can't simply let the published result through without knowing which request it's answering.
The dispatch_fence=... count lines and the event sequence around one refusal would be useful, if you can share them.
Fixed in 0.49.1. The dispatch check no longer refuses a prepared turn because of an agent_end that arrives after the last-good request was published. It now matches the outgoing request against the prepared one by structure (message count, roles, tool call ids and the last message), which survives Oh My Pi's own later edits such as secret obfuscation, image compaction and date reminders, so it no longer depends on event timing. Verified on real Oh My Pi 18.10.3 and 18.10.4, including headless chat-completions mode. Update with npx @cortexkit/magic-context@latest setup or by bumping the plugin version, then restart the host.
Activity
magic-alfonso commentedon Oct 13, 2026
Thanks for the precise report. The signature you point out (
origin=agent_end; context stage=LKG/served publication) is different from issue 667, and the analysis of which branch produced the refusal helps a lot.I'm reproducing it on a real Oh My Pi 18.9.x host to see exactly which event ends the run and which request arrives after it. The fix depends on that: the dispatch check has to keep sending only the current run's prepared request, so it can't simply let the published result through without knowing which request it's answering.
The
dispatch_fence=...count lines and the event sequence around one refusal would be useful, if you can share them.magic-alfonso commentedon Oct 14, 2026
Fixed in 0.49.1. The dispatch check no longer refuses a prepared turn because of an
agent_endthat arrives after the last-good request was published. It now matches the outgoing request against the prepared one by structure (message count, roles, tool call ids and the last message), which survives Oh My Pi's own later edits such as secret obfuscation, image compaction and date reminders, so it no longer depends on event timing. Verified on real Oh My Pi 18.10.3 and 18.10.4, including headless chat-completions mode. Update withnpx @cortexkit/magic-context@latest setupor by bumping the plugin version, then restart the host.