Skip to content

runtime: pi TUI Enter (CR) keypress does not submit under perry — raw-stdin/Kitty keypress decode divergence (real pi interactive blocker) #6728

Description

@proggeramlug

The ACTUAL blocker for pi's interactive TUI under perry (supersedes the async-generator theory — see below). Pi renders and accepts typed text, but pressing Enter (CR 0x0d) does not submit the message under perry, where node (same bundle) submits and renders the response.

Evidence (fixed-binary A/B, decisive)

Using /tmp/pi-fixed = pi compiled WITH the async-generator await-suspension fix (#6727), interactive PTY repro, bogus API key (a valid request 401s — that's the expected visible result):

Enter byte perry result node result
CR 0x0d "hello" stuck in input, no submit, no "Working…", no 401 (19547 B) submit → "Working…" → "Error: 401 authentication_error" (33338 B)
LF 0x0a input processed differently (25792 B) but still no 401
CRLF 0x0d0a 25792 B, no 401

So no Enter variant submits+responds under perry; node does with CR. The async-generator fix (#6727) does NOT change this (perry CR result byte-identical with and without it) — confirming the keypress→submit path, not async-generator event forwarding, is what blocks pi. (#6727 fixes a real, separate async-generator await-on-pending-Promise deadlock and is worth landing on its own; it would be the NEXT blocker once submit works.)

Mechanism (where to look)

Pi reads raw stdin itself: process.stdin.setRawMode(true) (bundle ~232037) + process.stdin.on("data", stdinDataHandler) (~232095), and runs a custom keypress parser that also negotiates the Kitty keyboard protocol (queryAndEnableKittyProtocol, KITTY_KEYBOARD_PROTOCOL_QUERY). Enter/CR decoding flows through that raw-byte parse (charCodeAt, string/Buffer handling, CR/LF/CRLF logic at ~50346, Kitty sequence parsing). A perry divergence in one of: (a) how stdin.on("data") delivers the chunk under raw mode (Buffer vs string, encoding, chunk boundaries), (b) charCodeAt/string comparison in the parser, (c) the Kitty-protocol negotiation buffer handling, or (d) setRawMode/termios not matching node (CR vs LF delivery). The CR-vs-LF asymmetry points at the parser receiving/classifying the Enter byte differently than under node.

Diagnosis approach

Instrument node-vs-perry inside stdinDataHandler / the keypress parser in the UNMINIFIED bundle (pi-target/dist/pi-bundle.mjs): log the exact bytes/keyname the parser receives and classifies for a sent CR under each runtime; find the first divergence. Repro harness: scratchpad/pty_drive.py (PTY_SCRIPT scripted input); fd pre-placed HOME; cwd=pi-target/dist; binary /tmp/pi-fixed (or recompile). Node oracle: node pi-bundle.mjs. Reduce to a minimal fixture (raw-mode stdin + the same parse shape) and fix the perry divergence node-identically.

Blocks pi interactive chat entirely. Peer walls on the pi path: #6704 (render, merged), #6727 (async-gen, worth landing), OAuth/login (source-tweak workaround).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions