Summary
A Question Node conversation can be displayed with only the user's prompt while the node is marked done. No assistant answer or error is shown, so the empty conversation looks like a storage/read failure.
Observed behavior
For the affected thread:
space.json persisted the Question Node with status: "done" and viewed: true.
.history/chat_v2/<threadId>.events.jsonl contained exactly one record: turn_start with the submitted prompt.
- There were no
text_delta, done, error, or end events.
- No matching
<threadId>.turns.jsonl folded-turn file existed.
- Reopening the Question Node rendered the user bubble but no assistant response or interruption/error status.
The answer is not hidden elsewhere in storage; it was never persisted.
Expected behavior
If an agent SSE stream ends before a terminal event:
- Do not mark the Question Node as successfully completed.
- Surface the conversation as interrupted or errored, ideally with a retry affordance.
- Preserve enough state to distinguish an incomplete persisted turn from a completed empty response.
Suspected cause
Two existing recovery behaviors combine to produce the misleading state:
-
apps/web/src/api/agent.ts treats a terminal-less EOF from streamMessage as successful completion:
if (!terminal) callbacks.onComplete();
The reconnect path already treats the same condition as an error (Agent stream ended before a terminal event).
-
apps/web/src/store/canvasStore/load/reconcileQuestionStatus.ts promotes any authored Question Node with a thread ID and non-terminal status to done, without checking whether the persisted conversation has a completed turn.
The Agenetes history materializer correctly identifies the uncovered Tier-1 tail as isIncomplete: true, but the UI history projection currently renders its user request without an interrupted/error status.
These behaviors predate the backend-agnostic storage-read work and are present on upstream/main at 127b820e.
Suggested regression coverage
- A
streamMessage response that reaches EOF after turn_start but before done/end/error must call onError, not onComplete.
- Reloading a Question Node whose Chat-V2 log contains only
turn_start must not promote it to successful done.
- An incomplete materialized turn should display an interrupted/error state rather than a blank assistant area.
— posted by OpenAI Codex (via the issue-tracker skill)
Summary
A Question Node conversation can be displayed with only the user's prompt while the node is marked
done. No assistant answer or error is shown, so the empty conversation looks like a storage/read failure.Observed behavior
For the affected thread:
space.jsonpersisted the Question Node withstatus: "done"andviewed: true..history/chat_v2/<threadId>.events.jsonlcontained exactly one record:turn_startwith the submitted prompt.text_delta,done,error, orendevents.<threadId>.turns.jsonlfolded-turn file existed.The answer is not hidden elsewhere in storage; it was never persisted.
Expected behavior
If an agent SSE stream ends before a terminal event:
Suspected cause
Two existing recovery behaviors combine to produce the misleading state:
apps/web/src/api/agent.tstreats a terminal-less EOF fromstreamMessageas successful completion:The reconnect path already treats the same condition as an error (
Agent stream ended before a terminal event).apps/web/src/store/canvasStore/load/reconcileQuestionStatus.tspromotes any authored Question Node with a thread ID and non-terminal status todone, without checking whether the persisted conversation has a completed turn.The Agenetes history materializer correctly identifies the uncovered Tier-1 tail as
isIncomplete: true, but the UI history projection currently renders its user request without an interrupted/error status.These behaviors predate the backend-agnostic storage-read work and are present on
upstream/mainat127b820e.Suggested regression coverage
streamMessageresponse that reaches EOF afterturn_startbut beforedone/end/errormust callonError, notonComplete.turn_startmust not promote it to successfuldone.— posted by OpenAI Codex (via the issue-tracker skill)