The mod is 63 files; the tree it lives in is 1838 files of a commercial game and 296 MB of history. Publishing therefore means stripping, and stripping by hand is exactly the sort of thing that quietly leaks a build of the game. accessibility/publish/publish.sh rebuilds the standalone repository from this tree with git-filter-repo, then asserts that no path outside accessibility/ and the docs survived, and aborts rather than pushing if one did. The publish-only files live in accessibility/publish/ rather than at the root so that the game-file footprint check stays a clean "main.lua | 1 +", and the filter renames them to the root where a visitor to the mod repo expects them. The script then drops the publish machinery itself, which means nothing to someone installing the mod. README.md is the install guide: copy accessibility/ into an extracted game folder and add the one line to main.lua, which install.patch also applies. CLAUDE.md now states which of the two repos the reader is in, since half of it (running the game, the footprint check) is meaningless without the game present. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
85 lines
3.9 KiB
Markdown
85 lines
3.9 KiB
Markdown
# 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.**
|
|
|
|
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
|
|
rm -rf ~/AppData/Roaming/LOVE/Alchemist # clean save
|
|
"C:/Program Files/LOVE/lovec.exe" . --a11y-test # ~4 min
|
|
```
|
|
|
|
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.
|