# AGENTS.md ## Project Purpose Audiogame Manager installs and launches Windows audio games under Wine or UMU/Proton on Linux. Contributions must preserve keyboard and screen-reader accessibility in both console `dialog` and graphical `yad` modes. ## Repository Map - `audiogame-manager.sh`: main entry point, game menu, launcher, removal flow, and shared runtime state. - `.install/`: one sourced Bash installer per game. The filename, minus `.sh`, is the game name shown in the install menu. - `.includes/`: shared bottle, UMU, download, dialog, desktop, help, update, and URL helpers. - `.includes/ipfs.sh`: centralized IPFS URLs for core files and games. - `game-scripts/`: scripts installed or used by particular games after installation. - `speech/`: speech-related helper and setup scripts. - `wine/`: distribution-specific dependency installers and Wine utilities. - `tests/`: isolated shell regression tests with mocked external programs. ## Runtime Architecture - This is a Bash project, not a POSIX `sh` project. Arrays, associative arrays, `mapfile`, `[[ ... ]]`, and Bash parameter expansion are used intentionally. - Installer files in `.install/` are sourced by the main process. They share functions and exported state from `audiogame-manager.sh` and `.includes/`; they are not independent programs. - Common installer state includes `game`, `cache`, `WINEPREFIX`, `WINEARCH`, `winetricksSettings`, and helper functions such as `download`, `install_wine_bottle`, `install_proton_bottle`, `install_with_progress`, `add_launcher`, and `add_umu_launcher`. - The launcher configuration is pipe-delimited. Keep its field order compatible with `create_game_array()` and `process_launcher_flags()`. - Native Wine and UMU/Proton are separate backends. Use the helpers for the selected backend; do not mix their bottle paths, environment setup, launcher functions, or shutdown functions. - The main script performs dependency checks, bottle setup, update checks, and other startup work before command dispatch. Do not source it casually in tests. Source the smallest `.includes/` file needed and mock its external commands. ## Game Installer Conventions - Name a new installer `.install/Game Name.sh`; that filename becomes the menu label. - A first line beginning with `#//` hides an installer from the menu. Preserve this convention when editing disabled installers. - Quote paths and expansions, especially game names and Windows paths containing spaces. - Use `download` so caching, progress reporting, retries, and validation remain consistent. - Use `install_with_progress` for archive extraction or copies that could otherwise prompt invisibly. Extraction must be non-interactive and safe to repeat. - Use `install_wine_bottle` plus `add_launcher` for the Wine backend. - Use `install_proton_bottle`, the UMU helpers, and `add_umu_launcher` for the UMU backend. - After installation, verify the expected executable exists before recording a launcher when failure would otherwise produce a broken menu entry. - Set game-specific environment or winetricks values in the installer rather than changing global defaults for one game. - Prefer idempotent installation steps. Re-running an installer should not hang on overwrite prompts or silently corrupt an existing bottle. - Do not delete a shared Wine or Proton bottle to remove one game. Removal code must target only the selected game's files and launcher entry. ## Portability and Dependencies - Contributors and coding agents may use any locally installed tools, including ripgrep (`rg`), while searching, reviewing, testing, or editing the repository. This restriction applies only to commands invoked by scripts shipped to users. - Keep commands used by shipped scripts portable. Do not make runtime code depend on ripgrep or other modern command-line tools that are not commonly installed by default when classic Unix tools can provide the required behavior. - Prefer broadly available classic Unix tools such as `grep`, `sed`, `awk`, and `find` when they provide the required behavior. - A nonstandard runtime dependency is acceptable when there is no practical portable alternative, but it must be declared and checked rather than assumed. - Add every new runtime dependency to `.includes/checkup.sh`, including its `packageList` entry so `audiogame-manager.sh -P` reports it. Update the relevant distribution-specific dependency scripts under `wine/` when they manage packages for that platform. - If Audiogame Manager cannot perform its basic startup or core functions without a dependency, also add it to the startup checks in `check_requirements()` alongside critical commands such as `sox` and `dialog`. - Do not assume a developer's interactive shell aliases, local utilities, desktop session, or current working directory are available. - Resolve repository files relative to `scriptDir` or `BASH_SOURCE`, as appropriate. - Do not add compatibility fallbacks or legacy paths unless they are an explicit requirement. ## Shell Style - Follow the surrounding file's style and keep edits narrowly scoped. - For new code, use camelCase variables and snake_case functions. Use PascalCase only for class-like concepts if any are introduced. - Quote variable expansions unless intentional splitting or pattern matching is required. - Prefer arrays for argument lists; do not construct commands in strings and evaluate them. - Treat sourced shared globals deliberately. Add a focused ShellCheck suppression with a reason when a value is populated by the caller; do not broadly silence actionable warnings. - Logging timestamps follow the message: `message [date]`. - Do not add colored output unless requested. ## Accessibility and Interaction - Screen-reader and keyboard users are first-class users. - Use the `agm_*` wrappers from `.includes/dialog-interface.sh` instead of invoking `dialog` or `yad` directly. Changes must continue to work in both interfaces. - Keep every workflow operable without a mouse. Do not introduce keyboard traps or communicate state only through color, sound, or visual layout. - Do not use `spd-say` or direct Speech Dispatcher calls in graphical interfaces. Expose information through accessible controls and the existing dialog wrappers. - Avoid commands that can stop at an invisible prompt behind a progress box. Supply non-interactive flags and handle failures explicitly. - When changing accessibility behavior, verify the exact affected console and GUI workflow when those environments are available. Automated shell checks do not prove live screen-reader behavior. ## Downloads, URLs, and External State - Treat remote URLs, archive layouts, executable names, and installer behavior as changeable external state. Verify them when working on a download or installer rather than relying on an old report. - Keep reusable IPFS references centralized in `.includes/ipfs.sh` and preserve their explicit `filename` query when the cache filename depends on it. - Never include credentials, private tokens, personal usernames, or live user paths in code, fixtures, logs, or examples. - Do not run destructive installer or removal tests against the real home directory, Wine prefixes, or game data. ## Testing and Verification - For every edited Bash or `.sh` file, run: ```bash bash -n path/to/file.sh shellcheck path/to/file.sh ``` - Fix real ShellCheck findings. A narrow suppression is acceptable for intentionally sourced globals or dynamic source paths when it includes a reason. - Run the smallest relevant test under `tests/`. Tests must use a temporary directory, replace external programs with stubs, and avoid network, GUI, Wine, and real user-state changes. - For UMU helper changes, run: ```bash bash tests/umu_backend_tests.sh ``` - For changes spanning many shell files, syntax-check every changed shell file rather than assuming one successful check covers sourced code. - Before handing work back, run `git diff --check` and inspect `git status --short --untracked-files=all` plus the final diff. - Distinguish automated verification from live acceptance. Installer, Wine, audio, focus, controller, and screen-reader behavior may still require a real installation or launch test. ## Repository Hygiene - Preserve unrelated tracked and untracked work. Do not reset, clean, overwrite, or incorporate files outside the requested scope. - Do not edit generated caches, Wine prefixes, downloaded game data, or logs as source changes. - Keep contributor changes reviewable; avoid unrelated formatting or refactors in installer fixes. - Do not commit, merge, push, or alter remote state unless explicitly requested.