Skip to content

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

Description

@RoarkJH

Preflight Checklist

  • I have searched existing requests and this feature hasn't been requested yet
  • 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., VS Code extension: Stop-hook-blocked draft and its rewrite both render as duplicate full responses #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.
  4. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions