Files
Accessibility ModandClaude Opus 5 c841bcc68d testbed: stop destroying the player's save
The documented way to run the testbed began with

    rm -rf ~/AppData/Roaming/LOVE/Alchemist

which is the player's actual playthrough. It was written down as the
official procedure in four places, so every run of the test suite ate a
real save -- including twice in the session that produced the previous
commit. Reported by Talon.

The testbed does genuinely need an empty save directory: it drives a new
game from the main menu through the prologue, which has already happened
in any real save. So tests/run-testbed.sh MOVES the save aside (never
deletes it), runs, discards the test run's directory and moves the real
one back. Restore is on an EXIT trap plus INT/TERM, so it also happens on
a failed run, a crash and Ctrl-C. If the restore itself fails it says so
loudly and leaves the backup on disk rather than pressing on.

This cannot live inside the mod: love.load calls config.initialize,
keybindings.initialize and user.initialize long before main.lua reaches
require("accessibility").initialize(), so by the time any of our Lua runs
the save directory has already been read. The swap has to happen around
the process.

The rm -rf is removed from all four docs that carried it, each replaced
with the script and the reason not to clear that directory by hand --
being written down as procedure is what made it recur.

accessibility/.gitattributes forces LF on *.sh, or a Windows checkout
hands bash a \r and the script dies. It sits inside accessibility/ on
purpose: a top-level one would show up in the game-file footprint check,
which still reads `main.lua | 1 +`.

Verified with a marker file in a populated save directory: 38 checks, 0
failures, marker intact, no leftover backup directories.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 02:59:34 +02:00

4.4 KiB

CLAUDE.md

What this repository is

A blind-accessibility mod for the commercial game Sulphur Memories: Alchemist 0.4.2 (LÖVE 11.5, Lua/LuaJIT). The work here is accessibility, not game development.

This file ships in two places, so check which one you are in:

  • The development tree — an extracted copy of the game with main.lua and states/ beside accessibility/. Everything outside accessibility/ is the vanilla game: treat it as read-only reference material. You read it to find out how the game works, and you patch it only where the docs sanction.
  • The standalone mod repository (alchemist-accessibility) — only accessibility/ and the docs; no game. You cannot run or test anything here. See README.md for how the two relate. The sections below about running the game and checking the game-file footprint apply to the development tree only.

All mod code lives in accessibility/ either way.

If a request sounds like a game change ("make the journal readable", "the inventory doesn't work"), it almost always means "a screen reader user cannot use this" — the fix belongs in accessibility/, not in states/ or models/.

Read this before doing anything

accessibility/docs/scratch.md — a living handoff document. It carries the current state of play, confirmed decisions that should not be relitigated, the traps that have already cost real debugging time, and what is verified versus merely written. Read it first, and update it before you finish.

accessibility/docs/00-dev-setup.md — how this tree is put together and why: the two-tree arrangement, prerequisites, building a dev tree from scratch, the everyday commands, and how publishing strips the game out. Read it if anything about the setup surprises you.

Then accessibility/docs/README.md maps the rest: architecture, hooking strategy, the phased plan, open questions, decisions.

accessibility/README.md is the user-facing manual — the key bindings the mod adds. Update it when you add or change a key.

Working agreements

  • The user is blind. Every verification must be describable in text. Never rely on a screenshot, and never ask them to check something visually. Console output and testbed transcripts are the evidence.
  • Change as little game code as possible, so the mod re-applies cleanly to new game versions. Currently the entire game-side footprint is one line in main.lua. Check it has not grown:
    git diff --stat vanilla-0.4.2 -- . ':!accessibility' ':!.gitignore' ':!CLAUDE.md'
    
    It must stay main.lua | 1 +. The pristine tree is tagged vanilla-0.4.2.
  • Speech must never throw. A missing DLL degrades to silence; the game keeps running. Wrappers call through to the original and return its results verbatim.
  • Never reveal anything outside FoV / rememberedFoV. The mod must not become a cheat.

accessibility/docs/scratch.md has the full invariant list; these are the ones worth knowing before you write a line.

Verify after any change

lua accessibility/tests/test_history.lua                      # pure Lua, instant
bash accessibility/tests/run-testbed.sh                       # ~4 min

Always use that script — never call lovec . --a11y-test directly, and never rm -rf the save directory. The testbed needs an empty save to drive a fresh playthrough; the script parks the player's real save, runs, and puts it back. Deleting the save by hand destroys a real playthrough.

The testbed drives the real game by code and navigates by reading focus rather than counting keypresses. It has caught essentially every bug in this project, so run it — a change that looks obviously correct is exactly the kind that fails.

What matters is 0 failures, not the check count, which varies between runs because several blocks are conditional.

Use lovec.exe (not love.exe) for a console. Every utterance is mirrored there as a [speech] line, so speech is verifiable from a log rather than only by ear: ! interrupted, * immediate, queued.

If something mysteriously does not speak

Run the game and read the startup self-test. It reports every patch and every descriptor probe. Most menu narration reads the game's file-local variables via debug.getupvalue, so a renamed local in a future game version shows up there as PROBE BROKEN: no upvalue 'x' rather than as silence three screens in. ok (unset until opened) is normal.