Skip to content

Native tooling: format every file, clang-tidy by family, stronger warnings, drop unused build options - #762

Merged
jtravs merged 92 commits into
mainfrom
chore/native-tooling
Nov 12, 2026
Merged

jtravs merged 92 commits into
mainfrom
chore/native-tooling

Conversation

@jtravs

@jtravs jtravs commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Native tooling: every C++ file formatted, clang-tidy pinned and enabled by whole families, stronger warnings, a stricter sanitizer build, a weekly deep-check workflow, and the unused build options removed. The changes are in native/, CI, the build guide and docs/dev/tooling.md, plus two benchmark harnesses moved into benchmarks/. There is one commit per concern, and each clang-tidy check is fixed in its own commit.

Build options removed

  • GEMM providers. Only the hybrid provider remains. SOLPROP_NATIVE_GEMM_PROVIDER and the cuda-custom, cuda-native and cuda-tpl presets are gone. custom_gemm stays as the hybrid provider's kernel for shapes the vendor GEMM does not take, and build_info().gemm_provider is always "HYBRID".
  • GEMM microbenchmark. benchmark_gemm.cpp and SOLPROP_NATIVE_BUILD_BENCHMARKS are removed.
  • icpx. IntelLLVM support is dropped (about 45 CMake lines plus the docs). Linux CPU builds take GCC 14 or Clang/AOCC.
  • Kokkos Threads. SOLPROP_NATIVE_ENABLE_THREADS is removed; a CPU build's execution space is OpenMP.
  • Single-precision FFTW.
    • FFTW_FLOAT_LIB and FFTW_FLOAT_OPENMP_LIB now point at the double libraries before Kokkos-FFT is configured, as the MKL branch already did: one find_library per double library (FFTW_ROOT or FFTWDIR as hints, FFTW_USE_STATIC_LIBS honoured), whose cached result FindFFTW keeps. Every fftwf_ call in Kokkos-FFT sits behind if constexpr on float.
    • The single-precision FFTW builds are gone from ci/build-fftw.sh, ci/build-deps-windows.ps1 and native/pyproject.toml.
    • ci/smoke.py now refuses a wheel that bundles a libfftw3f or imports an fftwf_ symbol.
    • Checked locally: otool -L no longer lists libfftw3f.
  • native/benchmarks.
    • size_cliffs and statistics_cost move to benchmarks.size_cliffs and benchmarks.statistics_cost. Its m2_reduced and ctc_reduced arms keep the former harness's exact workloads (their own tables, rtol 1e-6, atol 1e-10).
    • m1, m2, m2_cases, ctc, gemm_shapes, provider_sweep and device_record are deleted. Nothing outside archived SEPs referenced them.
    • N = 6 soliton gap. The registry has no N = 6 case. The nearest is the N = 3 gnlse_soliton, on the same fibre, launch shape and grid limits, so m1's exact workload (N = 6, rtol 1e-10) is no longer timed.
    • cpu_timer.cpp is deleted rather than merged into coverage_labels.cpp. That module only counts labels in the instrumented coverage build, where timings mean nothing, and cpu_timer.cpp had no build rule.

Formatting (T1)

  • check.sh formatted a hand-written list of 40 files and missed 43 of the 83 tracked ones. It now formats everything git ls-files lists under native/, which is 81 files after the removals above.
  • .clang-format adds InsertNewlineAtEOF and regrouped include blocks: this package's headers, then third-party, then the standard library, then platform headers. Conditional includes stay where they are.
  • CommentPragmas keeps clang-format from reflowing NOLINT comments.
  • No RemoveSemicolon. It deletes the ; that ends const auto f = KOKKOS_LAMBDA(...) {...};. Declaring the macro under Macros: fixes that, but makes formatting take minutes.
  • New poe fmt-native. The reformat itself is a separate, mechanical commit.

Pinned clang-tidy (T2)

  • clang-tidy==23.1.4 is in the dev group, on Linux and macOS only (it has no Windows-on-Arm wheel, and the gate that uses it is bash). PyPI's wheels start at 23.1.3, so there is no 23.1.0 to match clang-format exactly; 23.1.4 is the closest.
  • CMake prefers the clang-tidy in the build's Python environment. On macOS it passes the SDK sysroot. On GCC builds it adds -Wno-unknown-warning-option so that the parser accepts GCC-only warning flags.
  • CI's tidy lane now uses the pinned clang-tidy instead of Ubuntu's LLVM 18.
  • New poe tidy-native [FILE...] (native/scripts/tidy.sh) checks the named files, or the files changed from main. It runs the clang-tidy command CMake resolved (clang_tidy_command.txt), reconfigures the cpu-tidy preset when that file or the compile commands are missing or older than CMakeLists.txt, and refuses a clang-tidy that is not the pinned version. The compiler and Raman provider choice is shared with check.sh through native/scripts/compiler.sh.

Warnings (T3)

  • Added: -Wundef -Wnon-virtual-dtor -Woverloaded-virtual; Clang's -Wimplicit-fallthrough; GCC's -Wduplicated-cond -Wduplicated-branches -Wlogical-op.
  • The list is defined once and feeds the targets, the label module and the build record.
  • The only new finding was a test helper's conditional with identical branches, which is fixed.

clang-tidy by family (T4)

Enabled: bugprone-*, performance-*, modernize-*, misc-*, readability-*, clang-analyzer-* and cppcoreguidelines-special-member-functions. Warnings remain errors, and each exclusion has a one-line reason in native/.clang-tidy.

Exclusions beyond the brief's list:

  • readability-function-cognitive-complexity: deferred, with function-size, until PR-5 splits the long functions.
  • readability-avoid-nested-conditional-operator: nested conditionals initialise const locals, in kernels too.
  • readability-make-member-function-const: Kokkos views are handles, so a member that writes through one would be marked const although it changes the object's state.
  • clang-analyzer-optin.performance.Padding: the cold configuration structs are ordered by concern, not by size.
  • misc-const-correctness: it judges one template instantiation and the active #if branch. Its fix-its made const the locals that another instantiation's if constexpr branch assigns, and broke the CPU build in about 30 places. Device branches would break the same way without a CPU build noticing.
  • readability-use-std-min-max: it rewrites if (a > m) m = a as m = std::max(a, m). That changes what a NaN gives (the original keeps m; std::max returns the NaN), and std::max is not device code.
  • readability-convert-member-functions-to-static: it sees only the CPU build, where some members (for example hybrid_shape_eligible) read no state; their device branches do.
  • clang-analyzer-cplusplus.NewDeleteLeaks: on Linux it reports Kokkos's reference-counted allocation records as a leak inside Kokkos's own header.

Options:

  • readability-simplify-boolean-expr.SimplifyDeMorgan: false: the De Morgan rewrite of !(a <= x && x <= b) lets a NaN through, and these guards are written that way to refuse NaN.
  • bugprone-unchecked-optional-access.IgnoreValueCalls: .value() is a checked access that throws.
  • bugprone-unused-return-value.AllowCastToVoid: a cast to void is an explicit discard.
  • bugprone-signed-bitwise.IgnorePositiveIntegerLiterals: shifts and masks by positive literals are not sign bugs.
  • performance-unnecessary-value-param.AllowedTypes: reference-counted handles passed by value by convention: Kokkos views and their aliases, and nanobind's handles and ndarrays (nb::, and the bindings' ...Input and ...Array aliases). The one remaining finding, an optional dict copied into a bound lambda, now takes it by reference.

Applied with clang-tidy, one commit each:

  • concise preprocessor directives
  • isolate-declaration
  • nodiscard
  • designated initialisers
  • std::ranges. Its fix-it left a stray comma, and in one place passed a pointer where a range was needed; both are fixed in the following commit.
  • redundant lambda parameter lists
  • if-else braces. Two of its braces straddled an #endif; a later commit fixes that (CI's CUDA and HIP compiles found it).
  • use-auto
  • qualified-auto
  • braced returns
  • return-with-void-value
  • std::numbers, with the <numbers> includes added in a separate commit
  • pass-by-value for execution spaces
  • duplicate includes
  • integer sign comparison
  • parameter names
  • named parameter
  • string_view
  • raw string literal
  • std::move
  • reserve
  • internal linkage, plus the anonymous-namespace follow-up

By hand:

  • A real bug the analyser found. Table::value wrote every column of a multi-column table into its single double. The stage-table loader now refuses, by name, a scalar table holding other than one value (stage::require_scalar_tables, tested); the read keeps only a debug assert.
  • Special member functions declared on the RAII classes.
  • .value() reads where the optional checks cannot see the invariant.
  • Named nanobind exception registrations.
  • noexcept helpers that could allocate.
  • Integer division, widening and implicit bool conversions.
  • Flattened branch clones.
  • A coupled-flow test without throwing static initialisers.
  • any_of in place of a hand-written loop.
  • The build record's macros compared with zero. The modernize-use-bool-literals fix-it would have written this build's values in.

Every NOLINT added

where check reason
include/solprop_native/adams_phi.hpp, adams_lanes_classify and adams_lanes_phi (BEGIN/END) bugprone-signed-bitwise, readability-implicit-bool-conversion signed 64-bit lane masks and bitwise selections, written so that every x86-64 target vectorises them; hot code left unchanged
src/general.cpp, the three strict Adams compensation helpers (BEGIN/END) misc-use-internal-linkage strict helpers (fp.hpp); a linkage change could move GCC's inlining of strict code and needs its own A/B
src/general.cpp, RestoreFlow cppcoreguidelines-special-member-functions a local scope guard, initialised as an aggregate and never copied or moved
src/general.cpp, ionisation_log_rate modernize-use-integer-sign-comparison device code, where std::cmp_* is host-only
src/far_field.cpp, the packed-row cascade (BEGIN/END) bugprone-assignment-in-if-condition each test takes the previous range off the row before comparing
src/dense.cpp, src/rk_march.cpp, tests/native/test_session.cpp readability-suspicious-call-argument reached(target, z) is solprop's Runge-Kutta crossing test, so the "swapped" names are its meaning
include/solprop_native/lagrange_basis.hpp (2), src/general.cpp (3) readability-suspicious-call-argument the names only coincide (a generic functor, the FFT pool lookup, buffer names)
tests/native/test_aperture.cpp, tests/native/test_adams_phi.cpp bugprone-random-generator-seed a fixed seed keeps the test reproducible
the generated source_digest.cpp (cmake/SourceDigest.cmake) misc-use-internal-linkage bindings.cpp declares and reads source_digest()

Sanitizers and deep checks (T5, T6)

  • Sanitizer preset. The cpu-sanitize preset adds Kokkos_ENABLE_DEBUG_BOUNDS_CHECK=ON, and sanitized targets compile with -fno-sanitize-recover=all.
  • New .github/workflows/native-deep.yml runs weekly, on dispatch, and on a pull request that changes the workflow itself (dispatch reaches only workflows on the default branch). It reports and gates nothing, and its builds turn warnings-as-errors off. It has three jobs:
    • Clang source coverage over GoogleTest and native pytest, with an HTML and text report artifact.
    • The extension built with ASan, UBSan and Kokkos bounds checks, run under native pytest (libasan and libstdc++ preloaded, detect_leaks=0; the outcome goes to the job summary).
    • A misc-include-cleaner report.
  • cuda.yml adds compute-sanitizer's initcheck and synccheck, and its comment now says GCC 14.

Tooling decisions

The table is in docs/dev/tooling.md, under "Native C++ tooling".

  • Adopted:
    • clang-format
    • the clang-tidy families, including clang-analyzer
    • the warnings above
    • ASan and UBSan with Kokkos bounds checks
    • compute-sanitizer's four tools
  • Scheduled: coverage, the extension under ASan, include-cleaner.
  • Ad hoc: perf, Hotspot, Instruments, Nsight, rocprof, optimisation remarks, llvm-mca, Compiler Explorer.
  • Rejected, each with its one-line reason:
    • cppcheck, the IWYU binary, CodeChecker, scan-build, GCC -fanalyzer
    • CodeQL, SonarQube
    • TSan (on-demand campaign only), MSan, TypeSanitizer, Valgrind
    • thread-safety annotations
    • Google Benchmark, Tracy, HPCToolkit
    • fuzzers, MPFR

Hot files for the Linux A/B

I ran a structural check rather than a benchmark: one Release _core build per side (cpu-benchmark preset, Clang 23 with LTO, SOLPROP_NATIVE_HOST_ARCH=OFF, macOS arm64), comparing symbol sizes from llvm-nm -n.

  • Kernels. No Kokkos kernel instantiation and no hot kernel symbol changed size by more than 3 %. Total text went from 5,845,620 to 5,842,216 bytes.
  • What did change:
    • GeneralWorkspace::low_storage_separable_fold grew from 6,080 to 16,316 bytes, because column_norms (14,460 bytes, now file-local) is inlined into it. Its kernels are separate symbols and unchanged.
    • Three constructors (CoupledFlowAction, DispersiveWeights, FarFieldPass) now take the execution space by value and are the same size.
    • The session's host functions moved by tens to a few hundred bytes (.value() and std::move).
  • Source-level fix-its in the hot files. None changes arithmetic.
    • general.cpp: isolate-declaration, designated initialisers, std::ranges (host code), use-auto and qualified-auto, a named row index in the fluence-moment kernels, the brace fix in team_band_statistics, column_norms linkage, and the removed GEMM provider branches.
    • plasma.hpp: designated initialisers; void-return dispatch in the band filter.
    • general_modal.cpp: if-else braces; designated initialisers; std::ranges.
    • gemm.hpp: selected_gemm simplified; one #ifdef.
    • vmath.hpp: #ifdef only.
    • adams_phi.hpp: use-auto and isolate-declaration in the lane passes; 1.0 / 1.0 written as 1.0.
  • Suggested Linux A/B (GCC 14): a low-storage separable case (for the inlined column_norms), a band-plasma field case and an Adams multimode case.

Verification (local, macOS arm64, Homebrew Clang 23)

  • cpu-debug builds after every commit, and the GoogleTest suite passes (236 tests).
  • Before the coordinator asked me to keep this machine light, cpu-sanitize (with bounds checks) passed GoogleTest. The Release cpu-benchmark build compiles.
  • Targeted native pytest passes: test_api_contract, test_radial, test_coupled_flow, test_envelope_plasma, test_dispersive, the test_backend metadata tests, and tests/backends/test_spatial_execution.py.
  • A per-check clang-tidy pass runs clean locally. The full tidy, sanitize and wheel stages run in CI on this PR: on the previous head, sanitize, lint, static, the CUDA and HIP compiles and the native wheels passed, and tidy failed only on the generated source_digest.cpp, fixed in the last commit.

🤖 Generated with Claude Code

jtravs and others added 14 commits November 11, 2026 23:18
Remove SOLPROP_NATIVE_GEMM_PROVIDER and its CUSTOM, KOKKOSBLAS_NATIVE and
KOKKOSBLAS_TPL values, with the cuda-custom, cuda-native and cuda-tpl
presets that alone selected them. No shipped or CI build used them.
custom_gemm stays as the hybrid provider's kernel for ineligible shapes,
and the build record keeps gemm_provider (always HYBRID).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
benchmark_gemm.cpp compared the GEMM providers that are gone; the
SOLPROP_NATIVE_BUILD_BENCHMARKS option built nothing else. End-to-end
'benchmarks ab' decides performance questions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No CI lane or shipped build uses icpx, and its special cases (the
precise floating-point model, its LTO archiver, the pthreads FFTW
requirement and MKL's Intel threading layer) cost about 45 CMake lines.
Linux CPU builds now take GCC 14 or Clang/AOCC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SOLPROP_NATIVE_ENABLE_THREADS had no C++ use, no CI lane and no shipped
build; every CPU wheel, Windows included, runs OpenMP. A CPU build's
execution space is now OpenMP only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kokkos-FFT requires the single-precision FFTW libraries, but every
fftwf_ call it makes sits behind an if constexpr on float that the
double-only package never takes. Point FFTW_FLOAT_LIB and
FFTW_FLOAT_OPENMP_LIB at the double libraries before Kokkos-FFT is
configured, as the MKL branch already does, drop the single-precision
FFTW builds from the wheel recipes, and make the wheel smoke test refuse
a bundled libfftw3f or an fftwf_ import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
size_cliffs and statistics_cost become benchmarks.size_cliffs and
benchmarks.statistics_cost (statistics_cost builds ctc_reduced through
the registry's builder and keeps m2_reduced's own table). The other
native/benchmarks scripts (m1, m2, ctc, gemm_shapes, provider_sweep,
device_record) predate 'python -m benchmarks track/ab', which covers
their workloads, and nothing referenced them. cpu_timer.cpp, a Kokkos
Tools timer with no build rule, goes too: the coverage label module
counts and must not time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check.sh hand-listed 40 files for clang-format and missed 43 of the 83
tracked ones; it now formats what 'git ls-files' lists under native/.
.clang-format adds InsertNewlineAtEOF, RemoveSemicolon and regrouped
include blocks (this package's headers, third-party libraries, the
standard library, platform headers; conditional includes stay put).
'poe fmt-native' formats the same list in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It removes the semicolon that ends a KOKKOS_LAMBDA variable's
declaration, which clang-format parses as a function definition.
Declaring the macro would fix that, but makes formatting general.cpp
take minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
Mechanical: clang-format 23.1.0 over the files the check now covers,
with the regrouped include blocks and a newline at the end of each file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
The dev group pins clang-tidy 23.1.4, the PyPI wheel nearest the
formatter's 23.1.0 (the wheels start at 23.1.3), and CMake looks for it
beside the build's Python before any machine's LLVM. CI's tidy lane
used Ubuntu 24.04's LLVM 18 and now uses the pinned one. On macOS the
SDK is passed explicitly, as Homebrew's Clang finds it from a
configuration file the PyPI build does not read.

'poe tidy-native [FILE...]' runs it on the given files, or on the C++
files that differ from main, with the cpu-tidy preset's compile
commands (configured when missing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
The project's sources now also compile with -Wundef,
-Wnon-virtual-dtor and -Woverloaded-virtual; with
-Wimplicit-fallthrough under Clang; and with -Wduplicated-cond,
-Wduplicated-branches and -Wlogical-op under GCC. The list is defined
once and feeds the targets' options, the coverage label module and the
build record, which repeated it by hand. The one new finding (a test
helper's conditional with identical branches) is fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
The cpu-sanitize preset turns on Kokkos_ENABLE_DEBUG_BOUNDS_CHECK, and
sanitized targets compile with -fno-sanitize-recover=all, so a UBSan
report fails the test whatever UBSAN_OPTIONS says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
native-deep.yml (weekly and by hand, report-only) collects Clang source
coverage over the GoogleTest and native pytest suites, runs the native
pytest suite on an extension built with ASan, UBSan and Kokkos bounds
checks (the bindings were never sanitized), and reports
misc-include-cleaner's findings. cuda.yml adds compute-sanitizer's
initcheck and synccheck beside memcheck and racecheck, and its comment
now names the GCC 14 host compiler CMake requires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
@jtravs jtravs added refactor Internal restructuring with no change in behaviour area: native The native backend, threading and FFT planning labels Nov 11, 2026
poe tidy-native and the include-cleaner report run clang-tidy after a
configure alone, which does not generate sleef.h.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
@read-the-docs-community

read-the-docs-community Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

jtravs and others added 12 commits November 11, 2026 23:44
clang-analyzer-security.ArrayBound: Table::value wrote every column of
the table into its one double. Every caller reads a one-column table;
the guard makes that a refusal instead of an out-of-bounds write.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAYtF4KqhYgzk6eBpqdfWA
misc-redundant-expression: '1.0 / 1.0' is the same double as 1.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
misc-misplaced-const: 'const fftw_plan' makes the pointer const, not the
plan, which the spelling suggests. The handles keep their meaning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A reflowed NOLINTNEXTLINE would suppress its own continuation line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cppcoreguidelines-special-member-functions: AccelerateRamanPlan,
BoundState, BoundSession and the test's SynthesisCapture delete their
moves as they already deleted their copies (BoundState's address is
held by the runtime's list of live states). The coupled flow's local
RestoreFlow guard stays an aggregate, with a NOLINT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bugprone-unchecked-optional-access: the transverse edge's record and
held readings, the session's monitor plan and the bound marches'
policies and stage tables are set whenever these lines run, by
invariants the flow analysis does not follow (a validating lambda, an
earlier stage of a state machine, a refusal in another member). A
.value() read keeps them checked; it throws instead of reading an empty
optional. The configuration counts .value() as checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bugprone-throw-keyword-missing and bugprone-unused-raii read the
temporaries that register the exception types as exceptions never
thrown. Registration happens in the constructor either way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bugprone-unused-return-value: the pointer was taken with get() before
the capsule was made, so release() only gives up ownership.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
.clang-tidy moves from an allow-list of about 35 checks to the bugprone,
performance, modernize, misc and readability families, the clang
analyser and cppcoreguidelines-special-member-functions, each exclusion
with its reason; warnings stay errors. The findings are fixed in the
commits that follow, one check each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/dev/tooling.md gains the native C++ tooling table, each tool's
status and the reason for every rejection. native/AGENTS.md and the
native README name the public API as solprop_native.__all__, add
'poe fmt-native', 'poe tidy-native' and the weekly native-deep.yml, and
the changelog records the tooling change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
readability-use-concise-preprocessor-directives, applied by clang-tidy. Directives in inactive branches are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jtravs and others added 12 commits November 12, 2026 00:20
bugprone-exception-escape: host_forward_pack compares the environment value as a string_view instead of building a string, and rk_dense_release move-assigns an empty vector instead of assigning {} (an initializer-list assignment, which may throw).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
misc-use-anonymous-namespace, after the internal-linkage commit made it static.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
readability-isolate-declaration, by hand in both build branches (the fix-it covered the active one only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
readability-implicit-bool-conversion, in two setup loops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bugprone-integer-division: a plane node's row index (in the fluence-moment and second-moment kernels) and the rate tables' interval count are whole numbers by design; each is now an integer of its own before its conversion. The kernels' arithmetic is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bugprone-implicit-widening-of-multiplication-result: the envelope rule count and the packed radial inventory's limit were int products widened afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bugprone-branch-clone: without a vendor BLAS the envelope branch and the non-real branch both returned false. The guard is now one #if'd test, and the family test its own; the decisions are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The readability-inconsistent-ifelse-braces fix opened a brace on two 'else' arms that end at an #endif, and closed it outside: the CUDA and HIP builds, which skip the host branch, saw an unmatched brace. The closing brace now sits under the same condition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
readability-suspicious-call-argument: a generic element functor, the FFT pool's lookup and the monitor's power callable take arguments whose names merely resemble other parameters'; each keeps a NOLINT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
readability-implicit-bool-conversion (reported by the Linux tidy lane): SpaceAccessibility<...>::accessible is an enumerator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Linux it reports Kokkos's shared allocation records, freed through a
reference count it cannot follow, as a leak inside Kokkos's own header
when a view is constructed. The code holds no raw ownership, and the
sanitizer builds check for leaks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
misc-use-internal-linkage (the Linux tidy lane): source_digest() is
defined in the generated source_digest.cpp and declared and read in
bindings.cpp, so it needs external linkage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

jtravs and others added 12 commits November 12, 2026 03:22
clang-tidy has no PyPI wheel for Windows on Arm, so the Windows arm64
test lanes built LLVM from its sdist and timed out. The native gate
that uses it is bash, run on Linux and macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
benchmarks.statistics_cost built ctc_reduced through the registry's
capillary builder, which changed the timed workload: tolerances, loss,
temperature, seeded noise and n_save all differed from the deleted
native/benchmarks/ctc.py. It now builds that case's own table exactly
as the old harness did (rtol 1e-6, atol 1e-10, lossless, Raman,
n_save 21, the defaults otherwise), as m2_reduced already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tidy.sh reconfigured only when the compile commands were missing, ran
whatever clang-tidy was on PATH, and copied check.sh's compiler choice
(without its /usr/local fallback). CMake now writes the clang-tidy
command it runs, the resolved binary first, to clang_tidy_command.txt;
tidy.sh reconfigures when that or the compile commands are missing or
older than CMakeLists.txt, runs that command, and refuses a clang-tidy
whose version is not the pinned one. The compiler and Raman provider
choice moves to scripts/compiler.sh, sourced by both scripts, and the
weekly include-cleaner report reads the same command file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The earlier guard threw from Table::value, a per-stage read. The
loader now checks every scalar table (density, taper, Kerr density,
chord, and each Raman, plasma and dispersive table) holds one value and
refuses one that does not by name; Table::value keeps a debug assert.
The test exercises the loader's refusal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
performance-unnecessary-value-param: the bindings' NOLINTBEGIN/END over whole files goes. The check's AllowedTypes now admits nanobind's reference-counted handles (nb::dict, nb::object, nb::handle, nb::ndarray and the bindings' ...Input and ...Array aliases of it), as it does Kokkos views; the one remaining finding, an optional dict copied into a bound lambda, now takes it by reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The block that names the double libraries for Kokkos-FFT's single-precision ones copied FindFFTW's search and dropped parts of it. It now makes one find_library per double library (fftw3, and fftw3_omp with OpenMP), with FFTW_ROOT or FFTWDIR as hints, honouring FFTW_USE_STATIC_LIBS, and points the FLOAT variable at each; FindFFTW keeps the cached results. The wheel smoke test still refuses an fftwf_ import.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
native-deep.yml's coverage job builds with Ubuntu's clang-18 and its
extension job with ASan, configurations no pull-request lane compiles;
with warnings as errors a new diagnostic there would stop the report.
Both now build with SOLPROP_NATIVE_WARNINGS_AS_ERRORS=OFF.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
clang-tidy 23.1.4 joins the dev group's record beside clang-format
23.1.0, with why it is pinned and why only on Linux and macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
workflow_dispatch reaches only workflows on the default branch, so a
change to this report-only workflow could not be tried before merging.
A pull request that edits the file now runs it; it still gates nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main's lint now caps positional parameters at five (PLR0917).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Python loads no C++ runtime, so ASan, preloaded alone, could not
resolve __cxa_throw at start-up and aborted at the first C++ exception
the extension threw. libstdc++ is now preloaded beside it, and the
report-only step records its outcome in the job summary instead of
failing the job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jtravs
jtravs marked this pull request as ready for review November 12, 2026 09:29
@jtravs
jtravs merged commit 6136c60 into main Nov 12, 2026
74 checks passed
@jtravs
jtravs deleted the chore/native-tooling branch November 12, 2026 09:29
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-12T09:30:40.340568Z 4393ad8 Draft marked ready
🔒 Security Review ✅ Completed 2026-11-12T09:31:30.523661Z 4393ad8 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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

Labels

area: native The native backend, threading and FFT planning refactor Internal restructuring with no change in behaviour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant