Skip to content

feat(cli): annotate PBN trees in place, and only where analysis is missing - #8

Merged
Rick-Wilson merged 4 commits into
mainfrom
feat/pbn-annotate-in-place
Aug 22, 2026
Merged

feat(cli): annotate PBN trees in place, and only where analysis is missing#8
Rick-Wilson merged 4 commits into
mainfrom
feat/pbn-annotate-in-place

Conversation

@Rick-Wilson

Copy link
Copy Markdown
Collaborator

The binary could already write Bridge Composer compatible DD and par tags, but only one file at a time, always recomputing, and it fabricated results for boards that have no deal. A build could not simply point it at a collection. Now it can:

bridge-solver -w -i Curated/        # fill in what's missing, recursively

Skip incomplete deals (bug fix)

A board written as [Deal "N:... ... ... ..."] — Bridge Composer's form for an auction-only teaching board — parses successfully into empty hands, so it was solved and stamped with an all-zero table plus [OptimumScore "NS 0"] and [ParContract "NS Pass"]. On one real lesson file that produced 19 annotated boards where only 6 were analyzable.

Hands::is_complete() now gates the pass; such boards are left untouched.

Fill in only what is missing

A board that already carries [DoubleDummyTricks] is passed through byte-for-byte. --recalculate redoes those. A stray par tag without a DD table does not count as analyzed, so it still gets filled in and the orphaned value replaced.

Several inputs, directories, in place

-i takes multiple paths; directories are searched recursively for *.pbn. -w/--in-place rewrites them. Unchanged files are not rewritten, so a re-run touches nothing and mtimes do not churn; in-place writes go through a temporary file and a rename. Naming more than one file without --in-place is an error rather than a surprise.

Verification

Against Bridge Composer's own output — 25 files it had already analyzed — all 102 distinct DoubleDummyTricks values were reproduced exactly, zero mismatches. That covers the full hex range (11- and 12-trick cells) and boards where the N and S groups differ, which is what would expose a wrong declarer or strain ordering.

Annotating a 63-file, 828-deal collection in one command:

deals annotated 828 / 828
all-zero tables 0
lines removed 0 (purely additive)
leftover temp files 0
second run 0 of 63 files updated

39 tests pass (--features cli --lib --bins), fmt and clippy clean, verified under dev-build.sh --ci.

Version bumped 0.4.0 → 0.5.0.

🤖 Generated with Claude Code

Rick-Wilson and others added 4 commits August 22, 2026 06:38
…ssing

The binary could already write Bridge Composer compatible DD and par tags,
but only one file at a time, always recomputing, and it fabricated results
for boards that have no deal. A build could not simply point it at a
collection. Now it can.

Skip incomplete deals. A board written as [Deal "N:... ... ... ..."] — Bridge
Composer's form for an auction-only teaching board — parses successfully into
empty hands, so it was solved and stamped with an all-zero table plus
[OptimumScore "NS 0"] and [ParContract "NS Pass"]. On one real lesson file
that produced 19 annotated boards where 6 were analyzable. Hands::is_complete
now gates the pass and such boards are left untouched.

Fill in only what is missing. A board that already carries [DoubleDummyTricks]
is passed through byte-for-byte; --recalculate redoes those. A stray par tag
without a DD table does not count as analyzed, so it still gets filled in and
the orphaned value replaced.

Accept several inputs, and directories, searched recursively for *.pbn, with
--in-place to rewrite them. Unchanged files are not rewritten, so a re-run
touches nothing and mtimes do not churn; in-place writes go through a
temporary file and a rename. Naming more than one file without --in-place is
an error rather than a surprise.

Verified against Bridge Composer's own output: across 25 files it had already
analyzed, all 102 distinct DoubleDummyTricks values were reproduced exactly.
Annotating a 63-file, 828-deal collection in one command added analysis to
every deal, produced no all-zero tables, removed no lines, and the second run
updated nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A newer stable clippy added `manual_isolate_lowest_one`, which flags
`m & m.wrapping_neg()` in pack_bits/unpack_bits and turns CI's Lint job red on
main. Its suggested `isolate_lowest_one()` is still unstable, so adopting it
would raise this crate's minimum Rust version for no gain in a hot path.
Suppress the lint locally instead, paired with `unknown_lints` so compilers
predating it stay quiet about the allow itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sets bit 0x00080000 ("double-dummy data has been verified") in each annotated
board's [BCFlags], adding the tag if the board has none and preserving every
bit already present.

This records provenance only. No documented BCFlags bit controls whether the
DD table is displayed, and Bridge Composer does not set this one itself: across
388 boards in files where it had written DoubleDummyTricks, the bit was set
zero times, and the flag values there (1f, 17, df, 40001f) are indistinguishable
from files with no analysis at all. The flag is therefore off by default and
documented for what it does rather than what it might be assumed to do.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The example uses `analyse_play`, which is gated behind `play-analysis`, but
unlike bench_fixtures beside it, it had no [[example]] block. Auto-discovered
with no required-features, it failed to compile under CI's featureless
`clippy --workspace --all-targets` pass and turned Lint red on main. Declare it
the same way its sibling is declared, so the pass skips it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Rick-Wilson
Rick-Wilson merged commit 1f334bc into main Aug 22, 2026
7 checks passed
@Rick-Wilson
Rick-Wilson deleted the feat/pbn-annotate-in-place branch August 22, 2026 13:52
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