Before submitting
Area
apps/server
Summary
OpenCode prompt-admission recovery can mark a turn completed before generation starts. It finds the submitted user message, reads an empty session-status map twice, and treats that as completion. A later native busy event cannot restore the running state because T3 has already cleared the active turn ID.
The agent continues generating and executing tools while the sidebar no longer shows "Working". This occurred on a remote Linux/WSL environment and is confirmed by that server's provider log and read-only database inspection.
Steps to reproduce
This is timing-dependent. The observed ordering was:
- Submit a prompt to an OpenCode thread. The observed case was an existing conversation whose provider session started again for this prompt.
- OpenCode persists the user message before reporting the session as busy.
- T3's prompt-admission recovery finds that message and receives
{} from session.status on two checks before generation begins.
- T3 emits
turn.completed with raw type session.status.recovered and clears the active turn.
- OpenCode emits native
session.status: busy and continues the response, but T3 leaves the session ready with no active turn.
A deterministic adapter regression test could hold the native busy event, make session.message return the submitted user message, return {} from the status requests that trigger admission recovery, then release busy and tool events. The turn should remain active until actual completion evidence arrives. This test has not yet been implemented or run.
Expected behavior
Finding the user message proves admission, not completion. A status map that omits the session during startup must not be enough to complete the turn before generation starts. The sidebar should show "Working" throughout the agent's work.
Actual behavior and captured timeline
All times below are UTC on 2026-09-21, from the affected environment's provider and orchestration logs:
| Time |
Event |
| 13:07:42.044 |
T3 emits turn.started. |
| 13:07:43.118 |
T3 emits turn.completed with raw payload {"type":"session.status.recovered","status":{}}. |
| 13:07:43.493 |
T3 observes the native user message.updated event. |
| 13:07:43.526 |
T3 observes native session.status with {"type":"busy"}, about 408 ms after it declared completion. |
| 13:07:43.527 |
T3 observes the native assistant message.updated event. |
| Through 13:11:18.219 |
T3 continues recording tool activity, now with turnId: null. |
The read model agrees with the premature completion:
projection_thread_sessions.status = ready
projection_thread_sessions.active_turn_id = null
projection_thread_sessions.updated_at = 2026-09-21T13:07:43.118Z
projection_turns.state = completed
projection_turns.completed_at = 2026-09-21T13:07:43.118Z
T3 also captured the turn checkpoint at that premature completion boundary. This is a server turn-lifecycle problem, not merely a missing sidebar indicator.
Source findings
In apps/server/src/provider/Layers/OpenCodeAdapter.ts, schedulePromptAdmissionRecovery:
- Sets
messageObserved when session.message returns the submitted user message.
- Treats an absent session in a valid status map as idle.
- Increments
idleStatusConfirmations when isIdle && messageObserved.
- Calls
completeOpenCodeTurn after two confirmations, without requiring evidence that generation started or an assistant response completed.
The emitted session.status.recovered payload in the live log identifies this exact completion branch. completeOpenCodeTurn clears context.activeTurnId. The native session.status handler then ignores a busy event when turnId is undefined, which explains why the subsequent busy event did not restore "Working".
These branches are at lines 1375-1399, 1433-1469, 1135-1150, and 2589-2593 in the inspected local checkout, commit ffb46df83a02289d2a3a6630929e2bd03eadebe7. The current checkout still contains the problematic recovery logic.
Impact
The sidebar looks idle while an agent is working. Subsequent tool activity loses its turn association, and checkpoint capture occurs before the work finishes.
Version or commit
- OpenCode session version from the native provider event:
1.18.31.
- Provider/model: OpenCode with
github-copilot/gpt-6-astra.
- Source inspected: local checkout at
ffb46df83a02289d2a3a6630929e2bd03eadebe7.
- The exact affected remote T3 binary version was not captured. The diagnosis uses its actual emitted provider events and persisted state, rather than assuming that it matches the source checkout.
Environment
Windows desktop client connected to a remote Linux/WSL T3 environment. The incorrect state is present in the remote server's database, independently of the client connection.
Related issues
Investigation
Investigated with GPT-6 Astra through OpenCode in T3 Code. Private repository names, thread identifiers, host addresses, and conversation content have been omitted. No live state was modified and neither environment was restarted.
Before submitting
Area
apps/server
Summary
OpenCode prompt-admission recovery can mark a turn completed before generation starts. It finds the submitted user message, reads an empty session-status map twice, and treats that as completion. A later native
busyevent cannot restore the running state because T3 has already cleared the active turn ID.The agent continues generating and executing tools while the sidebar no longer shows "Working". This occurred on a remote Linux/WSL environment and is confirmed by that server's provider log and read-only database inspection.
Steps to reproduce
This is timing-dependent. The observed ordering was:
{}fromsession.statuson two checks before generation begins.turn.completedwith raw typesession.status.recoveredand clears the active turn.session.status: busyand continues the response, but T3 leaves the session ready with no active turn.A deterministic adapter regression test could hold the native busy event, make
session.messagereturn the submitted user message, return{}from the status requests that trigger admission recovery, then release busy and tool events. The turn should remain active until actual completion evidence arrives. This test has not yet been implemented or run.Expected behavior
Finding the user message proves admission, not completion. A status map that omits the session during startup must not be enough to complete the turn before generation starts. The sidebar should show "Working" throughout the agent's work.
Actual behavior and captured timeline
All times below are UTC on 2026-09-21, from the affected environment's provider and orchestration logs:
turn.started.turn.completedwith raw payload{"type":"session.status.recovered","status":{}}.message.updatedevent.session.statuswith{"type":"busy"}, about 408 ms after it declared completion.message.updatedevent.turnId: null.The read model agrees with the premature completion:
T3 also captured the turn checkpoint at that premature completion boundary. This is a server turn-lifecycle problem, not merely a missing sidebar indicator.
Source findings
In
apps/server/src/provider/Layers/OpenCodeAdapter.ts,schedulePromptAdmissionRecovery:messageObservedwhensession.messagereturns the submitted user message.idleStatusConfirmationswhenisIdle && messageObserved.completeOpenCodeTurnafter two confirmations, without requiring evidence that generation started or an assistant response completed.The emitted
session.status.recoveredpayload in the live log identifies this exact completion branch.completeOpenCodeTurnclearscontext.activeTurnId. The nativesession.statushandler then ignores a busy event whenturnIdis undefined, which explains why the subsequent busy event did not restore "Working".These branches are at lines 1375-1399, 1433-1469, 1135-1150, and 2589-2593 in the inspected local checkout, commit
ffb46df83a02289d2a3a6630929e2bd03eadebe7. The current checkout still contains the problematic recovery logic.Impact
The sidebar looks idle while an agent is working. Subsequent tool activity loses its turn association, and checkpoint capture occurs before the work finishes.
Version or commit
1.18.31.github-copilot/gpt-6-astra.ffb46df83a02289d2a3a6630929e2bd03eadebe7.Environment
Windows desktop client connected to a remote Linux/WSL T3 environment. The incorrect state is present in the remote server's database, independently of the client connection.
Related issues
Investigation
Investigated with GPT-6 Astra through OpenCode in T3 Code. Private repository names, thread identifiers, host addresses, and conversation content have been omitted. No live state was modified and neither environment was restarted.