Skip to content

feat(api)!: add Pachner feasibility checks#489

Merged
acgetchell merged 2 commits into
mainfrom
feature/419-pachner-feasibility
Jul 2, 2026
Merged

feat(api)!: add Pachner feasibility checks#489
acgetchell merged 2 commits into
mainfrom
feature/419-pachner-feasibility

Conversation

@acgetchell

Copy link
Copy Markdown
Owner
  • Add immutable flip and Pachner feasibility reports for dry-run workflows.
  • Route Pachner feasibility through the shared bistellar preflight used by mutating flips.
  • Export Pachner feasibility from the focused Pachner prelude.

BREAKING CHANGE: External BistellarFlips implementors must add the new can_flip_* feasibility methods.

Closes #419

- Add immutable flip and Pachner feasibility reports for dry-run workflows.
- Route Pachner feasibility through the shared bistellar preflight used by mutating flips.
- Export Pachner feasibility from the focused Pachner prelude.

BREAKING CHANGE: External BistellarFlips implementors must add the new can_flip_* feasibility methods.

Closes #419
@acgetchell acgetchell self-assigned this Jul 2, 2026
@acgetchell acgetchell enabled auto-merge (squash) July 2, 2026 09:11
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds immutable flip-feasibility validation to bistellar flips, introduces topology-owner provenance, and replaces direct Pachner mutation with a staged proposal-and-attempt workflow. Downstream docs, examples, benchmarks, and tests are updated to use and verify the new APIs.

Changes

Pachner feasibility and provenance workflow

Layer / File(s) Summary
Flip preflight and feasibility
src/core/algorithms/flips.rs
Adds shared flip preparation, immutable feasibility validators, new flip error kinds, and core tests around feasibility and rejection cases.
Topology owner provenance
src/core/tds/storage.rs, src/core/triangulation.rs, src/delaunay/triangulation.rs, src/lib.rs
Adds runtime topology-owner identity types and forwards them through the triangulation surfaces and public re-exports.
Proposal-based Pachner API
src/delaunay/pachner.rs, src/delaunay/flips.rs, src/lib.rs
Replaces direct Pachner mutation with proposals, adds feasibility reporting on proposals, and exposes the new trait surface and prelude exports.
Docs, examples, and benchmark updates
docs/*, examples/*, benches/pachner_stress.rs
Updates API docs, workflow docs, examples, and the benchmark harness to use propose_pachner(...).attempt_on(...).
Roundtrip and export coverage
tests/pachner_roundtrip.rs, tests/prelude_exports.rs
Expands tests for feasibility agreement, stale/provenance failures, topology-owner checks, and prelude export coverage.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Suggested labels: enhancement, rust, breaking change, geometry, api, topology

Poem

A rabbit peeks before the hop,
checks every flip from bottom to top 🐇
Proposals first, then gentle glide,
with topology kept safely tied.
Dry runs hum, mutations sing—
precise little hops, delightful thing!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning docs/roadmap.md and docs/limitations.md add unrelated toolchain and concurrency planning updates beyond #419. Remove the unrelated roadmap and limitations edits, or split them into a separate PR focused on feasibility APIs.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding Pachner feasibility checks.
Description check ✅ Passed The description matches the staged feasibility and Pachner API changes in the diff.
Linked Issues check ✅ Passed The PR adds immutable flip validators, API exports, provenance checks, docs, and tests that match #419.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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 feature/419-pachner-feasibility

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

@coderabbitai coderabbitai Bot added api breaking change enhancement New feature or request geometry Geometry-related issues rust Pull requests that update rust code topology labels Jul 2, 2026
@codacy-production

codacy-production Bot commented Jul 2, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 99 complexity

Metric Results
Complexity 99

View in Codacy

🟢 Coverage 90.91% diff coverage · +0.01% coverage variation

Metric Results
Coverage variation +0.01% coverage variation (-1.00%)
Diff coverage 90.91% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (abd466f) 76956 70043 91.02%
Head commit (1cb06d8) 77334 (+378) 70395 (+352) 91.03% (+0.01%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#489) 429 390 90.91%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/pachner_roundtrip.rs (1)

603-649: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Reuse assert_topology_and_delaunay_valid to close a Delaunay-invariant coverage gap.

This generic D=2..5 smoke test only calls validate() and is_valid_embedding() after the mutation, but skips is_valid_delaunay(), unlike assert_topology_and_delaunay_valid (lines 66-78) used by the 2D toroidal test. Since this is the only test exercising K1Insert across D=2..5, a Delaunay-property regression in higher dimensions specifically would go undetected here.

♻️ Proposed fix
-    trial
-        .as_triangulation()
-        .validate()
-        .unwrap_or_else(|err| panic!("{D}D k=1 mutation should preserve topology: {err}"));
-    trial
-        .as_triangulation()
-        .is_valid_embedding()
-        .unwrap_or_else(|err| panic!("{D}D k=1 mutation should preserve embedding: {err}"));
+    assert_topology_and_delaunay_valid(&trial, &format!("{D}D k=1 mutation"));
🤖 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/pachner_roundtrip.rs` around lines 603 - 649, The generic K1Insert
smoke test in assert_public_k1_insert_feasibility_smoke only checks topology and
embedding after mutation, leaving the Delaunay invariant unverified. Update this
test to reuse assert_topology_and_delaunay_valid for the post-mutation
assertions, or add the same is_valid_delaunay check alongside validate() and
is_valid_embedding(). Keep the existing feasibility/mutation flow and ensure the
postcondition coverage matches the 2D toroidal test.

Source: Coding guidelines

🤖 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 `@tests/pachner_roundtrip.rs`:
- Around line 317-355: Add the missing parity assertion for the toroidal
K1Insert roundtrip test so it checks `result.removed_face_vertices` against
`feasibility.removed_face_vertices` just like
`assert_public_k1_insert_feasibility_smoke` does. Update
`pachner_feasibility_agrees_with_toroidal_2d_k1_insert` to compare this field
alongside `kind`, `direction`, `removed_simplices`, and `inserted_face_vertices`
to fully verify `can_attempt_pachner` and `attempt_pachner` stay in sync.

---

Nitpick comments:
In `@tests/pachner_roundtrip.rs`:
- Around line 603-649: The generic K1Insert smoke test in
assert_public_k1_insert_feasibility_smoke only checks topology and embedding
after mutation, leaving the Delaunay invariant unverified. Update this test to
reuse assert_topology_and_delaunay_valid for the post-mutation assertions, or
add the same is_valid_delaunay check alongside validate() and
is_valid_embedding(). Keep the existing feasibility/mutation flow and ensure the
postcondition coverage matches the 2D toroidal test.
🪄 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.yml

Review profile: CHILL

Plan: Pro

Run ID: 3752e0bc-9e0f-41a0-a161-9af129dcc164

📥 Commits

Reviewing files that changed from the base of the PR and between abd466f and 9d4a57f.

📒 Files selected for processing (9)
  • src/core/algorithms/flips.rs
  • src/core/simplex.rs
  • src/delaunay/construction.rs
  • src/delaunay/flips.rs
  • src/delaunay/insertion.rs
  • src/delaunay/pachner.rs
  • src/lib.rs
  • tests/pachner_roundtrip.rs
  • tests/prelude_exports.rs

Comment thread tests/pachner_roundtrip.rs
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 39 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.00%. Comparing base (abd466f) to head (1cb06d8).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/core/algorithms/flips.rs 90.52% 20 Missing ⚠️
src/core/tds/storage.rs 64.70% 6 Missing ⚠️
src/delaunay/flips.rs 90.90% 6 Missing ⚠️
src/delaunay/pachner.rs 94.87% 6 Missing ⚠️
src/delaunay/construction.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #489      +/-   ##
==========================================
+ Coverage   90.99%   91.00%   +0.01%     
==========================================
  Files          86       87       +1     
  Lines       76734    77112     +378     
==========================================
+ Hits        69823    70175     +352     
- Misses       6911     6937      +26     
Flag Coverage Δ
unittests 91.00% <90.90%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

- Add provenanced PachnerProposal values that carry topology owner, generation, and feasibility evidence.
- Route public Pachner dry-run and mutation workflows through propose_pachner, can_attempt_on, and attempt_on.
- Reject wrong-owner and stale-generation proposals with typed FlipError variants before interpreting topology-local keys.
- Update public examples, docs, benchmarks, preludes, and roundtrip tests for the proposal workflow.

BREAKING CHANGE: PachnerMoves no longer exposes raw can_attempt_pachner or attempt_pachner entry points. Callers must parse a PachnerMove with propose_pachner(...) and then use PachnerProposal::can_attempt_on(...) or PachnerProposal::attempt_on(...).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
benches/pachner_stress.rs (1)

200-220: 🚀 Performance & Scalability | 🔵 Trivial

Benchmark now measures the full propose+attempt cost, not raw flip mutation.

Each sample now pays for propose_pachner (feasibility computation) plus attempt_on (full revalidation before mutating), whereas the prior attempt_pachner path paid for the mutation's validation once. This is required correctness-wise (each cloned triangulation gets a fresh TopologyOwnerId, so proposals can't be pre-minted once and replayed across the batch), but it does shift what these numbers represent. Worth a brief note (here or in the benchmark's README/changelog) so future perf-regression comparisons against pre-PR baselines account for the added propose-stage cost rather than reading it as a flip-primitive regression.

🤖 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 `@benches/pachner_stress.rs` around lines 200 - 220, Update the benchmark
documentation or an adjacent comment in bench_pachner_move to note that the
measurement now includes both propose_pachner feasibility work and attempt_on
revalidation before mutation, not just the raw flip mutation. Use the
bench_pachner_move and attempt_pachner_move symbols to make clear this is a
benchmark semantics change, so future comparisons against older results account
for the added propose-stage cost.
🤖 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.

Nitpick comments:
In `@benches/pachner_stress.rs`:
- Around line 200-220: Update the benchmark documentation or an adjacent comment
in bench_pachner_move to note that the measurement now includes both
propose_pachner feasibility work and attempt_on revalidation before mutation,
not just the raw flip mutation. Use the bench_pachner_move and
attempt_pachner_move symbols to make clear this is a benchmark semantics change,
so future comparisons against older results account for the added propose-stage
cost.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 8c781190-e2d5-42c6-a09b-7859e552024a

📥 Commits

Reviewing files that changed from the base of the PR and between 9d4a57f and 1cb06d8.

📒 Files selected for processing (17)
  • benches/pachner_stress.rs
  • docs/api_design.md
  • docs/dev/rust.md
  • docs/limitations.md
  • docs/roadmap.md
  • docs/workflows.md
  • examples/delaunayize_repair.rs
  • examples/diagnostics.rs
  • examples/topology_editing.rs
  • src/core/algorithms/flips.rs
  • src/core/tds/storage.rs
  • src/core/triangulation.rs
  • src/delaunay/pachner.rs
  • src/delaunay/triangulation.rs
  • src/lib.rs
  • tests/pachner_roundtrip.rs
  • tests/prelude_exports.rs
✅ Files skipped from review due to trivial changes (3)
  • docs/limitations.md
  • docs/dev/rust.md
  • docs/roadmap.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/algorithms/flips.rs

@acgetchell acgetchell merged commit be6728c into main Jul 2, 2026
22 checks passed
@acgetchell acgetchell deleted the feature/419-pachner-feasibility branch July 2, 2026 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api breaking change enhancement New feature or request geometry Geometry-related issues rust Pull requests that update rust code topology

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose exact immutable flip-feasibility validators

1 participant