Skip to content

v0.8 R3-B: complete package-wide strict input adoption and immutable ownership #39

Description

@IvanChernyshov

Parent and dependency

Outcome

Complete the package-wide adoption of the strict validation foundation established in R3-A and make public/frozen value objects own canonical immutable copies of caller-provided data.

This is a feature-free v0.8 correctness and API-hygiene remediation. Preserve current public names, signatures, defaults, valid numerical behavior, the reviewed R3-A native precondition/resource contract, and the frozen R1/R2 scientific and solver contracts.

Approved public contract

Exact integers

Use the shared Python index-protocol validator after explicitly rejecting Python and NumPy Boolean scalars.

Accept Python int, NumPy signed/unsigned integer scalars, and deliberate non-Boolean index-protocol scalars when the destination range permits them. Reject floats, numeric strings, complex values, Booleans, and scalar arrays before lossy conversion.

Apply field-specific positive/non-negative/bounded policies to public IDs, indices, counts, search radii, shifts, iteration counts, and related options. Values stored in signed-int64 public result/observation fields must be checked for representability before conversion.

Exact Booleans and masks

Public Boolean fields accept only Python bool and NumPy bool_; reject integers, strings, and arbitrary truthy/falsy objects.

Mask inputs must be shape-checked and element-validated before Boolean conversion. Retained masks must be owned C-contiguous read-only arrays; mutable algorithm work masks may be made only after validation and copying.

Finite real values and ranges

Reject Boolean, complex, string, NaN, and infinite inputs before downstream numerical work. Apply the documented field-specific positive, non-negative, finite-signed, and interval rules to model parameters, solver options, duplicate/normalization/diagnostic tolerances, remapping epsilons, padding, references, confidences, and related public values.

Do not change R1/R2 formulas or solver semantics while centralizing validation.

Canonical ownership

Frozen/value objects must not change when the caller mutates an input object after construction.

Use:

  • owned nested tuples of built-in floats/booleans for structural domain data;
  • owned C-contiguous read-only NumPy arrays for retained numerical arrays and masks.

At minimum cover domain bounds/periodicity, triclinic vectors/origin, SeparatorObservations, L2Regularization.reference, and other exported frozen values that can retain caller-owned mutable input.

Periodic domains

PeriodicCell must reject left-handed cells at construction (det < 0) rather than failing later. Preserve the existing singular/conditioning policy and warning thresholds. Do not silently flip lattice vectors.

Box.from_points and remapping helpers must validate empty/non-finite data and padding/epsilon before reductions, flooring, or integer conversion.

Scope

  • Reuse and, only where necessary, extend the R3-A private validation helpers.
  • Adopt strict integers, Booleans/masks, finite/range validation, and canonical storage across forward APIs, domains, duplicate-option parsing, normalization/diagnostics, and the separator inverse layer.
  • Replace local integer-parsing logic with the shared contract where applicable.
  • Make retained caller-provided arrays/masks/references owned and read-only.
  • Canonicalize domain structural data to owned Python tuples.
  • Reject left-handed PeriodicCell instances at construction.
  • Validate remapping inputs before floor/cast and reject unrepresentable int64 shifts cleanly.
  • Add mutation, type, NaN/Inf, remapping, domain, forward-option, inverse-model, and compatibility regressions.
  • Complete the integrated R3 gate while preserving the reviewed R3-A native boundary.
  • Update the durable ADR, current docs, API inventory, active remediation record, changelog, and v0.8 release notes.

Implementation tasks

  • Audit remaining public-boundary int(...), bool(...), Boolean/int NumPy coercions, pre-validation casts, non-finite comparisons, and retained mutable aliases.
  • Adopt the shared exact-integer contract for IDs, shifts, indices, counts, search options, and solver/active-set iteration controls.
  • Adopt exact Boolean validation for forward/domain/normalization/diagnostic/inverse flags and masks.
  • Apply field-specific finite/range validation to model, solver, duplicate, normalization, diagnostic, remap, and padding inputs.
  • Canonicalize spatial/planar domain storage and reject left-handed triclinic cells early.
  • Fix Box.from_points and remap validation ordering.
  • Make retained observation/model/reference/mask arrays owned and read-only.
  • Preserve R1/R2 formulas and active-set behavior while validating their public options.
  • Add strict type, finite-value, mutation, domain/remap, and integrated compatibility tests.
  • Add the R3-B ADR and synchronize current documentation.
  • Run the combined R3 closure gate, including the existing R3-A native-boundary tests.

Acceptance criteria

  • No audited public exact-integer field accepts floats, strings, Booleans, or lossy array coercion.
  • Public Boolean fields/masks accept only Python/NumPy Boolean values.
  • NaN and infinities fail early for every audited R3-B numerical field.
  • Box.from_points rejects empty/non-finite inputs before NumPy reductions and validates finite non-negative padding.
  • Remapping rejects non-finite inputs/epsilon and unrepresentable shifts before integer casting, without sentinel values or cast warnings.
  • Frozen/value objects covered by R3-B are unaffected by later mutation of caller inputs.
  • PeriodicCell rejects left-handed cells at construction while preserving existing valid right-handed/conditioning behavior.
  • SeparatorObservations and L2Regularization.reference own their retained numerical data.
  • Existing R3-A native-boundary and resource-precondition tests still pass unchanged.
  • Valid forward and inverse numerical controls remain consistent with the pre-R3-B baseline.
  • No public signature/default/result-schema change, no new mandatory dependency, no vendored edit, and no R1/R2/R4/R5/R6/R7/R8/R9 policy change is introduced.
  • Focused tests, forward/inverse/integration suites, full deterministic tests, relevant fuzz/property tests, lint, compileall, generated-content checks, and strict docs pass.

Mandatory validation

At minimum:

flake8 src tests tools benchmarks examples
python -m compileall -q src tests tools benchmarks examples
git diff --check
focused R3-B strict-type/finite/mutation/domain/remap tests
pytest -q tests/forward/common/test_internal_validation.py
pytest -q tests/forward/common/test_native_boundary_validation.py
pytest -q tests/forward/common/test_native_preconditions.py
pytest -q tests/forward
pytest -q tests/inverse/separator
pytest -q tests/integration
pytest -q tests/forward tests/inverse/separator tests/integration
pytest -q
pytest -m fuzz --fuzz-n 100
python tools/check_notebooks.py
python tools/export_notebooks.py --check
python tools/gen_readme.py --check
mkdocs build --strict

Report exact command completion status, counts, skips, and environment limitations; do not treat a partial or timed-out run as a pass.

Explicit non-goals

  • Changes to R3-A C++ preconditions, resource estimates, or the 1-GiB policy.
  • Any cpp/ or vendored Voro++ modification in the normal R3-B implementation.
  • Certified nearest/minimum-image geometry (R4).
  • Mandatory generator containment or duplicate-safety semantics (R5).
  • Observation/result/report identity redesign (R6).
  • Active-set final-state redesign (R7).
  • Diagnostic severity/ok redesign (R8).
  • Final release/publication synchronization (R9/Qualify and release v0.8.0 #33).
  • Changes to separator objectives, R2 proximal certificates, ADMM algorithms/defaults, public result schemas, new features, or mandatory dependencies.

Stop and escalate

Stop for maintainer review rather than improvising if implementation requires:

  • changing cpp/ or vendor/;
  • redesigning the reviewed R3-A native/resource contract;
  • changing public signatures/defaults/result schemas;
  • resolving an external-ID range contradiction by silently narrowing or widening documented API behavior;
  • changing R1/R2 numerical behavior or certificates;
  • redesigning active-set semantics or diagnostic severity;
  • implementing R4/R5 behavior;
  • adding a mandatory dependency;
  • accepting unexplained valid-result drift.

Required closing evidence

Before closure, record:

  • implementation/review commit or PR reference;
  • exact-integer, Boolean/mask, finite/range, and ownership adoption inventories;
  • mutation-after-construction matrix;
  • domain/remapping/left-handed-cell regressions;
  • R3-A regression status;
  • focused/subsystem/full/fuzz/docs command results;
  • compatibility summary and remaining uncertainty;
  • explicit integrated R3 review verdict.

R3 itself remains open until the independent integrated R3 review accepts the combined R3-A + R3-B implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions