# Cthulhu review keys in Wine Status: approved, implemented, verified and installed on 2026-10-11. Independent review fixes and matching-binary desktop checks completed; MUSHclient listening and physical braille acceptance remain live checks. ## Intended outcome The user wants the existing Cthulhu review keys to work in Wine, especially MUSHclient running in `~/.local/bard`. Keep the current desktop keyboard bindings. Review must read and navigate independently of application focus, caret, selection, and keyboard input. The user confirmed this scope on 2026-10-11. Support current/previous/next line, word, and character; current-word spelling and phonetics; current-character phonetics; window start/end; word above/below; and line end. Reuse current speech and braille presentation and boundary behavior. This is flat text review, not semantic parent/child object navigation, Say All, editing, mouse activation, or braille routing into Windows controls. Cover exposed visible text and controls in 32-bit and 64-bit Wine applications. The concrete MUSHclient cases are its command Edit and read-only output notepad. Its custom game display does not become readable merely by adding this bridge; the existing output plugin remains the source of reviewable game text. ## Existing behavior and cause `wine-access/main.cpp` supplies normalized focus/menu/editor events to Cthulhu's session D-Bus service. The 32-bit standard Edit feedback change is already implemented and locally installed. Preserve that work. `cthulhu-go/internal/app/runtime_commands.go` sends review commands to `review.Worker`. Its `CaptureReviewWindow` provider currently captures only AT-SPI objects. Wine focus events go to a separate speech presenter and never establish a review provider or a text snapshot. A spoken caret line is not a reviewable window. `review.FlatCursor` already navigates immutable window trees and preserves a position through stable object identities. `AccessibleTree.Replace` preserves generations of live identities. Reuse these mechanisms instead of implementing a second Wine-specific navigation algorithm or reviewing cached speech. ## Architecture ### Wine capture provider Add a focused capture module beside `main.cpp`, rather than putting enumeration and serialization in its event loop. The helper publishes a read-only D-Bus capture endpoint on its existing unique session-bus connection. Multiple Wine prefixes therefore have independent endpoints without competing for one name. Capture uses a dedicated COM STA worker, independent of the existing native event/menu thread. Permit one active capture and one pending capture; reject additional requests promptly. Native accessibility objects stay on that STA and are released there. Application queries use `SendMessageTimeoutW` where available. A COM call that does not return cannot be forcibly cancelled safely; the Go deadline discards its result, and the busy provider rejects further capture work instead of accumulating it. Helper shutdown remains bounded by the supervisor's existing process-stop policy. Collect a complete snapshot of the foreground Wine window/dialog: hierarchy, stable identities, roles, captions, protected states, clipped screen bounds, visible text ranges, and the focused Edit's caret when available. Traverse MSAA objects and use existing standard-control queries when Wine exposes only a generic client. Standard Edit includes Windows Forms Edit subclasses, in both architectures. Preserve mnemonic decoding for captions and literal ampersands in values. Password text is excluded before copying or serializing it. For Edit text, collect displayed visual lines, including soft wraps and blank rows, with native character positions and client clipping. Do not scroll, select text, change focus, send navigation keys, or copy to the clipboard. The helper converts UTF-16 offsets to Unicode code-point offsets before serialization, retaining native offsets for diagnostics. Computing absolute offsets requires the preceding source text, so bound full Edit source reads at one million UTF-16 units in total per window and return `limited` above that bound. Only displayed ranges cross D-Bus. No approximate character geometry is presented as native. First implementation uses standard Edit and exposed native/MSAA captions and values. Custom painted text, RichEdit, and Scintilla text capture are excluded unless their existing accessibility data supplies usable visible text. Their caret feedback remains as it is today. ### Additive protocol Leave `PresentAccessibleEvent` and NVDA/Tolk contracts unchanged. Add: * `RegisterWineReviewProvider(object_path: o, protocol_version: u) -> b` to the Cthulhu service. Version 1 registration is associated with the actual unique D-Bus sender after the existing same-user authorization, never a caller-supplied destination name. Registration supplies no native references. * `PresentWineReviewFocus(instance: s, window: s, focus: s, revision: t, title: s, role: s, protected: b, bounds: (iiii)) -> b` for that registered sender. Window and focus are opaque lifetime identities. Emit on focus/owner changes and retire identities on destruction. The existing bounded foreground poll recovers missed events. * `CaptureWindow(expected_window: s, expected_focus: s, expected_revision: t) -> a{sv}` on `/org/stormux/Cthulhu1/WineReview`, interface `org.stormux.Cthulhu1.WineReview`. Return a versioned owned snapshot with its identities, revision, bounds, nodes, text ranges, and capture status. The capture dictionary has required keys `version: u`, `instance: s`, `window: s`, `focus: s`, `revision: t`, `status: s`, `bounds: (iiii)`, and `nodes: aa{sv}`. Status is `ok`, `unavailable`, `stale`, `busy`, or `limited`; non-ok responses contain no nodes. Each node has `id: s`, `parent: s` (empty only at root), `role: s`, `name: s`, `protected: b`, `visible: b`, `bounds: (iiii)`, `text_known: b`, `caret_known: b`, `caret: t`, `caret_utf16: t`, and `ranges: a(tttts(iiii))`. Ranges contain code-point start/end, native UTF-16 start/end, exact UTF-8 text, and bounds. `caret` counts code points. Go validates offsets, rune counts, and the resulting tree before use. Captions and identity fields are individually bounded at 4096 and 256 UTF-8 bytes respectively. Limit traversal depth to 64 and reject cycles or duplicate node identities. Revision tracks focus/window lifetime changes, not incoming text. Within a capture, recheck foreground/focus identity before returning and verify that each collected control's text length and visible ranges remain consistent. Return `stale` on a detected capture race, with at most one recapture under the original deadline. Text updates do not retire live control identities. Native handles in identities are opaque fixed-width integers. Include a helper-instance identity and a lifetime counter so reused HWNDs cannot inherit an old review position. MSAA child identities remain subordinate to their owning window lifetime; destroy/reorder events retire uncertain child identity. Do not serialize pointers, COM objects, or prefix environment data. The capture endpoint authorizes the current Cthulhu service owner under the same-user trust model. Reject invalid versions, identities, dimensions, offsets, UTF-8, and oversized messages at both ends. Older helpers/readers retain normal speech; review reports unavailable when this optional protocol is absent. ### Go ownership and integration Place provider registry, capture client, validation, and snapshot conversion in cohesive `internal/wine` files. The registry owns its session-bus connection and tracks provider disconnection. Copied focus notices go to the event-loop owner through a bounded mailbox; D-Bus callbacks never mutate event-loop state. Compose a review capturer around the existing AT-SPI adapter. Wine identities use the registered helper's unique bus name and a reserved `/wine/...` object path namespace. Only this composition layer routes those identities to Wine; they must never be sent to AT-SPI native operations. Ordinary AT-SPI capture keeps its current path. The event loop owns which focus source is eligible. On Xorg, corroborate Wine window bounds and metadata with the current foreground client and epoch. Support a child window inside Wine's virtual desktop using the existing foreground/title discovery. Title equality alone cannot establish ownership. When foreground ownership is unknown, reject Wine capture rather than using an earlier Linux focus. Returning to Linux restores its normal review path. `review.Worker` remains the only owner of the flat cursor and capture ordering. Before each Wine review command, obtain a fresh bounded snapshot, updating a stable owned tree so live object generations and independent review offsets survive text updates. Refreshing only on focus events would miss streaming MUD output. Reuse existing capture/result queues and presentation methods; native text is not fetched on the input or event loop. Accept a result only if the foreground epoch, registered provider, focus, window lifetime, and source revision still match. Focus change, provider death, helper restart, window destruction, or lock activation retires Wine review ownership and queued work. Repeated focus notifications for the same live control preserve review position. Empty focused edits remain valid anchors so review can reach other visible content in the window. ## Bounds, failures, and presentation Use a 500 ms total Wine capture deadline, at most 4096 nodes, 256 visible text ranges per control, 4096 code points per visual line, 65536 captured code points per control, and 1 MiB of text per window. Enforce a 2 MiB serialized snapshot limit including metadata. Exhaustion returns a limited status; never present a partial snapshot as a complete window. The existing review command FIFO remains bounded at 16. Shutdown cancels outstanding D-Bus work and drops late results. Unavailable capture, no visible content, and capture limits use existing complete review messages. Keep Python/current Go's silent movement boundaries, spelling and phonetic sequences, and blank/space handling. Review speech and braille go through the normal queues and settings; no direct speech calls from the helper. Debug logs include provider/source identities, epochs, native UTF-16 and converted offsets, capture timing, command, final speech, and braille text. Password contents never enter debug logs. ## Verification and acceptance Write failing behavioral checks before production changes: * Helper fixtures, 32-bit and 64-bit: visible wrapped text and blank lines, Unicode/surrogate conversion, read-only multiline output, empty command field, captions/native control fallback, hidden/clipped content, password exclusion, unchanged application caret/selection/focus, and capture limits. * Go protocol and review tests: real private-session D-Bus registration/capture, sender association and malformed payload rejection; all listed review units, spelling/phonetics and quiet boundaries; text updates preserving position; independent provider identities for two prefixes; focus switches, reused handles, provider death, helper restarts, stale replies, timeout/queue limits, and cancellation. * Existing helper menu/editor/list regressions and focused Go review, remote, Wine, speech and braille tests with race checks. * Private Xorg fixture driving physical X11 key events through the actual Go command router and both Wine architectures. Verify key press/release balance, focus switching to Linux, input responsiveness during a delayed capture, and no application caret movement caused by review keys. Run private displays sequentially. Recorded speech/braille requests establish queue behavior, not audible speech or physical braille acceptance. Live MUSHclient acceptance must check the user's existing desktop review keys in the command field and output notepad, repeated-word spelling, reading while output arrives, plugin dialogs, and returning to Linux. Install matching tested helper and reader builds only after verification; preserve backups and game state. ## Work locations and delivery Helper changes belong in this standalone repository. Reader integration and its tests belong in `/home/deedra/git/cthulhu-go`, with focused evidence in its Wine testing note and the corresponding gap updated in `MIGRATION_PLAN.md`. The reader directory and installed binaries are outside this session's writable roots, so writes there require tool approval. Existing uncommitted helper changes and `cthulhu.log` must be preserved. After user approval of this document, write a reviewable implementation plan and obtain the required plan/execution decision. Keep source changes available for human review; do not submit them automatically. ## Reference evidence Local behavior references: Cthulhu Python `flat_review_presenter.py` for desktop bindings, independent navigation, spelling, braille and silent boundaries; Cthulhu-Go `flat_review.go`, `flat_worker.go`, `flat.go`, `flat_layout.go`, `AccessibleTree.Replace`, foreground/title ownership, and remote authorization. The Python Wine bridge provides speech events, not a reusable review provider. Microsoft documents [Edit character positions](https://learn.microsoft.com/en-us/windows/win32/controls/em-posfromchar) and [Edit visible-line/text operations](https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/Controls/edit-controls-text-operations.md). These establish the native capture approach, not Wine or MUSHclient acceptance.