From 225fdbf50501783f5089658749723cd527c3fc0e Mon Sep 17 00:00:00 2001 From: "Claudia[bot]" <4437565+Claudia[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 05:06:43 +0200 Subject: [PATCH] docs: align the cron, teammate-pane and TUI comments with the paste - cron resolvePrompt(): give the reason the rest of the cron docs give (the submit check cannot recognise a multi-line paste; in paste mode the newlines reach the CLI as keys) instead of the old one about writeViaMux fusing lines. - sendInputToPane(): it types with send-keys -l and strips line breaks, so it no longer uses "the same approach as sendInput()". - TUI client: newlines become spaces (the docstring said stripped), and the test name no longer cites "multi-line breaks Ink". Co-Authored-By: Claude Opus 5.5 (1M context) --- src/cron/cron-service.ts | 10 +++++----- src/tmux-manager.ts | 4 +++- src/tui/tui-client.ts | 6 +++--- test/tui/tui-client.test.ts | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/cron/cron-service.ts b/src/cron/cron-service.ts index 7b0a6599..b1d33cd6 100644 --- a/src/cron/cron-service.ts +++ b/src/cron/cron-service.ts @@ -536,11 +536,11 @@ export class CronService { } /** - * Resolves the prompt text and enforces the single-line constraint: prompt - * delivery rides writeViaMux/PTY writes where a newline is Enter, so a - * multi-line prompt would be silently corrupted (typed mode fuses lines, - * paste mode submits the first line and dribbles the rest in as separate - * messages). Rather than mangle an unattended agent's instructions, fail the + * Resolves the prompt text and enforces the single-line constraint: a job + * fires unattended, and the submit check that re-presses an ignored Enter + * cannot recognise a multi-line paste in the composer (typed mode), so a + * stranded prompt would go unnoticed; in paste mode the newlines reach the + * CLI as keys. Rather than risk an unattended agent's instructions, fail the * run with a clear error. A prompt FILE may end with trailing newline(s) * (every editor writes one) — those are stripped before the check. */ diff --git a/src/tmux-manager.ts b/src/tmux-manager.ts index 8364cbeb..53cd3c89 100644 --- a/src/tmux-manager.ts +++ b/src/tmux-manager.ts @@ -4019,7 +4019,9 @@ export class TmuxManager extends EventEmitter implements TerminalMultiplexer { /** * Send input to a specific pane within a tmux session. - * Uses the same literal text approach as sendInput() but targets a specific pane. + * Types the text literally with `send-keys -l`, line breaks stripped, then Enter + * when the input carried a `\r`. Unlike sendInput(), it neither pastes nor keeps + * the line breaks of multi-line text. */ sendInputToPane(muxName: string, paneTarget: string, input: string): boolean { if (IS_TEST_MODE) return true; diff --git a/src/tui/tui-client.ts b/src/tui/tui-client.ts index a78bf453..c4f035af 100644 --- a/src/tui/tui-client.ts +++ b/src/tui/tui-client.ts @@ -704,9 +704,9 @@ export class TuiClient { * * Two hard rules from CLAUDE.md, both enforced here so no caller can get them * wrong: the payload must END with `\r` or the server never issues Enter and - * the text sits unsubmitted, and embedded newlines are stripped rather than - * sent (the server would paste them as one block, which its submit check - * cannot reliably recognise in the composer). + * the text sits unsubmitted, and embedded newlines become spaces rather than + * being sent (the server would paste them as one block, which its submit + * check cannot reliably recognise in the composer). * The `clientId`/`seq` pair makes delivery exactly-once, so a retry after a * dropped connection cannot type the prompt twice. */ diff --git a/test/tui/tui-client.test.ts b/test/tui/tui-client.test.ts index 59ab9844..8b78fdb8 100644 --- a/test/tui/tui-client.test.ts +++ b/test/tui/tui-client.test.ts @@ -327,7 +327,7 @@ describe('TuiClient.sendInput', () => { expect(JSON.parse(recorded[0].body)).toMatchObject({ input: 'hello world\r', useMux: true }); }); - it('collapses embedded newlines into spaces (multi-line breaks Ink)', async () => { + it('collapses embedded newlines into spaces (a multi-line paste cannot be confirmed as submitted)', async () => { await client().sendInput('abc', 'echo A\necho B\r\nline three '); expect(JSON.parse(recorded[0].body).input).toBe('echo A echo B line three\r'); });