--- id: "bug-1792" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "controller" severity: "unknown" timestamp: "2026-09-09T12:40:00.000Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/controller/testsuite/test_test_cli.c"] tags: ["libedit", "readline", "tab-completion", "pty", "ECHO", "test-harness", "xce-test-cli-ux", "task-2.3", "test_test_cli.c", "silent-input-mode"] related: [] legacy: true --- # bug-1792: test_test_cli.c tab-completion test (xce-test-cli-ux task 2.3): Tab keystroke produced zero effect… ## Description test_test_cli.c tab-completion test (xce-test-cli-ux task 2.3): Tab keystroke produced zero effect (no bell, no redraw, no completion) when driven through the existing clitest_spawn() pty harness -- 'wo' + Tab + Enter submitted literally "wo" ("wo: No such command for xce test."), never "worker". ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause clitest_spawn() (task 1.7) deliberately clears kernel ECHO on the pty slave BEFORE forking, documented at the time as affecting ONLY the line discipline's own re-echo of injected bytes, 'not readline()/libedit's own prompt/redraw output, which stays intact'. An A/B probe (standalone C program linked against this project's exact pinned libedit, driven both ways via a raw openpty()+fork() harness, controlling for controlling-terminal presence too) showed that assumption does not hold for THIS libedit build: when the slave's ECHO bit already reads off at the moment readline() is invoked, libedit treats the session as a silent/non-interactive (password-style) input mode and suppresses ALL of its own live editing feedback, not just kernel echo -- Tab is accepted as a no-op, the line is only ever consumed whole on Enter, and no bell/redraw/candidate-list ever appears. With kernel ECHO left at its default-on state (libedit reconfigures the tty itself once its own readline() call takes over, taking on echo/redraw duties without any raw kernel double-echo reaching the captured stream), the identical Tab sequence produced the expected bell + in-place completion + ambiguous-match candidate listing. Controlling-terminal setup (setsid()/TIOCSCTTY) was also probed and made no observable difference -- ECHO state was the sole deciding factor. ## Fix Refactored clitest_spawn() into clitest_spawn_ex(sess, path, argv, disable_echo) with the ECHO-clearing block made conditional on the new parameter; clitest_spawn() itself is preserved as a one-line wrapper calling clitest_spawn_ex(..., true), so every existing (output-only) caller is unaffected. The new xce-test-cli-ux task 2.3 tab-completion test calls clitest_spawn_ex(..., false) directly to keep kernel ECHO on, which restored full interactive completion behavior end-to-end (single-match auto-complete, ambiguous-match double-Tab listing, all verified via the real xce_test binary). Documented the finding in both clitest_spawn_ex()'s own comment and the file's top-of-file API summary so future tasks in this spec (3.5, 4.1-4.4) that add more interactive-feedback-dependent tests to this same file know to use clitest_spawn_ex(..., false) rather than rediscovering this the hard way. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._