Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.

fix(core)!: enforce atomic moves and validated runtime state - #111

Merged
acgetchell merged 2 commits into
mainfrom
fix/91-functional-boundaries-atomic-moves
Jul 20, 2026
Merged

acgetchell merged 2 commits into
mainfrom
fix/91-functional-boundaries-atomic-moves

Conversation

@acgetchell

@acgetchell acgetchell commented Jul 20, 2026 •

Copy link
Copy Markdown
Owner
  • parse CLI options into invariant-bearing values and reject invalid configurations
  • propose topology moves from immutable inputs and publish rebuilt manifolds only on success
  • use owner-safe CGAL snapshots, scope-owned MPFR values, and atomic checkpoint replacement

BREAKING CHANGE: Manifold and FoliatedTriangulation no longer expose mutable triangulations or handle-backed cache containers. Move callbacks now accept const manifolds and return synchronized replacement values. Replace update() with updated(), and use delaunay_snapshot() plus scalar queries for inspection.

Closes #91

Summary by CodeRabbit

  • New Features
    • Added runtime configuration objects that validate triangulation and simulation settings (topology, dimensions, geometric/numeric ranges, cadence, and positivity).
    • Introduced MPFR value helpers for safer precision-controlled calculations.
  • Bug Fixes
    • Improved command-line failure reporting and tightened config/argument error handling.
    • File output is now more robust (atomic temp-file replacement; stronger checks on serialization success).
    • Move handling now preserves the original state when operations are rejected.
  • Documentation
    • Updated contribution/testing guidance to match the 22-test smoke suite.
  • Tests
    • Expanded unit and CLI failure coverage, including validation edge cases and file parsing/output failures.

- parse CLI options into invariant-bearing values and reject invalid configurations
- propose topology moves from immutable inputs and publish rebuilt manifolds only on success
- use owner-safe CGAL snapshots, scope-owned MPFR values, and atomic checkpoint replacement

BREAKING CHANGE: Manifold and FoliatedTriangulation no longer expose mutable triangulations or handle-backed cache containers. Move callbacks now accept const manifolds and return synchronized replacement values. Replace update() with updated(), and use delaunay_snapshot() plus scalar queries for inspection.

Closes #91
@acgetchell acgetchell self-assigned this Jul 20, 2026
@acgetchell
acgetchell enabled auto-merge (squash) July 20, 2026 06:01
@coderabbitai

coderabbitai Bot commented Jul 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR centralizes runtime validation, changes manifold and move operations to snapshot-based value semantics, adds MPFR value helpers, hardens serialization, and expands tests for CLI boundaries, move atomicity, ownership, and exception behavior.

Changes

Validated topology and runtime flow

Layer / File(s) Summary
Runtime configuration and CLI wiring
include/Runtime_config.hpp, src/cdt.cpp, src/initialize.cpp, src/CMakeLists.txt, cmake/ExpectCommandFailure.cmake
Runtime factories validate topology, dimensions, numeric ranges, physical parameters, and simulation cadence before construction; CLI failure tests use a shared CMake helper.
Snapshot-based manifold state
include/Foliated_triangulation.hpp, include/Manifold.hpp, include/Geometry.hpp
Manifold and triangulation state expose owned snapshots, rebuilt values, derived counts, explicit checks, and revised copy/move behavior.
Atomic move execution
include/Apply_move.hpp, include/Move_command.hpp, include/Ergodic_moves_3.hpp, tests/Ergodic_moves_3_test.cpp
Move functions accept const manifolds, modify local Delaunay snapshots, return rebuilt manifolds, and test rejection without source-state changes.
MPFR and action calculations
include/Mpfr_value.hpp, include/S3Action.hpp, include/Metropolis.hpp
Scope-owned MPFR helpers replace manual resource handling, with validation for physical parameters and positive cadence values.
Serialization safeguards
include/Utilities.hpp, tests/Utilities_test.cpp
Writes use guarded temporary files and replacement, while reads reject malformed or trailing input.
API and regression coverage
tests/*
Tests adopt snapshot and count APIs, verify move/swap traits, and cover configuration, ownership, invalid inputs, and failed operations.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant RuntimeConfig
  participant Manifold
  participant Move
  CLI->>RuntimeConfig: Validate CLI parameters
  RuntimeConfig-->>CLI: Return triangulation and simulation config
  CLI->>Manifold: Construct validated universe
  Move->>Manifold: Request Delaunay snapshot
  Move->>Move: Apply move to local triangulation
  Move-->>Manifold: Return rebuilt manifold proposal
Loading

Poem

Snapshots hold the topology tight,
Bad bounds fade before the flight.
MPFR numbers flow with care,
Failed moves leave states still there.
Files swap safely, tests ring true.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the PR’s main changes around atomic moves and validated runtime state.
Linked Issues check ✅ Passed The changes address #91’s requirements: validated CLI config, atomic move paths, snapshot-based mutation, and complete file failure handling.
Out of Scope Changes check ✅ Passed No clear unrelated changes stand out; the added helpers, validation, and test updates all support the stated atomicity and runtime-safety goals.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/91-functional-boundaries-atomic-moves

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@include/Foliated_triangulation.hpp`:
- Around line 1103-1111: Update the empty-source branch of the
FoliatedTriangulation copy constructor to copy m_initial_radius and
m_foliation_spacing from other before returning, while preserving the existing
triangulation-copy path for non-empty sources.

In `@include/Runtime_config.hpp`:
- Around line 189-225: Factor the shared point-count and Int_precision
upper-bound calculation from make_generated_population() and
make_foliated_ball() into a small reusable helper, using
expected_points_per_timeslice() as the common source. Update both entry points
to consume the helper’s bounds result, while retaining make_foliated_ball()’s
per-timeslice loop validation separately.

In `@tests/Vertex_test.cpp`:
- Around line 25-33: Strengthen snapshot_vertices_are_owned instead of checking
only handles sourced from the snapshot. Ensure the test asserts a non-empty
collected vertex set and validates its count against the corresponding
manifold/live triangulation expectation, or otherwise verifies snapshot
independence from the live triangulation. Keep the existing snapshot collection
flow and update the REQUIRE call sites to exercise this meaningful ownership
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 97523a0c-c5c8-4338-87ab-4b22a22e5ca6

📥 Commits

Reviewing files that changed from the base of the PR and between c37fa09 and 71e7dc2.

📒 Files selected for processing (36)
  • .github/CONTRIBUTING.md
  • README.md
  • cmake/ExpectCommandFailure.cmake
  • include/Apply_move.hpp
  • include/Ergodic_moves_3.hpp
  • include/Foliated_triangulation.hpp
  • include/Geometry.hpp
  • include/Manifold.hpp
  • include/Metropolis.hpp
  • include/Move_command.hpp
  • include/Mpfr_value.hpp
  • include/Periodic_3_complex.hpp
  • include/Periodic_3_triangulations.hpp
  • include/Runtime_config.hpp
  • include/S3Action.hpp
  • include/Utilities.hpp
  • src/CMakeLists.txt
  • src/cdt.cpp
  • src/initialize.cpp
  • tests/Apply_move_test.cpp
  • tests/Bistellar_flip_test.cpp
  • tests/CMakeLists.txt
  • tests/Ergodic_moves_3_test.cpp
  • tests/Foliated_triangulation_test.cpp
  • tests/Function_ref_test.cpp
  • tests/Geometry_test.cpp
  • tests/Manifold_test.cpp
  • tests/Metropolis_test.cpp
  • tests/Move_always_test.cpp
  • tests/Move_command_test.cpp
  • tests/Move_tracker_test.cpp
  • tests/Runtime_config_test.cpp
  • tests/S3Action_test.cpp
  • tests/Tetrahedron_test.cpp
  • tests/Utilities_test.cpp
  • tests/Vertex_test.cpp
💤 Files with no reviewable changes (1)
  • tests/Apply_move_test.cpp

Comment thread include/Foliated_triangulation.hpp
Comment thread include/Runtime_config.hpp
Comment thread tests/Vertex_test.cpp Outdated
- use a contiguous spacelike-facet cache so move construction remains noexcept across standard libraries
- centralize generated-population bounds before allocation
- preserve physical parameters in empty copies and strengthen snapshot ownership checks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
tests/Foliated_triangulation_test.cpp (1)

77-81: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for require_nonempty()'s throw path.

The PR adds an explicit rejection of empty Delaunay input (require_nonempty), directly matching the stated objective to "reject configurations that would create an empty triangulation." No test here exercises constructing FoliatedTriangulation_3 from an empty/default Delaunay_t<3> and asserting it throws std::invalid_argument.

Suggested addition near this scenario:

THEN("Constructing from an empty Delaunay triangulation throws.")
{
  REQUIRE_THROWS_AS(FoliatedTriangulation_3{Delaunay_t<3>{}}, std::invalid_argument);
}

Want me to draft the full test case?
As per path instructions: "Comprehensive test coverage and proper test organization."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Foliated_triangulation_test.cpp` around lines 77 - 81, Add a test case
near the existing Delaunay constructibility scenario that constructs
FoliatedTriangulation_3 from a default-empty Delaunay_t<3> and asserts it throws
std::invalid_argument, covering the require_nonempty() rejection path.

Source: Path instructions

include/Foliated_triangulation.hpp (2)

1300-1300: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Naming: is_fixed() mutates state, unlike its is_* siblings.

Every other is_* predicate in this class (is_correct, is_delaunay, is_tds_valid, is_foliated, is_initialized) is a pure, side-effect-free query. is_fixed() swaps a rebuilt replacement into *this when changes are detected — a fix()/try_fix() name would better signal the mutation to callers, reducing the risk of someone treating it as a cheap, non-mutating check.

As per path instructions, this segment falls under: "Focus on design patterns, interfaces, and encapsulation."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@include/Foliated_triangulation.hpp` at line 1300, Rename the mutating
is_fixed() method to fix() or try_fix() so its interface clearly signals that it
may rebuild and replace the current triangulation. Update all declarations,
definitions, and call sites consistently, while leaving the pure is_* predicates
unchanged.

Source: Path instructions


1299-1316: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

is_fixed() may under-fix: fix_timevalues needs to loop, not run once.

fix_timevalues removes vertices whose cells are acausal/unclassified in a single detect-and-remove pass, but removing vertices re-triangulates the local star and can introduce new invalid cells. That's exactly why the free-function make_triangulation() loops fix_timevalues up to MAX_FIX_PASSES (lines 1030‑1037). is_fixed() calls it only once, so a triangulation needing multiple rounds of vertex removal can come back only partially fixed while changed still reports true, and the resulting replacement may still violate is_correct().

🐛 Proposed fix: loop fix_timevalues to convergence
     [[nodiscard]] auto is_fixed() -> bool
     {
       Delaunay   updated{m_triangulation};
       auto const fixed_vertices = foliated_triangulations::fix_vertices<3>(
           updated, m_initial_radius, m_foliation_spacing);
-      auto const fixed_cells = foliated_triangulations::fix_cells<3>(updated);
-      auto const fixed_timeslices =
-          foliated_triangulations::fix_timevalues<3>(updated);
+      bool fixed_timeslices = false;
+      for (auto pass = 0; pass < MAX_FIX_PASSES &&
+                          foliated_triangulations::fix_timevalues<3>(updated);
+           ++pass)
+      {
+        fixed_timeslices = true;
+      }
+      auto const fixed_cells = foliated_triangulations::fix_cells<3>(updated);
       auto const changed = fixed_vertices || fixed_cells || fixed_timeslices;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@include/Foliated_triangulation.hpp` around lines 1299 - 1316, Update
FoliatedTriangulation::is_fixed() so fix_timevalues<3>(updated) runs repeatedly,
matching make_triangulation()’s bounded MAX_FIX_PASSES behavior, until no
further time-value fixes occur or the pass limit is reached. Accumulate whether
any pass changed the triangulation in fixed_timeslices, while preserving the
existing vertex/cell fixes and replacement logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@include/Foliated_triangulation.hpp`:
- Line 1300: Rename the mutating is_fixed() method to fix() or try_fix() so its
interface clearly signals that it may rebuild and replace the current
triangulation. Update all declarations, definitions, and call sites
consistently, while leaving the pure is_* predicates unchanged.
- Around line 1299-1316: Update FoliatedTriangulation::is_fixed() so
fix_timevalues<3>(updated) runs repeatedly, matching make_triangulation()’s
bounded MAX_FIX_PASSES behavior, until no further time-value fixes occur or the
pass limit is reached. Accumulate whether any pass changed the triangulation in
fixed_timeslices, while preserving the existing vertex/cell fixes and
replacement logic.

In `@tests/Foliated_triangulation_test.cpp`:
- Around line 77-81: Add a test case near the existing Delaunay constructibility
scenario that constructs FoliatedTriangulation_3 from a default-empty
Delaunay_t<3> and asserts it throws std::invalid_argument, covering the
require_nonempty() rejection path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 040dab80-a988-4d57-a12e-96ac6ae3dfef

📥 Commits

Reviewing files that changed from the base of the PR and between 71e7dc2 and 1c39596.

📒 Files selected for processing (5)
  • include/Foliated_triangulation.hpp
  • include/Runtime_config.hpp
  • include/Utilities.hpp
  • tests/Foliated_triangulation_test.cpp
  • tests/Vertex_test.cpp

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden CLI boundaries, topology state, and move atomicity

1 participant