Four documented claims had gone false and were actively misdirecting agents working this repo; the independent reviewer on PR #9 repeated one of them verbatim. Each claim was re-verified against the tree before rewriting. MEMORY.md "Error handling" described C's exit() calls being unwound by a gameEnd panic recovered in Run. Refactor step 8 removed that: gameEnd appears nowhere in the sources, myExit (game/rip.go) restores the terminal via Terminal.Fini and calls os.Exit(0), and Run() has no return values and never returns. The section now states that model and its testing consequence -- a death exits the test binary, which is why tests drive command() directly and crash sweeps pin the hero with fortify() in game/run_test.go. MEMORY.md "Linting" said approved exceptions are recorded in a "Repo-specific exceptions" block in .golangci.yml. There is no such block: the config is byte-identical to canonical (sha256 021cc83f...46bcb) and the approvals live in in-code //nolint directives carrying their dates. Following the old text would have meant editing the canonical config. The same paragraph listed paralleltest as an approved disable when it was fixed instead -- no paralleltest token exists in the tree and all 32 tests call t.Parallel(). MEMORY.md "Debugging" and README.md both told the reader to run go test directly. Since PR #9 the test target carries -timeout 30s -race -cover, so a raw invocation silently drops the race detector while appearing to verify the change. Both now point at make test / make check. TODO.md asserted the host golangci-lint is "currently v2.12.2". It is v2.10.1 and the repo pins nothing, so the claim documented an accident of one machine. Only the false claim is removed; the pin question is tracked separately. Documentation only: no code, Makefile, or config change. Next Step is deliberately not rotated, per the precedent for out-of-band issue work.
2.8 KiB
Project Memory
Working notes for agents on this repo. Read this alongside TODO.md (which holds the step queue and workflow) before starting work.
Error handling
Panicking on bad/unexpected errors is allowed and preferred over threading
unlikely error returns through game code — e.g. write-side Close/encode failures
where continuing would mean corrupt state. Return errors where a caller
genuinely handles them (save-file prompts, restore validation). Reserve
deliberate _ = discards for true best-effort paths (scorefile writes,
signal-time autosave), always with a comment saying why.
C's exit() calls are not unwound: one game run is one process, so myExit (game/rip.go) restores the terminal via Terminal.Fini and calls os.Exit(0), and Run() never returns. There is nothing to recover — do not write code that expects to regain control after game-over. The testing consequence is that any death (combat, starvation, level drain, freezing) exits the test binary, so tests drive command() directly rather than Run(), and crash-sweep drives pin the hero each turn with the fortify() helper in game/run_test.go.
Linting
The .golangci.yml is byte-identical to the canonical shared config and must not be edited — not even to add an exception. To disable a linter, ask sneak, explaining what the linter does; approved exceptions are recorded as in-code //nolint directives (file-level where a whole file is affected) carrying the approval date, which is what keeps the config canonical. Approved so far: testpackage, exhaustive, and mnd (2026-07-07). paralleltest was approved on 2026-07-06 but the exception is no longer in force — it was fixed instead, with t.Parallel() in all 32 tests. The complexity linters (cyclop, gocognit, nestif) are enabled and clean as of refactor step 7 (2026-07-07): the whole golangci-lint run is 0 issues, so keep it that way — decompose new hot spots rather than reaching for a nolint. Line-level //nolint with a reason is used sparingly for C-faithfulness (e.g. the authentic "missle" message spellings) and provably-safe gosec conversions; each needs a justifying comment.
Faithfulness
Behavior must not change during the idiomatic-Go refactor unless a TODO step says so. The 80x24 seed-compatible gameplay, message text (including original typos), RNG call order, and C quirks (documented in tests like TestHoldScrollGreedyMonsterQuirk) are contract. Doc comments keep their "(file.c func_name)" breadcrumbs.
Debugging
Write real, committed test files with t.Logf output and run them with the make
targets — make test (or make check for the full gate); never raw go test.
The target carries -timeout 30s -race -cover and reruns verbosely on failure,
so a raw invocation silently drops the race detector. No throwaway scratch
scripts. Successful debug probes become regression tests.