summaryrefslogtreecommitdiff
path: root/src/CLAUDE.md
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-15 14:43:17 -0700
committerScott Gasch <[email protected]>2026-10-15 14:43:17 -0700
commitac7572166bd24868fcaf5980a91bb82fe61ba677 (patch)
tree8c583c3c631690e752d62bff674733358b48d1e2 /src/CLAUDE.md
parent993b6eeb2a9ac7b659c473b6883fa53af1ad3a0b (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.md33
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