Summary
TaskPlane 0.30.4 crashes Pi 0.83 during normal Runtime V2 batch startup when the asynchronous engine-worker IPC handler uses a captured ExtensionContext after Pi has marked it stale.
The engine subprocess may continue briefly, but the supervising Pi process exits. This is a TaskPlane/Pi infrastructure failure before normal lane supervision, not a worker-model failure.
Environment
- TaskPlane: 0.30.4
- Pi:
@earendil-works/pi-coding-agent 0.83.0
- Node.js: 24.18.0
- OS: Windows
- Orchestration: repo mode, one supervised lane
Reproduction
From a configured repository with one ready packet:
pi --approve --no-session --thinking high -p "/orch taskplane-tasks/TP-XXX/PROMPT.md"
The same exception reproduced through a persistent direct-Node Pi invocation, so this is not specific to --no-session print mode.
Observed behavior
TaskPlane begins batch planning, then Pi exits:
Error: This extension ctx is stale after session replacement or reload.
at ExtensionRunner.assertActive (.../pi-coding-agent/dist/core/extensions/runner.js:360:19)
at get ui (.../pi-coding-agent/dist/core/extensions/runner.js:462:24)
at ChildProcess.<anonymous> (.../taskplane/extensions/taskplane/extension.ts:1288:13)
The failing 0.30.4 code is the asynchronous startBatchInWorker() IPC handler:
child.on("message", (msg: WorkerToMainMessage) => {
switch (msg.type) {
case "notify":
ctx.ui.notify(msg.msg, msg.level);
updateWidget();
break;
}
});
updateOrchWidget() also retains orchWidgetCtx from session_start and calls ctx.ui.setWidget(...), which can fail under the same stale-context condition.
Root cause
Long-lived worker-process callbacks capture command/session extension contexts and perform UI-only side effects after Pi session replacement/reload. Pi 0.83 rejects those stale handles. The guard error is uncaught in TaskPlane's child event callback, so it terminates the supervising Pi process.
A package-wide search in 0.30.4 found no withSession implementation in TaskPlane for these callbacks.
Expected behavior
- Engine state and lane execution must not crash because an old UI context is unavailable.
- Post-replacement work should use Pi's supported
withSession/fresh-context mechanism where possible.
- If no active UI context exists, notification/widget refresh should be skipped without suppressing non-stale errors or engine failures.
- Dashboard/runtime persistence and review/verification behavior must remain unchanged.
Bounded compatibility validation
A hash-pinned local compatibility patch guarded only asynchronous UI operations:
- Treat the exact Pi stale-context error as an unavailable UI sink.
- Skip only
ctx.ui.notify(...) / ctx.ui.setWidget(...) for that exact error.
- Rethrow every other error.
- Do not alter engine state, review policy, verification, retries, or failure propagation.
Installed source SHA-256:
- Original
extension.ts: 091c111440a26a9e466b6838e7bc2945c8d8420c7df8104e5f294be6279ab2fd
- Locally patched:
edf04f685a69025e0d20ae9259c6f9bc0f9a19f1d3a30a0e90f3f6edb8755da1
After that patch, the identical /orch path passed the former crash point, created exactly one isolated lane, started its worker, and successfully exercised the configured code-navigation tools during preflight.
The validation environment imposed a hard 60-second command bound, so the exact batch processes were terminated at that bound and no claim of task completion is made. This proves the stale-context crash was removed, not that a full task completed.
Relationship to #597
Related to #597, but distinct:
The same lifecycle rule should be applied consistently across both background paths.
Acceptance criteria
/orch <packet> does not terminate Pi when worker IPC arrives after session replacement/reload.
- UI notifications/widgets use a fresh supported context or safely no-op only for Pi's exact stale-context error.
- Non-stale notification errors still surface.
- Runtime batch/lane state continues to persist and remains observable from the dashboard.
- Supervisor, reviewer, merger, strict verification, and failure handling retain their existing authority.
- A regression test covers an IPC
notify and widget refresh after context invalidation.
Summary
TaskPlane 0.30.4 crashes Pi 0.83 during normal Runtime V2 batch startup when the asynchronous engine-worker IPC handler uses a captured
ExtensionContextafter Pi has marked it stale.The engine subprocess may continue briefly, but the supervising Pi process exits. This is a TaskPlane/Pi infrastructure failure before normal lane supervision, not a worker-model failure.
Environment
@earendil-works/pi-coding-agent0.83.0Reproduction
From a configured repository with one ready packet:
The same exception reproduced through a persistent direct-Node Pi invocation, so this is not specific to
--no-sessionprint mode.Observed behavior
TaskPlane begins batch planning, then Pi exits:
The failing 0.30.4 code is the asynchronous
startBatchInWorker()IPC handler:updateOrchWidget()also retainsorchWidgetCtxfromsession_startand callsctx.ui.setWidget(...), which can fail under the same stale-context condition.Root cause
Long-lived worker-process callbacks capture command/session extension contexts and perform UI-only side effects after Pi session replacement/reload. Pi 0.83 rejects those stale handles. The guard error is uncaught in TaskPlane's child event callback, so it terminates the supervising Pi process.
A package-wide search in 0.30.4 found no
withSessionimplementation in TaskPlane for these callbacks.Expected behavior
withSession/fresh-context mechanism where possible.Bounded compatibility validation
A hash-pinned local compatibility patch guarded only asynchronous UI operations:
ctx.ui.notify(...)/ctx.ui.setWidget(...)for that exact error.Installed source SHA-256:
extension.ts:091c111440a26a9e466b6838e7bc2945c8d8420c7df8104e5f294be6279ab2fdedf04f685a69025e0d20ae9259c6f9bc0f9a19f1d3a30a0e90f3f6edb8755da1After that patch, the identical
/orchpath passed the former crash point, created exactly one isolated lane, started its worker, and successfully exercised the configured code-navigation tools during preflight.The validation environment imposed a hard 60-second command bound, so the exact batch processes were terminated at that bound and no claim of task completion is made. This proves the stale-context crash was removed, not that a full task completed.
Relationship to #597
Related to #597, but distinct:
ExtensionAPI(pi.sendMessage) on TaskPlane 0.30.1 / Pi 0.77.ExtensionContext(ctx.ui.notify/ widget context) on TaskPlane 0.30.4 / Pi 0.83.The same lifecycle rule should be applied consistently across both background paths.
Acceptance criteria
/orch <packet>does not terminate Pi when worker IPC arrives after session replacement/reload.notifyand widget refresh after context invalidation.