[FEATURE] Emit semantic marks for assistant-message boundaries and Stop-hook verdicts, so superseded drafts can be collapsed

Status Open
Maintainer reply None cached
Activity 1 comment · opened Jul 29, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Stop hooks are the documented enforcement layer: a hook that returns {"decision":"block"} to enforce output standards (e.g., validating the final message and
demanding a rewrite) makes rewrite loops normal operation, not an edge case. But every draft streams to the terminal before the Stop hook can evaluate it —
the hook needs the complete message, so printing always precedes the verdict. Result: each rejected draft prints in full, followed by the rewrite in full. With
a retry cap, the user reads near-identical walls of text multiple times per gated turn.

No external fix is possible: terminal scrollback cannot be selectively retracted, and the byte stream carries no mark a wrapper or terminal could key on — no
message-boundary sequence, no verdict sequence. The inside has the signal (the Stop event); the outside has silence.

Proposed Solution

Claude Code already serializes session state as semantic escape sequences — OSC 133 prompt zones (#32635, completed), OSC 9;4 progress state, OSC 21337 tab
status. Extend that shipped pattern with two small marks:

  1. an assistant-message-end mark, and
  2. a verdict mark when Stop-hook evaluation completes: accepted, or superseded (blocked; rewrite follows).

That single protocol addition lets every surface solve the duplication its own way: terminals with rich integration can dim or fold marked-superseded regions,
transcript views can collapse them, and external tooling can distinguish drafts from final answers. #78260 asks for the VS Code UI treatment of this same
event; marks at the protocol layer would give that issue — and every other surface — a common foundation.

Alternative Solutions

  • External PTY wrapper filtering stdout: impossible today — no message-boundary or verdict marks exist in the stream to key on, and scrollback can't be

retroactively edited.

  • Buffering output until the Stop verdict: rejected as an ask — it would sacrifice live streaming; this request adds information to the stream rather than

delaying it.

  • Per-surface UI fixes (e.g., #78260 for VS Code): works surface-by-surface, but protocol-level marks would give all surfaces one foundation.
  • Current workaround: lowering the hook's retry cap and loosening its thresholds — reduces how often duplicates appear, but every enforcement fire still

prints at least one superseded draft.

Priority

Medium - Would be very helpful

Feature Category

Interactive mode (TUI)

Use Case Example

  1. Register a Stop hook that validates the final assistant message against an output standard and returns {"decision":"block", "reason":"..."} on violation.
  2. Ask any question whose answer violates the standard.
  3. The draft streams to the terminal in full → the hook blocks it → the rewrite streams in full. The transcript now shows two (or with retries, three)

near-identical long responses back to back.

  1. With message-end + verdict marks emitted, my terminal or a transcript tool could fold the superseded drafts automatically, showing only the accepted answer

with the drafts collapsed behind a disclosure.

Additional Context

Related: #78260 (same event, VS Code rendering), #32635 (OSC 133 semantic prompt marks — precedent, shipped), #74408 (same request genre: OSC marks on cwd
change). The OSC 9;4 progress implementation already gates on terminal capability detection and a config flag — the same pattern (capability-detected, opt-in)
would suit these marks.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗