Skip to content

Claude paste confirmation misses CJK prompts that wrap (hard-cut rule counts UTF-16, not cells) #1292

Open

Description

@Juliusolsson05

src/shared/claude/pasteConfirm.ts:176 detects a mid-word hard wrap with previous.length >= width - 1. translateToString returns one UTF-16 unit per 2-cell CJK glyph, so a full CJK row is about half the width in length. The wrap is then joined with a space, and the 24-character tail needle misses. The result is a 5 s absorption timeout, a rollback, and "not sent", for roughly half of multi-row CJK prompts. Mixed rows ending in a long URL or path fail the same way. The width 20-140 fixture test uses Latin text only. Fix: measure cell width (wcwidth), not string length. Severity P2 (related to closed #1118).

Found by the Stage 3 C1 hunt; lines are origin/main d525d45 and pinned submodules. Findings: temp/quality-loop/hunt-c1.md.

🤖 Generated with Claude Code

Activity

  1. Juliusolsson05 commented on Sep 25, 2026

    @Juliusolsson05
    OwnerAuthor

    Status after #1310 (merged via batch #1318, 2026-09-25).

    Shipped: a wrap is judged a hard cut only when the row is full (width − 1 cells). Widths are measured per grapheme cluster and always rounded down when uncertain; flags count 2, and text-presentation pictographs and zero-width spaces count as they render. Wrapped CJK prompts now confirm at every pane width whose rows fill completely, and nothing confirms before the paste lands.

    Still open: a multi-row prompt of only wide characters can still miss at odd composer widths (43 of 121 widths for the test prompt, pinned in the tests). That costs a 5 s timeout and rollback, never an early confirmation. Fixing it needs a signal stronger than row text, such as xterm's isWrapped flag.

  2. Juliusolsson05 commented on Sep 27, 2026

    @Juliusolsson05
    OwnerAuthor

    Triage (W1, 2026-09-26): the remaining case needs evidence and a design call before any code.

    • No real recording exists. fix(claude): paste confirmation joins full-row CJK hard wraps (refs #1292) #1310's CJK composer frames were synthesised from the recorded Latin frame (testing/fixtures/image-absorption). How Claude's Ink actually lays out an all-wide-character prompt at an odd composer width has never been captured.
    • xterm's isWrapped is not the stronger signal. Ink draws each row with its own line break (wrap-text.ts, hard: true) instead of relying on terminal autowrap, so a wrapped Ink row is not flagged isWrapped.
    • The only other signal is the payload itself. At a row that is one cell short, we could decide hard cut or soft wrap by what the payload has at that spot. That is close to the optional-whitespace join that steering q34 rejected as an early-Enter risk. It needs a decision, and a recorded odd-width CJK frame to test against.

    Needed: a raw PTY recording of a Claude composer holding a multi-row, all-CJK prompt at a few odd composer widths (for example 41, 63 and 81 columns), plus a decision on whether a payload-guided join is acceptable. Until then the residual costs a 5 s timeout and rollback, never an early Enter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclass:C1-prompt-deliveryPrompt delivery inferred from the terminal screenneeds-evidenceNeeds a recording/real use to settleprovider:claudeAffects Claude Code integrationsev:P2Real bug with a workaroundtype:bugSomething works wrong

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions