Bring in goodies from testing.

# Conflicts:
#	docs/testing/wine-proton.md
This commit is contained in:
hjozwiak committed 2026-11-02 11:30:32 -05:00
commit 3026bc55c2
54 files changed
+2615 -918

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
# Audacious GUI verification
The shared AT-SPI table handling recognizes Qt trees exposing the Table
interface and GTK list tables. A uniquely selected row can restore its showing,
focused cell after a menu closes. Multiple selected rows must not produce a
guessed focus target. GUI full-row speech omits cells that are not showing.
When Qt hides a submenu without a focus event, its parent action is accepted
only with fresh provider focus and visibility evidence.
Run `python3 tests/native_audacious.py` with Audacious's Qt and GTK interfaces,
Xvfb, i3, xdotool, Python gi/pyatspi, and the native build dependencies installed.
The harness creates temporary tracks and private configuration, display and
D-Bus sessions. It checks queued speech and Braille for playlists, nested menus,
the playlist manager, settings, and context menus. It does not verify audible
speech or a physical Braille display. Also run the
[generic Qt checks](qt-control-states.md).
For live acceptance:
1. Quit Cthulhu with Cthulhu+Q. Press Ctrl+Escape, then Shift+G to rebuild and
launch it. These are separate key presses.
2. In an Audacious playlist, move between tracks. Expect the selected track's
visible row content in speech and the focused cell on Braille, without
hidden filename/path columns.
3. Open Playlist's Sort submenu. Move through commands, then press Left and
Escape. Expect the parent menu item on return and the original track when
the menus close; arrow keys must continue moving through tracks.
4. Open Settings, Tab and Shift+Tab through controls, then close it. Expect each
focused control and restoration of the playlist. Unfocused password-field
initialization must not be announced.
5. Repeat with the other interface when available. Record the exact speech,
Braille, focused control and key sequence for any discrepancy.
+7 -4
View File
@@ -5,8 +5,10 @@ selected descendants or capturing their text, values, attributes and geometry.
The native adapter owns this decision on the GLib thread. It uses the existing
foreground window and epoch; there is no additional window ownership cache.
Events from another provider can be rejected using copied bus identities and
libatspi's cached role and application name, without querying that provider.
Events from another provider first resolve their containing window: GTK socket
children can belong to the foreground host while using a different provider
bus. Unrelated providers are then rejected using the resolved window and copied
bus identities, before any content queries.
Events from another window on the same provider undergo the existing window
correlation before content capture. Lifecycle invalidation still runs, but a
background provider no longer clears another provider's cached document lines.
@@ -16,8 +18,9 @@ their existing handling. Announcement events are explicit requests to speak
and also bypass the filter; see [announcements](announcements.md). Native alerts, notification daemons and supported
Steam toasts retain their notification paths. Menu popups retain existing
foreground checks. Verified active/showing `mate-panel` menu windows may pass
across provider boundaries, including over an empty desktop; ordinary panel
controls and hidden menus remain filtered. See [MATE desktop](mate-desktop.md).
across provider boundaries, including over an empty desktop. Embedded panel
controls use their host's normal X11 correlation; unrelated panel windows and
hidden menus remain filtered. See [MATE desktop](mate-desktop.md).
Same-provider autocomplete relations and tooltip candidates
continue through the existing event-loop ownership checks; they do not acquire
focus merely by passing the early filter.
+34
View File
@@ -18,6 +18,7 @@ Reviewed the local `orca/` checkout at revision `a8a851800`:
| Marco window cycling | `script_manager.py`, `scripts/switcher/script.py`, `scripts/switcher/script_utilities.py` | Already implemented; see [window switcher checks](window-switcher.md). |
| MATE notification daemon | `script_manager.py`, `scripts/apps/notification-daemon/script.py` | Already routed through notification capture, speech, Braille and history; added an explicit MATE daemon regression. |
| Unnamed panel icons | `generator.py:_generate_accessible_name` | Adapted the containing panel's name/description when the icon supplies neither. Own names and descriptions retain precedence. |
| Embedded panel applets | `script_utilities.py:frame_and_dialog`, `script_utilities.py:top_level_object`, `scripts/default.py:_on_focused_changed` | Follow the accessible parent chain through a GTK plug/socket to its host window before normal foreground validation. |
Orca has no dedicated `mate-panel` script in this checkout. Its current app
script catalog also contains no Caja, Pluma, Atril, Engrampa or Eye of MATE
@@ -39,10 +40,32 @@ hidden menu items retain normal filtering. Native actions and review use the
same window validation. The correlated X11 application is preserved; no popup
cache, native references, timer or extra window owner is introduced.
## Embedded applet ownership
The newer `kendell/mate.log`, recorded with revision `702894ee`, shows a
different failure: Bottom Panel controls are accepted, but focused icons from
other provider buses are rejected as outside the X11 foreground. The reader
announces the host's generic "panel" while discarding the embedded icon.
A real GTK socket/plug reproduction exposes the same structure. The applet
publishes its own frame, whose accessible parent chain crosses the socket's
provider and reaches the panel frame. Window resolution now follows that chain
to the host instead of stopping at the plug frame. The background filter also
resolves this window before rejecting a different provider bus. The source
object retains its own bus, path and process identity for focus and actions.
This is shared window ancestry handling: it requires no MATE process-name
exception. Normal X11 process, state and geometry checks still apply to the
host. Same-provider nested frames retain their existing nearest-window
behavior. An unembedded or detached applet cannot borrow the host's identity,
and a background host cannot admit applet focus. Parent links beyond the plug
frame are refreshed on the GLib owner; no embedding cache is retained.
## Automated checks
```sh
python3 tests/native_test_session.py env CTHULHU_NATIVE_PANEL_MENU=1 CTHULHU_NATIVE_WINDOW_SWITCHER=1 CTHULHU_NATIVE_BACKGROUND_EVENTS=1 go test -race ./internal/atspi ./internal/app -run '^TestNative(MatePanelMenu|MateWindowSwitcherOutsideForeground|BackgroundEventFiltering)' -count=1 -p=1 -timeout=90s -v
python3 tests/native_test_session.py env CTHULHU_NATIVE_PANEL_APPLET=1 go test -race ./internal/atspi ./internal/app -run '^TestNativeEmbeddedPanelApplet' -count=1 -p=1 -timeout=90s -v
go test ./internal/app -run '^TestNotificationProvidersAndHistoryMatchReferenceBehavior$' -count=1
```
@@ -55,6 +78,14 @@ inherited labels, own-name/description precedence and unrelated-container
rejection. The event-loop check verifies queued speech and Braille frames for
navigation, dismissal, editor return and reopening. It emits no audible speech.
The socket/plug fixture uses separate host, applet and editor processes. It
checks the shared containing-window identity, preserved applet identity, icon
label inheritance, Tab/Shift+Tab within the applet, host controls on either
side, and editor restoration. It also checks a non-MATE host, background applet
focus, an unrelated applet claiming the MATE application name, and stale focus
after socket destruction. The event-loop check verifies speech requests and
Braille frames through two panel/editor round trips.
The existing background flood regression checks that ordinary same-provider
and other-provider updates still cause zero content queries. The Marco
regression checks switcher insertions and showing events while an editor
@@ -87,6 +118,9 @@ MATE session. After starting the candidate through the normal launcher:
typing and ordinary Tab navigation. Check terminal-reader handoff if used.
3. Use Control+Alt+Tab to reach the panel and navigate its applets. Confirm
applet icons use supplied labels without repeating unrelated container text.
Traverse both directions through launchers, clock, notification area and
configured external applets. Open and dismiss applet controls, then return
to the previous application. Background applet updates must stay silent.
4. Cycle windows with Alt+Tab and Shift+Alt+Tab, then cancel with Escape.
Check a MATE notification and its notification-history entry.
5. Return to browser heading navigation and address-bar suggestions, and open
+33
View File
@@ -128,3 +128,36 @@ The implementation work does not replace the running reader.
once and the normal focus display returns afterward.
Actual Pidgin listening, physical shortcuts, and Braille acceptance remain pending.
## Discord message focus
Named article ancestors are announced when focus enters their controls, matching
Python's article ancestor presentation. Discord supplies the message author,
contents, and timestamp in the article's accessible name. The message is spoken
once on entry, followed by the focused button. Moving between controls within
the same article does not repeat it. Leaving does not repeat the old message.
This also works in focus mode and while browser context discovery is pending.
Unnamed articles do not add announcements; other container preferences retain
their existing browse-mode policy. Native traversal retains its depth and time
limits and does not scan message descendants.
Automated checks:
```sh
go test ./internal/app -run '^TestMessageArticleAnnouncedOnceWhenTabbingIntoControls$' -count=1
CTHULHU_NATIVE_BROWSER_TESTS=article python3 tests/native_browser.py
```
Both tests fail without the corresponding fix. The private Chromium fixture
checks native capture of a message article labelled by author, body, and time.
The speech replay checks entry, movement within a message, movement to another
message, exit, and re-entry. Neither establishes audible Discord acceptance.
Before submission, review the diff and test a rebuilt reader in Discord with
Tab and Shift+Tab: enter a message's controls, move through Reply/Forward and
reactions, then enter another message. Confirm each message is read on entry,
control labels remain correct, and message contents do not repeat at each Tab
stop. Repeat in browse and focus modes; check the message composer, ordinary
browser buttons, and list/panel context announcements for regressions. Verify
physical Braille focus and routing separately. Installed-binary, physical-input,
audible-speech, and Braille-display acceptance remain pending.
+4 -2
View File
@@ -40,8 +40,10 @@ queued speech and Braille frames through Cthulhu's event loop for menu-bar and
context-menu actions, checking and unchecking ordinary checkboxes and checkable
buttons, an ordinary menu command, same-label action replacement, and explicit
capability removal. It also traverses shared and context-only actions in both
directions and after reopening the context menu. It requires both Python Qt bindings,
xdotool and the native build dependencies. It does not replace the active
directions and after reopening the context menu. It also checks Left and Escape
from nested menus, including providers which report the return only by hiding
the submenu; see [Audacious GUI checks](audacious.md). It requires both Python
Qt bindings, xdotool and the native build dependencies. It does not replace the active
reader or establish audible speech or physical Braille acceptance.
Existing package checks cover mixed states, state sounds, speech-only and
+44
View File
@@ -0,0 +1,44 @@
# Tentacle update verification
Refresh an installed Tentacle's repository in Preferences, select the Tentacle,
and choose Update. The confirmation displays both versions and the old and new
capabilities. Cancel must leave the installation unchanged. Update preserves
enablement at the point the package is saved, including a disable requested
while downloading.
Versions use dotted numeric components, optional prerelease identifiers and
optional build metadata. Missing numeric components compare as zero; build
metadata does not make a release newer. Invalid versions are not offered as
updates. Downloads retain the existing HTTPS, checksum and manifest checks.
An enabled replacement must register and activate before success is reported.
Startup failure or cancellation attempts to restore the previous package and
enablement. Recovery persistence errors are reported explicitly. Retired files
remain until their session has stopped. A disabled package is replaced without
starting it.
Automated checks:
```sh
go test ./internal/tentacle ./internal/app -run 'Test.*(Upgrade|Update|Version)' -count=1
go build -o /tmp/cthulhu-update-check ./cmd/cthulhu
CTHULHU_BINARY=/tmp/cthulhu-update-check CTHULHU_PREFS_TENTACLE_UPDATES_ONLY=1 python3 tests/native_preferences.py
```
The GTK harness uses fixture data and a private display/bus, checks Tab and
Shift+Tab, confirmation details, Cancel and the upgrade request, and does not
update installed packages. Lifecycle tests exercise activation and rollback.
For live acceptance:
1. Quit Cthulhu with Cthulhu+Q. Press Ctrl+Escape, then Shift+G to rebuild and
launch it. These are separate key presses.
2. Open Preferences and select an installed test Tentacle with a newer release.
Refresh its repository, then Tab to Update and use Shift+Tab to return.
Expect accessible control names in speech/Braille and no keyboard trap.
3. Activate Update. Verify versions and capabilities are readable, then Cancel.
Verify the installed version and existing shortcuts still work.
4. If you intend to install that release, reopen Update and accept. Verify the
new version, its shortcuts and its previous enabled/disabled state. Close
and reopen Preferences to verify persistence.
5. Record exact speech, Braille, focus and keyboard results for discrepancies.
+26
View File
@@ -40,6 +40,32 @@ operational only; this contract remains normative if they differ.
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.
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
+30
View File
@@ -0,0 +1,30 @@
# XTerm handoff verification
While input is delegated to a terminal reader in XTerm, Cthulhu suppresses
ordinary key echo, input-driven speech interruption and lock-state feedback.
It releases its command grabs. On return, Caps Lock tracking adopts the current
XKB lock state before treating Caps Lock as the reader modifier again.
Focused checks:
```sh
go test ./internal/app -run 'Test(XTerm|DelegatedInput)' -count=1
python3 tests/native_x11.py
```
The native harness uses a private X display and checks grab suspension,
restoration and lock state with synthetic input. Audible output from another
reader and physical keyboard handling require live verification.
1. Quit Cthulhu with Cthulhu+Q. Press Ctrl+Escape, then Shift+G to rebuild and
launch it. These are separate key presses.
2. Focus XTerm with your console reader active. Press its reader modifier and
navigation keys. Expect the console reader to receive them, without
Cthulhu modifier echo or Cthulhu interrupting its speech.
3. Change Caps Lock in XTerm, then switch to an ordinary desktop application.
Expect Cthulhu to resume focused-control speech and Braille and accept its
configured modifier commands with the current lock state.
4. Switch back and repeat with keypad commands where configured. Confirm
focus stays on the intended application and no key remains grabbed after
handoff. Restore the original lock state.
5. Record the exact keys, focused application, speech and Braille for failures.