This file is the operational repository guide for AI agents. Detailed design
rationale lives in CONTRIBUTING.md; read the relevant sections there before
changing architecture, public APIs, dependencies, or platform support. For state
or lifecycle changes, read its state and lifecycle
contracts and preserve the
stated Basin 1.x compatibility boundaries.
Basin is a semver-stable Rust numerical-optimization library with a generic
Executor/Solver/State core and support for Vec<f64>, nalgebra, ndarray,
and faer backends.
- Preserve public API compatibility. Treat changes to public signatures, required trait methods, enum variants, generic defaults, feature semantics, and re-exports as potentially breaking. Prefer additive changes and default-bodied trait methods; raise unavoidable breaking changes before implementing them.
- Preserve the default
wasm32-unknown-unknownbuild. Gate file I/O, threads, rayon, and BLAS/LAPACK-linked math behind non-default features. Useweb-timerather thanstd::time::Instantin default paths. - Do not bump the package MSRV casually. Check the current CRAN toolchain before
changing
rust-version. The development toolchain may be newer when a versioned opt-in backend requires it. Every dependency selected by the MSRV-compatible features, including dev dependencies used during publishing and CI, must compile on the MSRV. Document the reason beside any MSRV-driven pin or feature-specific exception.
Run focused tests while developing, then the checks matching the changed scope:
- Rust formatting:
cargo fmt --all -- --check. - Routine pure-Rust tests:
cargo test -p basin --features nalgebra_latest,ndarray_latest,faer_latest,problems,parallel. - Workspace lint:
cargo clippy --workspace --all-targets --all-features -- -D warnings. - Public documentation:
cargo doc --no-deps -p basin --features nalgebra_latest-lapack,ndarray_latest-blas,faer_latest,parallel,problems,serde. - WASM-sensitive changes:
cargo build --target wasm32-unknown-unknownandcargo build --target wasm32-unknown-unknown --no-default-features. - Web changes, from
web/:pnpm format:check,pnpm lint,pnpm check, andpnpm build.
Do not assume cargo test --all-features links without a BLAS/LAPACK provider.
The nalgebra-lapack and ndarray-blas features intentionally select no
provider. Supply one through linker flags when those tests are required; clippy
and rustdoc only check and do not link. The package MSRV is Rust 1.87.0; CI
checks it separately. The dev environment pins Rust 1.89.0, supplies the WASM
target and project tooling, and runs all-feature clippy and rustfmt in
pre-commit.
crates/basin/src/lib.rsdefines the documented public surface through module declarations and re-exports.crates/basin/src/core/problem.rsdefines user-implemented cost, gradient, residual, Jacobian, and Hessian traits;crates/basin/src/core/numdiff.rsprovides finite differences.crates/basin/src/core/state.rsandcrates/basin/src/core/state/defineState, concrete states, and the minimum-shape extension traits used by convergence checks and run controls.crates/basin/src/core/solver.rsdefinesSolver;crates/basin/src/core/executor.rsowns the driver loop; andcrates/basin/src/core/convergence.rsshares solver convergence checks;crates/basin/src/core/run_control.rsowns execution limits and hooks; andcrates/basin/src/core/termination.rsretains the deprecated 1.x facility.- Problem-side constraints and adapters live under
crates/basin/src/core/inconstraint.rs,barrier.rs, andaugmented_lagrangian.rs; composition contracts live ininner.rs. crates/basin/src/core/math.rsandcrates/basin/src/core/math/implement the tiered backend layer.crates/basin/src/solver.rsandcrates/basin/src/solver/contain concrete solvers;crates/basin/src/core/rng.rssupports stochastic algorithms.
Use src/foo.rs plus src/foo/bar.rs; never introduce mod.rs.
The root workspace contains crates/basin, crates/basin-wasm, and
crates/competitor-bench. web/ is a separate Svelte project. Keep optional
backend, parallel, and problem integrations as features on basin. Add a
workspace crate only for heavy or platform-specific dependencies that do not
belong in the core crate.
- Preserve conventional optimization-framework vocabulary and the generic driver-loop shape unless another constraint requires divergence.
- Each supported backend release has an exact version feature. The
*_latestaliases move to the newest supported release, while the original unversioned features retain their Basin 1.x meanings. If dependency feature unification enables several releases of one backend, implement the newest enabled release. - Numerical convergence settings belong on the solver, with one owner per
test and shared internal calculations. Execution budgets, targets, stalls,
cancellation, and application stops belong to the executor. Bind optional
checks to the minimum state shape and backend capabilities they need. Use
explicit
with_absolute_*_tolerance/with_relative_*_tolerancenames where applicable;Nonedisables optional checks and zero means exact-zero. Keep algorithm controls distinct and preserve deprecated 1.x behavior until its scheduled removal in Basin 2.0. - Constraints describe problems: keep them problem-side, never on state or as executor configuration. Solvers declare supported constraint traits; projection, barrier, and penalty adapters are explicit opt-ins.
- Keep the universal vector math tier small and the richer linear-algebra tier capability-based. Missing operations must fail at compile time.
Public types that store or expose scalar-valued state should use F: Scalar
with an F = f64 default. Carry that generic through state, solver,
termination, and math implementations when the surface requires it; do not add
a scalar parameter to a type that does not need one. Preserve the f32
round-trip coverage in crates/basin/tests/f32_round_trip.rs.
- Add a regression test for behavioral fixes and analytic or reference checks for new numerical algorithms. Use deterministic seeds in stochastic tests, scale-appropriate approximate comparisons, and explicit coverage of relevant degenerate or non-finite inputs.
- New vector-based solvers must support all four dense backends (
Vec, nalgebra, ndarray, and faer), with tests for bothf32andf64on each. Scalar algorithms do not require a linear-algebra backend. - Test every backend claimed in public rustdoc. Every solver rustdoc must include
a
# Backendsnote listing supported parameter types. - Keep shared vector traits limited to operations every backend implements well. First-order and derivative-free solvers should remain generic over this tier.
- Put richer matrix operations in
crates/basin/src/core/math/linalg.rs. Linear-algebra-heavy solvers must bound only the capabilities they need. - Add backend operations only when they can be implemented honestly in pure Rust and without a BLAS/LAPACK link or fake stub. Implement any missing dense capabilities as part of the new solver. Sparse support is optional and must be documented separately.
For a new corpus problem, use the add_test_problem project subagent. Its
instructions in .codex/agents/add-test-problem.toml own the full file layout,
metadata, backend, testing, visualizer, and verification workflow. Add exactly
one problem per task; do not replace symbolic production gradients with finite
differences or omit a supported backend.
The static SvelteKit site at https://basin.rs/ signposts to the authoritative
docs.rs API rather than copying it. When a top-level section is added, removed,
or renamed, update the hand-maintained web/src/routes/llms.txt/+server.ts;
keep it a link-oriented signpost with absolute SITE_ORIGIN URLs and trailing
slashes. The sitemap discovers pages automatically.
When a solver is added, removed, renamed, or changes backend support or
references, update web/src/routes/docs/solvers/+page.svx in the same change:
- The prose catalogue must equal the public solver re-exports in
crates/basin/src/lib.rs. - Keep backend caveats beside the relevant solver entry and consistent with
its rustdoc
# Backendssection, including requirements imposed by custom inner solvers or strategies. - Each bullet must link to docs.rs and reproduce the solver rustdoc reference.
Canonical docs.rs links include the defining snake-case submodule:
https://docs.rs/basin/latest/basin/solver/<module>/struct.<Name>.html or the
equivalent line_search/<module>/.... Root-module struct links fail. Aliases
link to the defining type—for example, both Lbfgs and Lbfgsb link to
solver/lbfgs/struct.Lbfgs.html. A new solver may legitimately be absent from
/latest/ until the next release.