Safe to embed — a Result-clean library surface under a stated compatibility contract
The #295 shell-boundary cut made the engine consumable as a library, and the first downstream research project pins it as a cargo git dependency (surveyed in #295, recorded in #296). Three finishing moves on that surface. #296: record the compatibility contract for the public library surface — even if the recorded answer is "no stability promised before 1.0; downstream pins a commit", the policy is then written rather than implicit, and it classifies whether the churn below counts as breaking. #297: convert the ~20 remaining std::process::exit refusal sites in the runner's single-run paths to RunnerError propagation (as reproduce.rs already models), so an embedding caller gets a Result instead of a killed host process; shell dispatch keeps byte-identical stderr text and exit codes, already pinned by the E2E suites. #299: the reproduce API returns the per-member report on the simple path and derives the DataSource from the stored manifest by default, refusing loudly on pip/window mismatch instead of reporting a spurious determinism divergence.
Done: no library code path exits the host process, reproduce is honest on its simple path, and the compatibility contract is a recorded ledger fact.