Skip to content

Give the terms argument a test surface, and read a suite once - #260

Merged
aywrite merged 3 commits into
masterfrom
arch/instruments-seam
Sep 16, 2026
Merged

aywrite merged 3 commits into
masterfrom
arch/instruments-seam

Conversation

@aywrite

@aywrite aywrite commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner

Three changes to the command line side of the instruments. None touches a
searched tree, so no bench moves and there is no Bench: trailer.

Pin what a terms argument takes and how it refuses. terms was the only
one of the five instruments with no test over what it reads. Its settings
reader was called by nothing but the one-line smoke assertion in the usage
test, no test ever named it a suite file, and the refusal table in
tests/uci_session.rs covered the other four while its own comment said it
asked this of each command that takes settings.

It now has three settings tests, and the table has a terms row so the
comment is true.

Check: dropping TERMS.claim(params)? from term_settings leaves every test
passing before this commit and fails an_unreadable_terms_setting_is_named_rather_than_run
after it.

Read an instrument's suite in one place. The residual sampler, the
reduction ledger and the term extraction each took a suite and each read it
with the same five lines written out again. suite is that reading once,
beside the read_epd it calls. The cutoffs argument is left out because it
takes no suite. The refusal each argument gives for a line with more than one
bad word was compared on fifteen lines against master and is identical.

Check: a suite that swallows the refusal fails the no-suite test on all
three arguments.

Name a suite the bench does not use when checking one is read. The
residuals and reductions tests of a named suite named bench.epd and then
compared against bench::positions(), which is the same file. A reader that
checked the named file and handed back the bench's own positions passed both.
They now name tactics.epd. Each also gains a file that opens and holds no
position, which read_epd refused and nothing tested.

Check: both of those mutations fail these tests after the commit and did not
before it.

Verified with cargo test --workspace --release and cargo test --workspace
at the tip, the release suite at each commit on its own, cargo fmt --all -- --check, and clippy (the only warning is the pre-existing const-evaluation
one from the magic tables).

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Speed against 9e4bb4c3

Both sides built and run on this runner in this job, the way
scripts/speed.sh measures a perf commit. The change is between
medians, and the spread beside it is what the change has to be
read against. The node counts are the search's: they move when
the search does, and a speed change leaves them alone.

round     base nps  candidate nps
    1     10823855       10832128
    2     10964030       10857845
    3     10861777       10885247
    4     10959806       10824248
    5     10992876       10848590
    6     10937869       10920580
    7     10926193       10931132
    8     10924650       10837407
    9     10922245       10848681

             nodes    time  median nps  fastest nps
base       3868987  0.35 s    10926193     10992876
candidate  3868987  0.36 s    10848681     10931132
change                           -0.7%        -0.6%

the change is inside the spread, so the medians make no claim; the
fastest column is the steadier comparison when the machine was not
quiet

Speed: -0.7% (bench nps, 9 interleaved rounds vs 9e4bb4c3, spread 1.5%)

aywrite and others added 3 commits September 16, 2026 19:06
The terms argument was the only one of the five with no test over what it
reads. Nothing called its settings reader but the one line in the usage
test, no test named it a suite file, and the refusal table every measuring
tool leans on named the other four.

It gains three tests. The suite is the bench's own unless the line names a
file, and a named file is checked against tactics.epd rather than the bench's
own, so a reader that ignored the name could not pass. A file that is no
suite is named rather than walked, on three readings: it will not open, it
holds a position no board will take, and it holds no position at all. The
last is written to the temp directory for the test, since nothing checked in
is one. And a word the argument does not know is refused, which is the
refusal only this one can make: it runs no search, so a number where the
depth would be is a word rather than a depth.

The table in tests/uci_session.rs gains a terms row, so its own comment
about asking this of each command that takes settings is now true.

Checked by mutation. Dropping the claim from term_settings leaves every
test passing before this commit and fails the third of these after it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The residual sampler, the reduction ledger and the term extraction each take
a suite, and each read it with the same five lines written out again. The
reading is two decisions rather than one: the path is kept because the
report's header states it, and the positions are read while the settings are
so that a file which is no suite is refused before the minutes are spent. Two
decisions written three times can come apart on one of the three without the
other two saying anything.

`suite` is that reading, once, beside the `read_epd` it calls. The cutoffs
argument is left out because it takes no suite, which is a difference the
declaration already states and this does not hide.

Checked by mutation. A `suite` that swallows the refusal fails the no-suite
test on all three arguments, which is what the one copy has to keep true.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The residuals and reductions arguments each have a test that the suite a
line names is the suite the settings hold. Both named arche-core/bench.epd
and then asserted the positions equalled bench::positions(), which is the
same file. A reader that opened the named file, checked it, and handed back
the bench's own positions passed both. With the suite now read in one place
that reader would be wrong for all three arguments at once.

Both now name tactics.epd and hold the positions against that file, and
against the bench's as well, so the two cannot be mistaken for each other.

Each also gains the third way a file can fail to be a suite. A file that
opens and holds no position was refused by read_epd and tested by nothing.
Nothing checked in is one, so the test writes it to the temp directory and
removes it when done.

Checked by mutation. Returning the bench's positions after checking the
named file, and dropping the empty check from read_epd, each left both of
these tests passing before this commit and fail them after it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@aywrite
aywrite force-pushed the arch/instruments-seam branch from 2c92f14 to 94e03c8 Compare September 16, 2026 09:09
@aywrite

aywrite commented Sep 16, 2026 •

Copy link
Copy Markdown
Owner Author

Review round 1, folded as 5ebfb37, 9c69dac and 94e03c8 (previously 46307a5 and 2c92f14).

Seventeen mutations to src/instruments.rs, src/main.rs and src/uci.rs, each run against the whole release suite with nothing else touching the tree.

mutation before the round after
A suite swallows the refusal caught (4) caught (4)
B suite drops the path caught (3) caught (3)
C term_settings without the claim caught (1) caught (1)
D term_settings claims after the suite caught (1) caught (1)
E residuals reads the suite before taint survives survives
F reductions reads the suite before sampling survives survives
G read_epd drops the empty check survives caught (3)
H read_epd drops the fen check caught (3) caught (3)
I suite keeps the first position only caught (3) caught (3)
J TERMS takes a depth caught (1) caught (1)
K the terms arm removed caught (1) caught (1)
L the terms refusal names another command caught (1) caught (1)
M the refusal printed on stdout caught (1) caught (1)
N the refusal exits 0 caught (1) caught (1)
O the bench claims before the depth survives survives
P the bench ignores taint caught (1) caught (1)
Q suite checks the named file, then returns the bench's own survives caught (3)

Q was the finding. Every test that a named suite is read named bench.epd and compared against bench::positions(), the same file, so a reader that ignored the name passed. The new terms test had copied the pattern. Fixed in the terms commit for its own test and in a separate commit for the residuals and reductions tests, which predate this change. G was the same gap one step down: read_epd refuses a file holding no position and nothing tested it.

E, F and O are left. Each reorders the settings a reader checks, which changes which refusal a line with two bad words reports. The fold did not reorder anything: fifteen such lines give byte-identical refusals on master and on this branch. Pinning an order nobody has asked to keep is a separate decision, with one exception worth naming. O moves the bench's claim ahead of its depth, and that order is one the code states a reason for (claim last, so a word read as the depth is refused under the better name). It is observable: bench evrey 50 reports depth: evrey as committed and word: 50 with the claim first. No test holds it. That predates this change and is left for a change of its own.

One gap stays out of reach: NO_AUDIT_MEMORY on the binary path. Reaching it needs the table to allocate and the audit keys not to, and the hash range the uci option advertises gives no size that does one without the other.

@aywrite
aywrite merged commit 6f3de04 into master Sep 16, 2026
20 checks passed
@aywrite
aywrite deleted the arch/instruments-seam branch September 16, 2026 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant