Summary
OpenCode + DeepSeek can complete a turn without leaving a usable final assistant answer visible to the user. We observed two related shapes:
- Phenotype A: stdout only emits
step_start, with no text and no error, while OpenCode SQLite still contains the assistant text for the same sessionID + messageID.
- Phenotype B: stdout emits a short prelude
text, then tool_use, then ends without a final text after the tool.
The root cause is a completion-state gap in the adapter: tool completion or earlier text is treated as enough evidence that the turn is complete, but the adapter does not verify that final assistant text exists after the last tool.
Expected
- If OpenCode persisted assistant text for a silent
step_start turn, Clowder should recover that text by sessionID + messageID.
- If the last meaningful event is a tool and no later text exists, Clowder should recover via a no-tool finalizer in the same OpenCode session.
- The whole OpenCode turn must not be rerun, because that can duplicate tool side effects.
Proposed fix
- Track the latest
step_start message reference plus text/tool event order in OpenCodeAgentService.
- Recover phenotype A from OpenCode SQLite read-only state.
- Recover phenotype B with one dedicated
cat-cafe-no-tool-finalizer run, with all tool permissions denied, and replace the incomplete prelude.
- Keep existing diagnostics for true silent completions when recovery finds no text.
- Keep pure tool-only completions from being mislabeled as silent failures.
Validation target
The corresponding branch adds regression coverage for both shapes and keeps the existing AC-G3 behavior intact.
Summary
OpenCode + DeepSeek can complete a turn without leaving a usable final assistant answer visible to the user. We observed two related shapes:
step_start, with notextand noerror, while OpenCode SQLite still contains the assistant text for the samesessionID + messageID.text, thentool_use, then ends without a finaltextafter the tool.The root cause is a completion-state gap in the adapter: tool completion or earlier text is treated as enough evidence that the turn is complete, but the adapter does not verify that final assistant text exists after the last tool.
Expected
step_startturn, Clowder should recover that text bysessionID + messageID.Proposed fix
step_startmessage reference plus text/tool event order inOpenCodeAgentService.cat-cafe-no-tool-finalizerrun, with all tool permissions denied, and replace the incomplete prelude.Validation target
The corresponding branch adds regression coverage for both shapes and keeps the existing AC-G3 behavior intact.