Why: The composed reply copied the registered artifact id and file size out of the tool summary.
Evidence: go test ./internal/runtime/ -run 'TestComposeUserPromptOmitsArtifactIDs|TestComposeReplyDropsInternalRefs'
Impact: Those tokens are removed from the compose input and from the reply before it is shown.
Refs: feature/final-reply-compose
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: The first live run wrote its deliberation, including a think block and the quality score, as the reply the user sees.
Evidence: go test ./internal/runtime/ -run TestCompose
Impact: Think blocks are stripped before the reply is stored or shown. The compose prompt forbids paths, scores, and step-by-step reasoning.
Refs: feature/final-reply-compose
Co-authored-by: Cursor <cursoragent@cursor.com>
Why: End-of-turn checks were injected as user messages, so the model answered the checker instead of the user, and the last draft was treated as the reply.
Evidence: go test ./internal/runtime/ ./internal/prompts/ ./internal/settings/ ./internal/ctxasm/
Impact: Rejections are system reminders. A main-model compose step writes the user-facing reply when tools were used. Deliverable cards stay after that reply.
Refs: feature/final-reply-compose
Co-authored-by: Cursor <cursoragent@cursor.com>