Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions .github/workflows/codacy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ jobs:
fail-fast: false
matrix:
tool:
- markdownlint
# Upload only repository-owned rules to GitHub Code Scanning.
# Advisory quality engines stay in local/Codacy checks so they do
# not create empty Security/Quality tool configurations.
- opengrep
steps:
# Checkout the repository to the GitHub Actions runner
Expand All @@ -56,8 +58,11 @@ jobs:
- name: Set Codacy paths
run: |
set -euo pipefail
echo "CODACY_WORKDIR=$RUNNER_TEMP/codacy-src" >> "$GITHUB_ENV"
echo "CODACY_SARIF=$RUNNER_TEMP/results-${{ matrix.tool }}.sarif" >> "$GITHUB_ENV"
{
echo "CODACY_WORKDIR=$RUNNER_TEMP/codacy-src"
echo "CODACY_SARIF=$RUNNER_TEMP/results-${{ matrix.tool }}.sarif"
echo "CODACY_HAS_UPLOADABLE_SARIF=false"
} >> "$GITHUB_ENV"

- name: Prepare workspace copy without .git
run: |
Expand Down Expand Up @@ -114,8 +119,10 @@ jobs:
raise SystemExit(f"Codacy produced invalid SARIF JSON: {exc}") from exc

runs = sarif.get("runs")
if not isinstance(runs, list) or not runs:
sys.exit("Codacy SARIF did not contain any runs to upload")
if not isinstance(runs, list):
sys.exit("Codacy SARIF did not contain a runs array")
if not runs:
print("Codacy SARIF did not contain any runs to upload")

out_dir.mkdir(parents=True, exist_ok=True)
for stale in out_dir.glob("*.sarif"):
Expand All @@ -126,7 +133,14 @@ jobs:
return normalized.strip("-") or "unknown"

seen_categories: dict[str, int] = {}
uploadable_count = 0
for index, run in enumerate(runs, start=1):
rules = run.get("tool", {}).get("driver", {}).get("rules")
results = run.get("results")
if not rules and not results:
print(f"Skipping empty SARIF run {index} with no rules or results")
continue

run_copy = copy.deepcopy(run)
tool = run_copy.get("tool", {}).get("driver", {}).get("name")
base_category = f"codacy-{slug(str(tool or f'run-{index}'))}"
Expand All @@ -148,13 +162,20 @@ jobs:
out_file = out_dir / f"{index:02d}-{category}.sarif"
out_file.write_text(json.dumps(split_sarif, indent=2), encoding="utf-8")
print(f"Wrote {out_file} with category {category}")
uploadable_count += 1

with Path(os.environ["GITHUB_ENV"]).open("a", encoding="utf-8") as env_file:
env_file.write(f"CODACY_SPLIT_SARIF_DIR={out_dir}\n")
env_file.write(f"CODACY_HAS_UPLOADABLE_SARIF={'true' if uploadable_count else 'false'}\n")

if uploadable_count == 0:
print("No non-empty Codacy SARIF runs to upload")
PY

- name: Upload split SARIF files
if: env.CODACY_HAS_UPLOADABLE_SARIF == 'true'
uses: github/codeql-action/upload-sarif@b25d0ebf40e5b63ee81e1bd6e5d2a12b7c2aeb61 # v4
with:
sarif_file: ${{ env.CODACY_SPLIT_SARIF_DIR }}
category: codacy-${{ matrix.tool }}
wait-for-processing: true
119 changes: 119 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,116 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Merged Pull Requests

- Enable repo Semgrep rules for issue #338 [#354](https://github.com/acgetchell/delaunay/pull/354)
- Type repair diagnostics and harden invariants [#332](https://github.com/acgetchell/delaunay/pull/332) [#352](https://github.com/acgetchell/delaunay/pull/352)
- Harden Python benchmark parsing [#351](https://github.com/acgetchell/delaunay/pull/351)
- Expand profiling benchmarks around public API workflows [#349](https://github.com/acgetchell/delaunay/pull/349)
- Bump taiki-e/install-action from 2.75.18 to 2.75.22 [#348](https://github.com/acgetchell/delaunay/pull/348)

### Changed

- Type repair diagnostics and harden invariants [#332](https://github.com/acgetchell/delaunay/pull/332) [#352](https://github.com/acgetchell/delaunay/pull/352)
[`a244053`](https://github.com/acgetchell/delaunay/commit/a2440531ae7ee1407e7436379a82fe092f02e7dd)

- Replace stringified flip-repair skip samples with typed diagnostic context.
- Make vertex removal transactional across post-removal repair and orientation canonicalization.
- Deprecate DelaunayTriangulation::as_triangulation_mut ahead of removal in v0.8.0.
- Use scale-aware degeneracy checks for low-dimensional simplex and facet measures.
- Add regression and property coverage for rollback behavior, typed diagnostics, and scaled valid measures.
- Tolerate throughput formatting precision in benchmark baseline round-trip tests.

### Fixed

- Harden Python benchmark parsing [#351](https://github.com/acgetchell/delaunay/pull/351)
[`fea5898`](https://github.com/acgetchell/delaunay/commit/fea58987a2fb84e47603be9f0d1960aaa7e0f5f0)

- Reject non-finite and unordered Criterion timing estimates before using them in summaries, baselines, or backend comparisons.
- Preserve full Criterion benchmark IDs and normalize timing units when comparing storage backend results.
- Reuse the shared baseline parser while preserving malformed-section skip behavior and supporting scientific notation.
- Fall back from unusable lscpu output to /proc CPU core detection on Linux.
- Add regression and round-trip tests for parser behavior, benchmark IDs, unit normalization, and Linux CPU fallback.
- Document Python parser/file-format round-trip test expectations.

**Fixed: Harden Criterion estimate parsing and validation**

Consolidates estimate validation into a single public helper,
`is_valid_criterion_estimate`, now used by `PerformanceSummaryGenerator`
and `StorageBackendComparator`. Adds explicit type checks to
`PerformanceSummaryGenerator` to reject structurally malformed JSON
data, improving parsing robustness.

### Maintenance

- Bump taiki-e/install-action from 2.75.18 to 2.75.22 [#348](https://github.com/acgetchell/delaunay/pull/348)
[`31ec720`](https://github.com/acgetchell/delaunay/commit/31ec720a8638103b9acd7ea58c35b2baa5f571b9)

Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.75.18 to 2.75.22.

- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/taiki-e/install-action/compare/055f5df8c3f65ea01cd41e9dc855becd88953486...cf525cb33f51aca27cd6fa02034117ab963ff9f1)

---
updated-dependencies:

- dependency-name: taiki-e/install-action
dependency-version: 2.75.22
dependency-type: direct:production
update-type: version-update:semver-patch
...

- Enable repo Semgrep rules for issue #338 [#354](https://github.com/acgetchell/delaunay/pull/354)
[`9d51d30`](https://github.com/acgetchell/delaunay/commit/9d51d3038ae3f3316102ecaf39429bdfb73ff1cc)

- Enable project-owned Semgrep rules in local checks, CodeRabbit, and Codacy/OpenGrep scanning.
- Harden Semgrep execution with strict mode, a higher timeout, and fixture coverage for hot-path hash collection rules.
- Replace flagged diagnostics and silent numeric fallbacks with explicit tracing, expectations, and typed Hilbert quantization errors.
- Centralize Delaunay triangulation cache invalidation through the existing repair-cache helper.

**Maintenance: Enable repository Semgrep rules**

- Rename the Semgrep config to semgrep.yaml and wire it into local checks, CodeRabbit, and Codacy/OpenGrep.
- Add strict Semgrep execution plus fixture coverage for hot-path hash collections and targeted panic bypasses.
- Make Hilbert errors non-exhaustive and document quantization-scale conversion failures on APIs that can return them.
- Replace fragile VertexBuilder expect paths with infallible Vertex point constructors.

**Maintenance: Expand repository Semgrep rules**

- Add project-specific Semgrep checks for Rust dynamic errors, lint suppression reasons, Python subprocess mocks, and typed script helpers.
- Add focused Semgrep fixtures for hot-path hash collections, Rust project rules, and Python test conventions.
- Wire the expanded Semgrep fixture suite into `just check`.
- Replace stale Clippy `allow` suppressions with documented `expect` attributes and remove dynamic error trait-object usage from tests.

**Maintenance: Refresh quality tooling and diagnostics**

- Pin GitHub workflow tool versions and update action SHAs for cache, artifact upload, install-action, and SARIF upload.
- Exclude Semgrep fixtures from Codacy analysis so intentional rule-test violations do not surface as production issues.
- Add a cargo-machete backed just unused-deps recipe for checking unused direct dependencies.
- Gate convex hull test diagnostics behind test-debug tracing instead of unconditional stdout output.
- Add Hilbert ordering and zero-dimensional sort coverage for Codecov patch gaps.

**Fixed: Harden Hilbert ordering errors and prelude checks [#338](https://github.com/acgetchell/delaunay/pull/338)**

- Return typed Hilbert errors for non-finite quantization inputs and failed u32 coordinate conversions instead of silently collapsing values.
- Preserve item order when Hilbert sort key construction fails, and add regression coverage for the new error paths.
- Add the focused ordering prelude and update doctests, examples, benchmarks, and integration tests to use orthogonal prelude imports.
- Add a Semgrep rule and fixture coverage for examples and benchmarks that bypass focused preludes.
- Verify pinned shfmt binaries in CI with explicit SHA256 values instead of downloading a missing upstream checksum file.

### Performance

- Expand profiling benchmarks around public API workflows [#349](https://github.com/acgetchell/delaunay/pull/349)
[`0acbf65`](https://github.com/acgetchell/delaunay/commit/0acbf651b57c287aecc10bd51eea55fdbcbe2442)

- Run profiling comparisons with the checked-out crate toolchain by default
- Add local `just profile` support for comparing code refs and compiler versions
- Expand `ci_performance_suite` beyond construction to cover hulls, boundary traversal, validation, and bistellar flips
- Emit a versioned API benchmark manifest so benchmark logs show which public workflows were measured

## [0.7.6] - 2026-04-25

### ⚠️ Breaking Changes
Expand All @@ -14,6 +124,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Merged Pull Requests

- Release v0.7.6 [#347](https://github.com/acgetchell/delaunay/pull/347)
- Preserve fallback rebuild cell data [#305](https://github.com/acgetchell/delaunay/pull/305) [#346](https://github.com/acgetchell/delaunay/pull/346)
- Switch coverage reporting to cargo-llvm-cov [#345](https://github.com/acgetchell/delaunay/pull/345)
- Clarify research scope and changelog hygiene [#344](https://github.com/acgetchell/delaunay/pull/344)
Expand Down Expand Up @@ -502,6 +613,13 @@ Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6.3.0 to
- Add GitHub issue templates and clarify private vulnerability reporting guidance.
- Tighten Python lint/typecheck settings and clean up benchmark/changelog utility diagnostics.
- Add changelog post-processing coverage for version-heading reset behavior.
- Release v0.7.6 [#347](https://github.com/acgetchell/delaunay/pull/347)
[`6e437fb`](https://github.com/acgetchell/delaunay/commit/6e437fb5869f7ada49d6760114c4d25f15eb9b29)

- Bump version to v0.7.6
- Update changelog with latest changes
- Update documentation for release
- Add performance results for v0.7.6

## [0.7.5] - 2026-04-10

Expand Down Expand Up @@ -2866,6 +2984,7 @@ Older releases are archived by minor series:
- [0.3.x](docs/archive/changelog/0.3.md)
- [0.2.x](docs/archive/changelog/0.2.md)

[unreleased]: https://github.com/acgetchell/delaunay/compare/v0.7.6..HEAD
[0.7.6]: https://github.com/acgetchell/delaunay/compare/v0.7.5..v0.7.6
[0.7.5]: https://github.com/acgetchell/delaunay/compare/v0.7.4..v0.7.5
[0.7.4]: https://github.com/acgetchell/delaunay/compare/v0.7.3..v0.7.4
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,26 @@ Add the library to your crate:
cargo add delaunay
```

Choose the smallest prelude that matches the task:

| Task | Import |
|---|---|
| Build, configure, insert, or remove vertices | `use delaunay::prelude::triangulation::*` |
| Read-only traversal, adjacency, convex hulls, and comparison helpers | `use delaunay::prelude::query::*` |
| Points, kernels, predicates, and geometric measures | `use delaunay::prelude::geometry::*` |
| Random points or triangulations for examples, tests, and benchmarks | `use delaunay::prelude::generators::*` |
| Bistellar flips / Edit API | `use delaunay::prelude::triangulation::flips::*` |
| Delaunay repair diagnostics and policies | `use delaunay::prelude::triangulation::repair::*` |
| Delaunayize workflow | `use delaunay::prelude::triangulation::delaunayize::*` |
| Hilbert ordering and quantization utilities | `use delaunay::prelude::ordering::*` |
| Low-level TDS cells, facets, keys, and validation reports | `use delaunay::prelude::tds::*` |
| Collection aliases and small buffers | `use delaunay::prelude::collections::*` |
| Topology validation and Euler characteristic helpers | `use delaunay::prelude::topology::validation::*` |
| Topological spaces and topology traits | `use delaunay::prelude::topology::spaces::*` |

`use delaunay::prelude::*` remains available for quick experiments, but examples
and benchmarks in this repository prefer focused preludes so imports document intent.

```rust
use delaunay::prelude::triangulation::*;

Expand Down
1 change: 0 additions & 1 deletion docs/api_design.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ use `DelaunayTriangulationBuilder`:

```rust
use delaunay::prelude::triangulation::*;
use delaunay::core::triangulation::{TopologyGuarantee, ValidationPolicy};

// Toroidal (periodic) triangulation in 2D
let vertices = vec![
Expand Down
28 changes: 22 additions & 6 deletions docs/dev/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,17 +547,33 @@ pub mod core {

## Prelude Design

Preludes should remain **small and purposespecific**.
Focused preludes should remain **small and purpose-specific**.

A prelude should import only the items needed for a specific task.
A focused prelude should import only the items needed for a specific task.
Prefer these focused preludes in doctests, integration tests, examples, and
benchmarks because they make intent visible at the import site.

Example:
Examples:

```text
delaunay::prelude::triangulation
```

Avoid giant catch‑all preludes.
delaunay::prelude::triangulation::flips
delaunay::prelude::triangulation::repair
delaunay::prelude::triangulation::delaunayize
delaunay::prelude::query
delaunay::prelude::geometry
delaunay::prelude::generators
delaunay::prelude::ordering
delaunay::prelude::collections
delaunay::prelude::tds
delaunay::prelude::topology::validation
delaunay::prelude::topology::spaces
```

The root `delaunay::prelude::*` is intentionally available as a convenience for
new users and quick experiments. Avoid using it in committed examples,
benchmarks, and doctests when a focused prelude communicates the workflow more
clearly.

---

Expand Down
2 changes: 1 addition & 1 deletion docs/numerical_robustness_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ The convenience constructors (`DelaunayTriangulation::new()`, `::empty()`, etc.)
`AdaptiveKernel`. To opt into a different kernel, use the explicit-kernel constructors:

```rust
use delaunay::geometry::kernel::RobustKernel;
use delaunay::prelude::geometry::RobustKernel;
use delaunay::prelude::triangulation::*;

let kernel = RobustKernel::<f64>::new();
Expand Down
2 changes: 1 addition & 1 deletion docs/workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ If repair fails to converge within the flip budget, you get
detections, etc.).

```rust
use delaunay::core::algorithms::flips::DelaunayRepairError;
use delaunay::prelude::triangulation::repair::DelaunayRepairError;
use delaunay::prelude::triangulation::*;

let vertices = vec![
Expand Down
1 change: 1 addition & 0 deletions examples/memory_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! This example demonstrates basic memory usage analysis for Delaunay triangulations
//! using the existing allocation counter infrastructure from the tests.

use delaunay::prelude::generators::generate_random_triangulation;
use delaunay::prelude::query::*;
use std::any::Any;
use std::backtrace::Backtrace;
Expand Down
2 changes: 1 addition & 1 deletion examples/zero_allocation_iterator_demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! zero-allocation `vertex_uuid_iter()` method compared to the traditional
//! `vertex_uuids()` method that allocates a Vec.

use delaunay::prelude::query::*;
use delaunay::prelude::generators::generate_random_triangulation;
use std::hint::black_box;
use std::time::Instant;

Expand Down
21 changes: 21 additions & 0 deletions semgrep.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,27 @@ rules:
- pattern-regex: '^\s*use\s+delaunay::(core|geometry|triangulation|topology)::'
- pattern-not-regex: '^\s*use\s+delaunay::prelude::'

- id: delaunay.rust.prefer-prelude-imports-in-triangulation-doctests
languages:
- rust
severity: WARNING
message: >-
Use focused delaunay::prelude imports in public triangulation doctests
instead of deep crate module paths.
metadata:
category: maintainability
tracking_issue: "https://github.com/acgetchell/delaunay/issues/355"
rationale: >-
Public doctests should model the small, orthogonal prelude import
surfaces that users can copy into their own code.
paths:
include:
- "/src/**/*.rs"
- "/tests/semgrep/src/project_rules/**/*.rs"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
patterns:
- pattern-regex: '^\s*//[/!]\s*(?:#\s*)?use\s+delaunay::(core|geometry|triangulation|topology)::'
- pattern-not-regex: '^\s*//[/!]\s+use\s+delaunay::prelude::'

- id: delaunay.python.no-broad-exception
languages:
- python
Expand Down
4 changes: 2 additions & 2 deletions src/core/adjacency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use thiserror::Error;
/// # Examples
///
/// ```rust
/// use delaunay::core::adjacency::AdjacencyIndexBuildError;
/// use delaunay::core::tds::{CellKey, VertexKey};
/// use delaunay::prelude::query::AdjacencyIndexBuildError;
/// use delaunay::prelude::tds::{CellKey, VertexKey};
/// use slotmap::KeyData;
///
/// let cell_key = CellKey::from(KeyData::from_ffi(1));
Expand Down
Loading
Loading