Two coupled changes, both about debug mode (which @vue-tui/testing's render()
is built on):
1. Debug stdout is now byte-identical to Ink v7.0.4: the debug commit branch
re-emits the FULL accumulated <Static> history every frame (not just the
per-commit delta), writes every frame unconditionally (no FrameWriter
dedup), and drops the synthetic trailing "\n" — matching Ink's
`fullStaticOutput + output` (ink.tsx:558, output.ts has no trailing newline).
2. The test frame-capture no longer reverse-engineers frames out of stdout.
The runtime exposes an internal, per-app frame sink (INTERNAL_FRAME_SINK,
a Symbol from @vue-tui/runtime/internal; the public MountOptions type is
untouched). The debug branch hands each committed frame to the sink,
mirroring the stdout writes. @vue-tui/testing's render() builds
frames[]/lastFrame() from the sink instead of sniffing stdout.
Why: an isTTY:true test stdout (which render() needs for the interactive resize
listener) lets isTTY-gated escapes — bracket-paste \x1b[?2004h/l from usePaste —
land in a stdout-sniffing capture and pollute frames[]. Capturing at the source
makes frames[] provably content-only regardless of which composables a test
mounts, while public debug stdout stays byte-exact to Ink (escapes still written,
not debug-gated). The test surface stays cleanly tiered (Ink's model): render()
= content; createApp+debug:false = in-process control sequences; PTY = real
terminal. '' floor, verbatim SGR/OSC8, frames[] multi-frame/static semantics,
and terminal.resize() are all preserved.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>