# Changelog

## [0.1.2] - 2026-05-24

### Added

- `notrump-tricks` example: histogram of notrump tricks across random
  deals (per-seat, right-sided per pair, and per-deal max). Migrated
  from `pons`, where the only pons-side dependency was `rand` and the
  ddss solver itself.

### Fixed

- Round two of the 0.1.1 stack-overflow fix. `Box::<T>::default()` for
  the multi-hundred-KB FFI packs still routes through a stack temporary
  in unoptimized downstream builds — the std impl boils down to
  `Box::new_uninit() + write(T::default())`, and the `T::default()`
  value lives in the caller's stack frame at opt-level 0. This
  overflowed Windows' 1 MB default thread stack from consumers like
  `pons`'s README doctest. The five `Box::default()` sites in
  `Solver::solve_deal_segment` and `Solver::solve_board_segment` now
  use `Box::new_zeroed().assume_init()`, which allocates the heap slot
  first and zeroes it in place. ddss-sys's bindgen-generated `Default`
  impls for these structs are already `write_bytes(_, 0, 1)`, so the
  behavior is bit-identical.

### Changed

- Removed the `[profile.dev] opt-level = 2` override from `Cargo.toml`.
  After the fix above it was no longer load-bearing for correctness, and
  keeping it would have masked any future regressions of the same shape
  in ddss's own test suite. Local `cargo test` execution is now
  noticeably slower at opt-level 0 (about 3x for the solver tests), but
  on a clean build the wall time is essentially unchanged (the C++ DDS
  sources also compile faster without `-O2`).

### Added

- `batch_solvers_fit_on_one_megabyte_stack` regression test that
  exercises `solve_deals` and `solve_boards` on a worker thread with an
  explicit 1 MB stack — matching Windows' default — so the stack-temp
  bug class is caught on every CI run rather than waiting for a
  Windows-only failure downstream.

## [0.1.1] - 2026-05-23

### Fixed

- `Solver::solve_deal_segment` and `Solver::solve_board_segment` no longer
  construct the multi-kilobyte `ddTableDeals`/`boards` packs on the stack
  before boxing them. They now allocate the box first via `Box::default()`
  and write the field in place, avoiding a stack overflow when called with
  default thread-stack sizes.

### Changed

- Bumped `ddss-sys` to 0.1.1, which fixes the docs.rs build by no longer
  writing `compile_commands.json` outside `OUT_DIR`. As a result, docs.rs
  builds of `ddss` now succeed.
- `tricks::strain_to_sys` is now `pub` (previously `pub(crate)`) so
  downstream code can map a `Strain` to its ddss index without
  reimplementing the table.

## [0.1.0] - 2026-05-23

Initial release. High-level wrapper around [`ddss-sys`](https://crates.io/crates/ddss-sys):

- `Solver` — mutex guard that serializes access to ddss's non-reentrant
  global thread pool, with `lock`, `try_lock`, `solve_deal`, `solve_deals`,
  `solve_board`, `solve_boards`, `analyse_play`, `analyse_plays`.
- `calculate_par`, `calculate_pars` — reentrant par-score helpers that do
  not require a `Solver`.
- `system_info` — wrapper around `GetDDSInfo` with typed accessors for
  version, platform, compiler, threading model, and pool configuration.
- Domain modules `board`, `tricks`, `par`, `play`, `strain_flags`,
  `vulnerability`, `system_info` mirror the layout of
  [`dds-bridge`](https://crates.io/crates/dds-bridge).
- Shared bridge primitives come from
  [`contract-bridge`](https://crates.io/crates/contract-bridge).
- Optional `serde` feature for serialization of all public types.

[0.1.0]: https://github.com/jdh8/ddss/releases/tag/0.1.0
[0.1.1]: https://github.com/jdh8/ddss/releases/tag/0.1.1
