githubnext/ace2Public

Ace: a collaborative coding environment on the team's own machines

Preserve literal newlines when inserting text into web composers

IA

Found while validating #67 against Ace's actual WKWebView composer, under #8 / #65.

`desktop_insert` turned a newline in its text into an Enter/submit action. The first line became a real message in the isolated validation channel; the rest began entering a new draft before the native receiver check stopped the call with an uncertain outcome. Resolved by #67, merged as `8fb8ccf`; the original reproduction is preserved below.

### Reproduction and evidence

- Candidate: #67 at `d04c8c489441a8781cad28c0b674a7589f0c4feb`, signed development app, embedded Peekaboo 4.8.0. Real local host/channel and WKWebView, no mocked input. - After independent Accessibility inspection and explicit field focus (the separate availability/focus limitations are recorded in #64/#70), take a fresh native observation of an initially empty `Message` AXTextArea. - Call `desktop_insert` with `Ace 🧑🏽‍💻 café\nalpha duplicate omega\nbeta duplicate gamma\nFinish 東京`. - Native result: `unknown`, `window_targeted_events`, `may_have_dispatched`, at least 23 emitted input units. The error reports that the Accessibility text receiver no longer matches the exact target and requires a fresh observation. - Fresh native observation shows a posted message containing `Ace 🧑🏽‍💻 café` and a remaining draft of `alpha duplic`. The text-area frame is still 808×45 at (426,779); an auto-resize explanation is not established. - Evidence on the validation host: `/tmp/ace-actions-validation-xaLuQq/keyboard-webview-TnvO1M/keyboard-attempt-p4VBE1/` and the fresh post-failure observation in `keyboard-webview-QJVHFD/`. Input was not replayed and channel history was preserved.

### Required behavior

Text insertion must preserve literal Unicode and newlines without silently invoking the application's Enter/submit behavior. Explicit key presses remain separate. Determine the correct literal-text path for WKWebView/editable controls and its relationship to the GUI-owned paste work in #72/#75. Keep exact target/focus authority, clipboard preservation where applicable, and truthful partial/unknown outcomes; weakening the receiver check or repeating a partially delivered request is not a fix.

Validate the actual Ace composer: inserting multiline text leaves one draft with the intended contents and adds no message; contextual selection and insertion preserve surrounding text. Retain the real AppKit, hosted routing/replay, changed-focus refusal, Stop, and restart guarantees. A constant-size AppKit field alone does not cover this behavior.

### Resolution — merged #67

The final signed head `eff5e49` replaces character-event insertion with one GUI-owned plain-text paste. Newlines remain text instead of acquiring the editor’s Enter/submit semantics. The existing native lane, clipboard gate, snapshot lease, and exact receiver validation remain in force; uncertain delivery is not retried or reported as completed.

Final dogfooding also exposed ProseMirror’s default plain-text parser turning single newlines into separate paragraphs, which made the actual Accessibility value differ from the intended text. Ace now parses plain-text line breaks as `hard_break` nodes and preserves them during plain-text copying. Rich HTML and code-block paste retain their existing behavior. Native exact-text verification was not weakened.

On the signed final build, a contextual replacement of the second repeated match in Ace’s actual composer passed with Unicode/emoji, a literal newline, exact surrounding text and UTF-16 caret, observed consumption, restored clipboard, and released ownership. Live observation and independent durable replay confirmed every chat’s messages were unchanged; no text was submitted. Evidence on the validation host: `/tmp/ace-literal-composer.bTz4ep/validation-ready/result.json`.

Real pi/Anthropic completed-insertion and Stop-during-pending-paste cases also passed. Restarting the isolated channel worker retained exact tool results/images and provider usage without repeating input. Stop preserved the partial-input warning, and the original pending paste arrived once afterward. Evidence: `/tmp/ace-literal-channel.5gwa0r/completed/validation-completed/result.json` and `/tmp/ace-literal-channel.5gwa0r/stop/validation-stop/result.json`.

This closes the actual-composer newline/submission defect. Broader hosted validation remains in #65, and the remaining clipboard ownership failure/recovery matrix stays open in #78. Public clipboard tools remain #75. All disposable fixture apps are closed, and final cleanup preserved the current clipboard generation.

  1. iamnbutlerreferenced this in [Meta] Complete native computer use in Ace #8last month on GitHub

  2. iamnbutlerreferenced this in Add literal desktop insertion with reserved clipboard ownership #67last month on GitHub

  3. iamnbutlerreferenced this in Explain native inspection failure when the desktop or target window becomes unavailable #64last month on GitHub

  4. iamnbutlerreferenced this in Verify unsent composer drafts survive a signed desktop quit and relaunch #77last month on GitHub

  5. iamnbutlerreferenced this in Keep clipboard ownership while a native paste is unresolved #78last month on GitHub

  6. iamnbutlerreferenced this in Report actual application activity and visibility in desktop inventory #79last month on GitHub

  7. iamnbutlerreferenced this in Add native text selection and keyboard shortcuts #81last month on GitHub

  8. iamnbutlerreferenced this in Validate native text insertion on hosted channels and under interruption #65last month on GitHub

  9. IA
    Author

    The current plain-text paste path prevented submission in Ace's real composer: one contextual replacement preserved the surrounding draft, and read-only watches plus an independent replay confirmed every chat's messages were unchanged.

    The native result correctly remained `unknown`/`retained_unverified`/`reserved`: the intended single newline became a paragraph separator in the composer. Both `AXValue` and a separate signed, read-only `AXStringForRange` probe returned two newlines (100 UTF-16 units), while the intended draft was 99 units. This rules out treating a different AX text reader or newline normalization as proof of the exact edit.

    Source inspection found ProseMirror's default plain-text clipboard parser splits newline runs into paragraph nodes. #67 will include a small composer correction that preserves plain-text line breaks as the existing `hard_break` nodes. Rich HTML paste and code-block handling keep their existing paths. Native exact-text verification and clipboard ownership remain unchanged. Fresh actual-composer, delayed ownership, real-model completion/replay, and Stop checks remain before merge.

    Evidence: `/tmp/ace-literal-composer.EEotCj/validation-activated/`, `/tmp/ace-literal-composer-post-observation.json`, and `/tmp/ace-literal-ax-window-probe-result.json`. The native request drained and its exact receiver process exited before test cleanup; newer clipboard contents were preserved when the explicit recovery check found an ownership mismatch.

  10. iamnbutlerclosedlast month on GitHub