Restoring a pi-goal-x session in T3 deadlocks on confirmation, then exposes premature goal execution#30926

opened6d agobyWwsulais

Summary

I encountered two failures when I restored a Pi session with a paused pi-goal-x goal in T3 Code:

  1. T3 queued my confirmation response behind the initialization effect that needed it, so Pi timed out.
  2. After I applied a local fix for response delivery, pi-goal-x resumed native work before T3 attached an owned turn. T3's unsolicited-work guard correctly stopped Pi.

I am reporting two distinct stages of the same restoration scenario. I am not asking T3 to disable the guard or automatically approve extension dialogs.

Environment

  • Pi 1.3.0 with pi-goal-x 0.32.3.
  • Local T3 build based on public commit 171f8d880f28, with additional native Pi workflow-projection changes—not an unmodified release.

Investigation and limits

  • I also reproduced Stage A in an isolated in-memory SQLite fixture using T3's real outbox/worker code.
  • Stage B occurred only after the local correction for Stage A. This does not establish that an unchanged build reaches Stage B through the deadlocked path.

I reproduced these failures with pi-goal-x, not @narumitw/pi-goal. I have since switched extensions, but that change does not prove that T3's general startup/admission boundary is correct.

Reproduction scenario

  1. Install pi-goal-x and create a focused, paused goal whose session-restoration hook asks whether to resume it.
  2. Reopen that native Pi session through a T3 thread and start a turn.
  3. Accept pi-goal-x's startup resume confirmation.
  4. Check whether T3 delivers the response and attaches turn ownership before pi-goal-x resumes work.

I have not attached a self-contained public end-to-end repro yet. I based the findings below on the focused outbox fixture and correlated runtime events. I omitted private session contents and raw RPC logs.

Stage A: T3 blocks the confirmation response behind initialization

provider-turn.start remains running while native session initialization waits for pi-goal-x's confirmation. T3 persists my response as another effect for the same thread, but its ordinary per-thread ordering places that response behind the running start effect:

text
1provider-turn.start -> waits for pi-goal-x startup confirmation
2runtime-request.respond -> waits behind provider-turn.start

switch_session repeatedly reached its 60-second timeout. T3 later reported Pi RPC terminate failed: pi process was stopped, but that shutdown error did not cause the initial failure. Several concurrent initializations can also occupy all ordinary workers while they wait for responses.

I tested a narrowly reserved response lane locally. It made the outbox fixture responsive while retaining same-thread response serialization, rollback barriers, and request/session validation. I include this experiment as evidence, not as a requirement to use that particular implementation.

Stage B: pi-goal-x resumes work before T3 attaches turn ownership

After the local fix delivered my confirmation response, pi-goal-x resumed native work during session restoration. I correlated these events relative to successful response delivery:

text
1+149 ms T3: Pi started agent work outside an active T3 turn.
2 The session was stopped to prevent invisible tool execution.
3+150 ms pi-goal-x recorded an active goal checkpoint with a dispatch identifier.
4+170 ms The native assistant ended with an error and no text.
5+171 ms T3 recorded the run's startedAt.

T3's guard behaved correctly: it stopped native continuation that reached the boundary before T3 attached the owned turn. T3 should admit that work only after it establishes ownership and the intended model and permissions. Later process-stopped/stream errors can obscure the primary diagnostic.

Expected behavior

  • T3 delivers live confirmation responses while initialization waits for them, without auto-approval or weakened ordering and rollback rules.
  • T3 holds work that an approved startup response triggers until it can admit that work under an owned turn with the intended model and permissions. Otherwise, it defers the work in a recoverable state.
  • T3 preserves unsolicited-work protection. Buffering output after execution begins does not provide sufficient admission control.
  • T3 preserves the primary lifecycle/admission error instead of replacing it with a secondary RPC shutdown error.

I also encountered safely refused goal activation when helper tools were inactive. I did not observe an RPC crash in that case, and I am not conflating it with these pi-goal-x restoration failures.

  • #24187 concerns Pi extension background-work lifetime; this report concerns startup confirmation delivery and restoration-time admission.
  • Closed issue #12467 describes invalidated extension contexts after switch_session. I observed response-ordering deadlock and outside-turn execution here, not stale-context exceptions.

Note

🤖 GPT 6.1 Sol responding on behalf of StiensWout

The maintainer closed our independent #33332 as a duplicate and is retaining #30996, which implements the startup-answer ordering exception and reserved response worker. Our PR retains additional ordering and worker-saturation regression coverage. Please verify Stage A startup confirmation on a build containing the retained fix. Stage B native restoration/admission remains outside our fix and lacks a stock-main native reproduction, so this issue should stay open if premature goal execution remains.