# Steam/Proton and controller-only verification Status: Closed — accepted with known limitations on 2026-11-02. Settled decisions from the 2026-11-01 grilling session are recorded here; unresolved questions and unfinished verification stay visibly marked. This document is deliberately **not** marked Final under decision 15: the maintainer superseded the original exhaustive done checklist for closure after judging the core implementation and basic live behavior sufficient for this stage's purpose. See the maintainer closure amendment under the scope contract. Execution is split into separately reviewed phases: Phase 0, the already-committed native-exclusion foundation; Phase 1, ready record, spawn evidence, and mixed-prefix semantics; Phase 2, live Wine settings; Phase 3, the Wine preferences tab; and Phase 4, live verification and final results. Branch assignments, activation rules, fresh-session startup text, and handoff reporting live in [wine-proton-phases.md](wine-proton-phases.md). That ledger is operational only; this contract remains normative if they differ. ## Established facts (verified live, 2026-11-01) - Cthulhu sends one `--exclude-hook-program ` argument per entry in the profile's `wine.excluded-hook-programs` setting, plus `--no-dialog-reader` when a listed program (or the global `wine.controller-only` setting) makes the prefix controller-only. - The wine-access helper enforces exclusions itself: a listed program's thread never receives the native menu/input hooks, and its windows get no dialog reading, from the helper's first foreground poll. Controller speech and review remain available. - Diablo IV under Proton Hotfix (Steam app 2344520), with `excluded-hook-programs = ['Diablo IV.exe']`: the running helper showed `--exclude-hook-program diablo iv.exe --no-dialog-reader`, staged under `~/.local/state/cthulhu/wine-access/helper//` for the pressure-vessel session, and the game stayed up past the roughly 100-second window in which full-mode sessions had crashed on 2026-10-31. - Two failure modes were proven the same evening: a missing TOML section silently means full mode, and a stale helper that owns the Wine session singleton defeats any newly launched helper regardless of settings. ## Loader selection and helper staging Merged in from the testing branch's parallel document during the 2026-11-02 sync, corrected where Phases 1–3 superseded it. Cthulhu selects a loader from the application's Wine environment and executable. It bypasses a recognized Protontricks runtime proxy and searches the Proton installation for a usable loader. For processes advertising `PRESSURE_VESSEL_RUNTIME`, it stages the complete helper set under `$XDG_STATE_HOME/cthulhu/wine-access/helper` (default `~/.local/state`). Sets are content-addressed and verified before use; running sets are never overwritten. The helper keeps the reader's D-Bus address and receives the application's display, authentication, and Wine synchronization settings. Loader selection, staging, and environment forwarding are covered by `go test ./internal/wine ./internal/config -count=1`; fixtures do not establish compatibility with a real Proton runtime or audible Wine output. Helper readiness is published from bounded stderr input before diagnostic throttling or log delivery, so a diagnostic burst or stalled log sink cannot discard the exclusion count needed for fallback. Configuration, preferences, and helper launch use the same executable-name validation, including rejection of embedded control characters. Regression checks: ```sh go test ./internal/wine ./internal/config ./internal/preferences -count=1 ``` The private Wine preferences check also exercises pasting an embedded tab, blocking Apply, deleting the invalid row, and applying valid entries. It needs `xclip` for the private clipboard: ```sh go build -o /tmp/cthulhu-wine-check ./cmd/cthulhu CTHULHU_BINARY=/tmp/cthulhu-wine-check CTHULHU_PREFS_WINE_ONLY=1 python3 tests/native_preferences.py ``` Two statements in that parallel document described pre-stage behaviour and are **not** carried forward: Wine settings no longer require a reader restart (a global preferences Apply republishes them live, Phase 2/3), and an excluded program appearing in a prefix no longer switches that prefix's helper wholesale to controller-only mode (gating is per-program native, Phase 1). ## Settled decisions 1. Scope of the next stage (2026-11-01): the manager trio (diagnostics classification, spawn decision logging, live settings reload), a Wine section in preferences, and this document. Nothing outside that set is approved by this decision. (Widened once, by decision 5, to include the ready-record field in the wine-access helper.) 2. Spawn logging mirrors Orca's text format: the helper-start record carries `programs=[...] extra=[...]` with sorted program names and the exact extra helper arguments, so both readers' logs read identically and can be compared line for line. 3. Wine settings take effect as soon as preferences are finished (Apply), with no reader restart. The manager reads the same live settings the rest of the reader uses, at each poll and helper spawn, instead of the one-time snapshot it takes at startup today. 4. A running helper keeps its current mode until its game exits. The only mid-session change is the existing safety upgrade: if an edit newly protects a running game, its helper restarts into the protected mode. Removing a program or clearing the global switch never downgrades a running helper. Rationale: helper restarts tear down and recreate the NVDA controller endpoint, and some programs (Mistworld is the known example) crash when that endpoint is pulled out from under them. Restarts therefore happen only when protection is being added, never as a side effect of unrelated edits. (For the listed-program path, this restart is superseded by decision 16; the no-downgrade rule stands.) 5. The helper's ready record gains a `hook_exclusions` count beside `controls_enabled` and friends, and Cthulhu parses and logs it as a field of the initialized record. The plain startup line stays (it is emitted even when a helper exits early, for example against the singleton), and Cthulhu recognizes it as info; the invalid-exclusion line stays a warning. Older helpers without the field report zero, which is accurate for them. This extends the stage into the wine-access helper by explicit choice. 6. Preferences gain a Wine tab modeled on the Pronunciation page: a "Controller-only mode for all Wine applications" checkbox and an editable program list (tree view with New and Delete), with text explaining that listed programs keep controller speech but lose standard control reading. Entries are validated by the existing settings rules at Apply. 7. Done includes physical Braille acceptance. The display is usable again (paired over Bluetooth, so the missing charger no longer blocks it), and the stage is not done until Wine output is checked on the physical display alongside the speech checks. 8. The stage lands in reviewable steps, evidence first: diagnostics and spawn logging, then live settings exercised through the TOML, then the Wine preferences tab, then this document and the live acceptance pass. The reader stays usable at every step, and no intermediate step counts the stage as done. 9. The Wine tab validates entries as they are edited: a path, a blank, or an overlong name is flagged by name in the tab and blocks Apply until fixed or deleted. Case-insensitive duplicates collapse to a single entry. Config validation remains the backstop; invalid entries are never silently dropped, since a user who believes a game is protected when nothing was saved for it is tonight's failure repeated. 10. The Braille bar is a full Wine regression on the physical display: review cursor, window titles, menus, and edits across several applications, not a spot check of focus output alone. This widens decision 7's "done" by explicit choice. 11. Every failure that regression finds blocks done, whenever the defect was born. There is no baseline carve-out for pre-existing failures: the stage ends with the full Wine Braille regression passing clean, at whatever size that makes the stage. 12. No escape hatch. If a blocking Braille failure needs a redesign, or its root cause sits in shared infrastructure rather than Wine-specific code, it is still built inside this stage. The stage's true size is accepted as unknown until the regression passes clean. 13. Program names enter the Wine tab by typing only, as under Orca. There is no running-program picker and no file browser in this stage; a well-formed but wrong name remains possible, with the mirrored spawn log as the after-the-fact evidence. 14. The live regression corpus is fixed by name: Diablo IV (excluded, anti-tamper), Mistworld (controller-endpoint sensitivity), Wine Notepad (menus and plain edits), Notepad++ (Scintilla edits), and the Battle.net bootstrapper (UIA path). Results are recorded per application in this document. If an application becomes unusable for reasons unrelated to the reader, its replacement is decided and recorded here, never silently dropped. 15. This document stays Draft through implementation and acceptance testing. Contract acceptance settles the decisions above; the document becomes Final only when the done checklist passes and the per-application results are written in. 16. Exclusion is per program, enforced by the helper natively. A listed program's presence in a prefix no longer flips the whole helper to `--no-dialog-reader`: other programs in the same prefix keep full hook and dialog reading while the listed one gets the controller only. For avoidance of doubt, `--no-dialog-reader` itself remains helper-wide for the whole prefix; a listed name by itself must never cause Cthulhu to pass it. The global controller-only switch still runs the whole helper with `--no-dialog-reader`, and that wholesale mode is also the fallback when a helper's ready record does not confirm it applied the exclusions it was sent (for example an old helper that ignores the flags). This supersedes the upgrade-on-listed-appearance restart in decision 4 for the listed path, and both readers change together; the wine-access side of this stage therefore includes the Orca manager's spawn semantics, not only the ready-record field. 17. A list addition reaches a running helper at the moment it matters: if the newly listed program is discovered in a prefix whose running helper lacks its flag, that helper restarts once in the same mode, now carrying the flag. Additions for programs that are not running wait for the next natural spawn. Restarts thus happen only to add presently-needed protection, never for prospective edits or housekeeping. 18. Both managers consume the helper's ready record at startup. If its `hook_exclusions` count does not match the flags sent, that helper restarts once in wholesale `--no-dialog-reader` mode, and the manager remembers that binary as unconfirmed so later spawns go wholesale directly. Go wires its existing diagnostics parser into the manager; Orca reads the spawn's stderr through a bounded forwarding path instead of only filing it. No new D-Bus protocol surface is added for this. 19. The Wine exclusion list is global-only. The manager always reads the active/global profile's Wine values and ignores per-application profile switching for Wine. The Wine tab appears only in global preferences. One list therefore governs every prefix regardless of which application currently has focus. 20. Cthulhu and Orca keep independent Wine exclusion lists. There is no one-time import and no live shared canonical list in this stage. Each reader's list is maintained in its own settings system. The maintainer plans to transition to Cthulhu full-time relatively soon, so Cthulhu is the primary path going forward. 21. Orca is frozen as-is for this stage. The maintainer does not intend to use Orca anymore after today, and Cthulhu is the sole normative reader for the remaining Wine work. This supersedes the parts of decisions 5, 16, and 18 that required both readers to move together: no Orca manager per-program spawn semantics, bounded Orca stderr reader, Orca test gate, or Orca relaunch acceptance is required here. Existing Orca support stays as it is; anyone who wants to carry it forward can do so later. The wine-access helper ready-record field remains in scope because Cthulhu consumes it. 22. Decision 21 is a stage-and-maintainer scope decision, not a project-wide deprecation of Orca. This maintainer is not the repository's sole maintainer, and the decision records only that he will not use or carry the Orca path in this stage. It does not preclude other maintainers from using, maintaining, or improving Orca support. 23. No wine-access maintenance-status notice will be added for this stage. The work is overwhelmingly Cthulhu-based; apart from any root-cause Braille fix the regression may prove necessary, the only planned wine-access code change is the helper ready-record field that Cthulhu consumes. Decisions 21 and 22 do not change Orca's project status, functionality, or availability to other maintainers, so there is no work-relevant maintenance-status change for wine-access documentation to announce. 24. Mixed-prefix operation remains mandatory. It is not merely a Diablo hypothetical: the maintainer has real mixed-prefix uses, and ordinary programs in a prefix must retain hooks and dialog reading while a listed program in that same prefix receives only controller support. The current silence from Wine Notepad while Diablo IV is alive is therefore a defect against decision 16, caused by Cthulhu adding the prefix-wide `--no-dialog-reader` once the listed program is discovered. Removing that listed- presence trigger is required; wholesale mode remains available only for the global switch/environment override and the unconfirmed-helper fallback in decision 18. 25. The scope contract below is accepted for now as the settled stage boundary. On 2026-11-01, in this Muse Code session, the maintainer said: "For now, I am satisfied." Per decision 15, that acceptance does not finalize this document or authorize implementation; it remains Draft until the done checklist passes and the per-application results are written in. ## Unresolved questions (none) ## Scope contract (accepted; closed with known limitations) Boundary. In Cthulhu: `internal/wine`, the Wine settings wiring in `internal/app` and `internal/config`, a Wine page in `internal/preferences` including `preferences.ui`, and this document. In wine-access: the ready-record field in the helper only. For this stage and this maintainer's work, the Orca integration is frozen as-is under decisions 21 and 22; that is not a project-wide Orca deprecation. No Orca manager changes, Orca test gate, or Orca relaunch acceptance belongs to this stage. Fixes for blocking Braille regression failures (decisions 11 and 12) may land wherever their root cause lies, including shared Braille infrastructure. Out of scope: staged-helper hardening parity for the Orca manager, stale-helper retirement redesign, the `explorer.exe` classification divergence, Nix helper candidates on the Go side, and landing either repo's branches anywhere (commits and merges stay the maintainer's separate acts). Done means, all of: - Cthulhu test suites pass for the touched packages, and the wine-access helper CTest suite passes. Orca tests are not a gate. - Diablo IV under Cthulhu: controller speech confirmed by ear, game survives a normal session, and the start log shows the mirrored `programs=[...] extra=[...]` record plus the exclusion count. - An ordinary Wine application still reads standard controls in the same setup, including inside an excluded game's own prefix while the game is present and unaffected. - Full Wine Braille regression on the physical display: review cursor, window titles, menus, and edits across several applications, passing clean with no unresolved failures regardless of when a defect was introduced. - Preferences round trip by keyboard: Tab and Shift+Tab through the Wine tab, edit the list, Apply, and confirm a newly started helper picks the change up with no reader restart. Nothing outside this checklist is a completion dependency. Accepting this contract does not authorize implementation; that takes a separate explicit request. Maintainer closure amendment, 2026-11-02: after Phases 0–3 landed and the partial Phase 4 verification below, the maintainer closed this stage as **accepted with known limitations**. The original checklist is retained above as the historical criterion, but its no-carve-out/no-escape-hatch closure gates in decisions 11 and 12 are superseded for closure of this stage. The maintainer judged the original planning more expansive and pessimistic than the stage's core objective requires; the delivered basics are working well enough. This closure does **not** assert that every original checklist item passed. The following remain unfinished, deferred, or separately future work rather than stage blockers under the revised acceptance basis: the localized Wine window-title failure; Battle.net's unread Chromium login; completion of the full physical-Braille pass and unrelated tangential Braille bugs; the deferred pre-attached edit-subclass remedy; Notepad++ operations not separately reported; and a single-environment wine-access CTest 7/7 on this Wayland system. Marking this contract Final, if ever desired, remains a separate maintainer act. ## Live verification results (Phase 4, interim at closure) Recorded as results arrived; evidence kinds are kept separate. These entries retain their individual scopes and caveats at the stage's accepted-with-limitations closure; the original done checklist was not fully satisfied. Automated baseline, 2026-11-02, on the Phase 4 tree (`ec1a620`): Cthulhu `go test ./...` passes in full when run unsandboxed (the sandbox-only Unix-socket failures seen during Phases 1–3 do not occur), `go vet ./...` is clean, the parity ledger validates, and the brlapi-tagged wine/config/preferences suites pass. Wine-access builds clean. Its CTest suite initially ran 5/7 on the live desktop, with `review-capture64/32` failing at one stale-status/clipping check on source unchanged since they last passed; follow-up classification on 2026-11-02 identified display-environment sensitivity, not a code regression: under a private Xvfb screen the review-capture pair passes while `foreground-focus` fails for want of real window-manager focus semantics, and on the live desktop the pattern inverts. Every test passes in at least one environment. A single-environment 7/7 run has not been established on this Wayland system and may require a purpose-built private compositor/XWayland harness with real window-manager focus semantics; an idle live desktop should not be assumed to provide it reliably. Whether the present split-environment evidence suffices is an open question for the maintainer and other reviewers before this phase closes. - Diablo IV (Proton app 2344520), 2026-11-02 — **passed so far.** Exclusion-list-only configuration, global controller-only switch off. Evidence: installed binary (maintainer-rebuilt reader) and audible speech. The game survived a normal-length session after relaunch with no crash observed, following the extended Phase 3 test period. Controller speech is normal by ear, "the same as it's ever been," apart from long-standing game-side formatting quirks present for years and unrelated to this stage. The mirrored start-record and exclusion-count parts of this done item are covered by automated tests; a live log sighting was not separately recorded. Physical-Braille evidence for this title belongs to the dedicated Braille pass below and is still outstanding. - Mistworld (plain Wine, prefix `~/.local/wine64`), 2026-11-02 — **passed so far.** Evidence: installed binary and audible maintainer report. Configuration as found in the live settings file and confirmed by the maintainer: the global controller-only switch was OFF and `mw.exe` is not in `excluded-hook-programs` (only `Diablo IV.exe` is listed), so this normal session—login and daily chores—ran with dialog reading enabled and no per-program protection, and worked properly with no helper-restart incident. This does not prove listing Mistworld or the global switch unnecessary in all circumstances; it records that ordinary play in the maintainer's actual configuration is unregressed. A maintainer attempt to co-launch Notepad into the same prefix by an incorrect method crashed the game; that is recorded as a launch-method incident outside the corpus (the mixed-prefix item belongs to an excluded game's prefix), not as reader evidence either way, and will not be retried. The maintainer also notes Mistworld takes roughly fifteen seconds to close, attributed to the Wine helper's shutdown and observed since before this stage; recorded as a pre-existing wine-access annoyance, not a stage regression. Physical-Braille evidence outstanding, as above. - Wine Notepad in an excluded game's prefix — **passed.** Evidence: installed binary, audible speech, physical input. Established by two maintainer live runs already on record: the Phase 1 smoke (Diablo IV excluded and running, Notepad launched into app 2344520's prefix read normally, Diablo unaffected) and the Phase 3 flesh test's baseline reading before Notepad itself was listed. No re-run was needed for Phase 4. - Keyboard-only preferences round trip — **passed.** Evidence: physical input and audible speech. The maintainer confirms the Phase 3 flesh test was driven by Tab and Shift+Tab through the Wine tab's controls: the list was edited, Apply submitted the change, the restarted helper adopted it with no reader restart (dialogs and fresh instances of the newly listed program were gated), and reopening preferences to remove the entry completed the round trip. The pre-attached edit-subclass caveat recorded at Phase 3 acceptance applies to the already-running instance in that test and is deferred as recorded in the phase ledger; it does not affect this round trip's result. - Physical Braille, preliminary observations, 2026-11-02 — **in progress, with one open failure.** In Wine Notepad (`~/.wine`), Braille follows movement, and reading by character, word, and line Brailles normally. Inserted characters not echoing is the maintainer's key-echo configuration (key echo disabled), which Wine typing intentionally honours for both speech and Braille; not a failure. However, Wine window titles are not being read in any tested Wine application (the `~/.wine` Notepad, Diablo IV, Mistworld), in speech or Braille, while native Linux window titles read normally; the explicit title command in the Notepad answered that it could not find the current window title. The intended behaviour—introduction on foreground return and an explicit title that bypasses automatic policy, with a Braille flash—is specified and unit-tested, so this is an open failure to fix under decisions 11–12, not a known accepted limitation. A maintainer debug log from 2026-11-02 localized it: the session is Wayland, native foreground/title metadata stays unknown/empty (epoch 0), every Wine review notice is rejected as a foreground mismatch, an automatic helper title for the Notepad did reach the speech queue and Braille at least once, but the explicit present-title command immediately afterwards still failed—its lookup has no Wine-helper/review fallback when native metadata is absent and no AT-SPI owner stored a title. Menus on the physical display and the remaining applications' Braille checks are still outstanding. - Battle.net bootstrapper, 2026-11-02 — **open; investigation deferred by the maintainer.** Evidence: installed binary and audible report. The launcher reached its login, but the login did not read. No root-cause diagnosis was attempted; the maintainer defers this Chromium-engine surface as a later task because of its separate intricacies and scope. Under the original decisions 11–12 it was a completion blocker; the maintainer closure amendment above later superseded that gate for this stage. Deferral is still not a pass. - Notepad++ (Scintilla edits), 2026-11-02 — **passed so far.** Evidence: installed binary, audible speech, physical input, and physical Braille. The maintainer reports that normal editing worked fine, including basic navigation, Braille tracking, selection, Backspace, and Delete. A document with copious Unicode was not available, so extensive Unicode editing was not live-exercised; cut, undo, menu return, read-only mode, and a very long line were not separately reported. This entry therefore closes the basic live Scintilla navigation/edit/ Braille item without claiming those unreported extras.