diff options
| author | Scott Gasch <[email protected]> | 2026-10-15 14:43:17 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-15 14:43:17 -0700 |
| commit | ac7572166bd24868fcaf5980a91bb82fe61ba677 (patch) | |
| tree | 8c583c3c631690e752d62bff674733358b48d1e2 /src/CLAUDE.md | |
| parent | 993b6eeb2a9ac7b659c473b6883fa53af1ad3a0b (diff) | |
NNUE accumulator struct scaffolding; fix 3 bugs found by DEBUG+TEST; add that gate
Partial checkpoint on the nnue-accumulator-plumbing branch, before the
MakeMove/UnmakeMove hookup itself:
- chess.h: NNUE_ACCUMULATOR struct (256 floats, pre-activation, float32
for now -- quantization to int16 deliberately deferred until a real
quantization-aware export pass exists, per docs/NNUE.md). Added the
live, always-current SEARCHER_THREAD_CONTEXT.sNnueAccum[2] (one per
color) and PLY_INFO.sNnueAccumBackup (the king-move full-recompute
backup slot, DEBUG-only color tag declared for a later ASSERT).
LIGHTWEIGHT_SEARCHER_CONTEXT also mirrors sNnueAccum[2] at the same
relative position -- omitting that broke its byte-compatible-prefix
contract with the full context the moment MakeMove/UnmakeMove will
start touching it unconditionally (caught by this session's own
TestSan self-test failure).
- Combining DEBUG=1 and TEST=1 for the first time (apparently ever)
while chasing that failure immediately turned up three more real,
pre-existing bugs, all in self-test-only code whose assert-guarded
invariants had never been checked with asserts actually compiled in:
- board.c: IsBoardLegal now rejects an en passant square whose rank
doesn't match the side to move (and verifies the double-moved
pawn/empty origin square), closing a gap VALID_EP_SQUARE alone
can't catch.
- testgenerate.c: TestCapturesAndPromotionsGenerator's fixture table
had a self-contradictory FEN this new IsBoardLegal check would
have caught; replaced with a genuine Black-to-move en passant
position.
- testgenerate.c: TestFindUnblockedSquaresSpeed called
_GenerateAllMoves directly instead of the GenerateMoves wrapper,
skipping the DEBUG-only pStack->board[uPly] snapshot
WouldGiveCheck's own ASSERT checks against.
- precommit_check.sh / CLAUDE.md: added the DEBUG=1 TEST=1 combination
as a permanent third pre-commit gate, given what its first-ever run
turned up. Real cost (~235s of ~266s total, unoptimized build
dominates), judged worth it.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/CLAUDE.md')
| -rw-r--r-- | src/CLAUDE.md | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/CLAUDE.md b/src/CLAUDE.md index f2bbd37..c8e9c08 100644 --- a/src/CLAUDE.md +++ b/src/CLAUDE.md @@ -42,9 +42,9 @@ object mismatches at link time. ## Pre-commit testing -Two cheap, complementary gates exist and should both be run before +Three cheap, complementary gates exist and should all be run before committing a search/eval/move-generation change (not needed for pure -doc/comment-only changes). Neither replaces the curated-suite/`sd`-`sn` +doc/comment-only changes). None of these replace the curated-suite/`sd`-`sn` comparison workflow below -- these catch outright bugs (crashes, broken invariants) fast; the suite workflow measures whether a change is actually *better*, which is a slower, separate question. @@ -61,7 +61,28 @@ invariants) fast; the suite workflow measures whether a change is actually original-2004-era and untouched since, but `testeval.c`/`testsearch.c`/ `testsee.c` have been actively edited by recent sessions -- this is a live, working harness, not dead code, despite living outside the normal - build profile. + build profile. **Note this profile has no `DEBUG`, so every `ASSERT` in + these test files is a silent no-op** -- see the next gate. +- **`gmake DEBUG=1 TEST=1` combined self-test.** Same self-test suite as + above, but with asserts actually compiled in. Added 2026-10-15 after + running this exact combination for the first time (ever, as far as + anyone could tell) immediately turned up three real, previously- + undiscovered bugs in one run -- none in production code, all in + self-test-harness code whose assert-guarded invariants had apparently + never been checked with asserts live: (1) `testgenerate.c`'s + `TestCapturesAndPromotionsGenerator` fixture table had a + self-contradictory hand-built FEN (en passant square on rank 6 paired + with Black to move -- only reachable with White to move; see `board.c`'s + `IsBoardLegal`, which now rejects this same mistake if it ever arrives + via `setboard`); (2) same file's `TestFindUnblockedSquaresSpeed` called + `_GenerateAllMoves` directly instead of the `GenerateMoves` wrapper, + skipping the DEBUG-only `pStack->board[uPly]` snapshot + `WouldGiveCheck`'s own `ASSERT(PositionsAreEquivalent(...))` checks + against. Budget real time for this step -- it's unoptimized (`DEBUG` + implies no `-O3`), so it dominates `precommit_check.sh`'s total runtime + (measured ~235s of ~266s total on this box, vs. ~16s for the plain + `TEST=1` gate) -- but kept anyway: the bug-catching rate on its first + ever run made the cost clearly worth it. - **`debug_smoke_test.sh [binary] [depth] [count]`** (defaults: `./_typhoon`, `sd 4`, 10 positions). Builds/runs a `DEBUG=1` binary (asserts compiled in) against a fresh random sample of positions drawn from the full @@ -79,11 +100,13 @@ invariants) fast; the suite workflow measures whether a change is actually flushes the logfile every call) before triggering the `int3` breakpoint, so that text survives in the logfile even if stdout capture is lost to an abrupt `SIGTRAP` death. -- **`precommit_check.sh`** runs both gates back-to-back and restores a +- **`precommit_check.sh`** runs all three gates back-to-back and restores a normal release build afterward (`gmake clean` + the standard `GENETIC=1 PERF_COUNTERS=1 MP=1 SIXTYFOUR=1` profile), so the working directory isn't left with a `TEST`/`DEBUG`-flavored binary as a side - effect of running it. ~20s end to end on this box. + effect of running it. **~266s (~4.5min) end to end on this box** as of + adding the combined DEBUG+TEST gate (was ~20s with just the two original + gates) -- almost all of the increase is that one unoptimized step. **On not making this an automatic git pre-commit hook**: deliberately not wired up that way. Two concrns pushed toward manual-by-default: (1) each |
