Skip to content

refactor(dnn,psnr): clear the dnn + psnr clang-tidy buckets to zero (ADR-1142 wave 2) - #1323

Draft
lusoris wants to merge 11 commits into
masterfrom
refactor/tidy-wave2-dnn-psnr
Draft

refactor(dnn,psnr): clear the dnn + psnr clang-tidy buckets to zero (ADR-1142 wave 2)#1323
lusoris wants to merge 11 commits into
masterfrom
refactor/tidy-wave2-dnn-psnr

Conversation

@lusoris

@lusoris lusoris commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Wave-2 of the epic #1237 ADR-1142 whole-tree clang-tidy ratchet, covering the core/src/dnn/ and core/src/feature/*psnr* buckets. Nine sources go from 60 measured warnings to 0: model_loader.c 29 → 0 (four oversized functions split into named helpers, the per-encoder preset ladder replaced by a lookup table, two ADR-0461-cited getenv NOLINTs), psnr_tools.cpp 24 → 0 (designated initialisers), integer_psnr.c 3 → 0, dnn_api.c / onnx_scan.c / float_psnr.c 2 → 0 each, dnn_attach_api.c / op_allowlist.c / psnr.c 1 → 0 each. Every finding is fixed by refactoring; the only new suppressions reuse an established in-tree citation (ADR-0278 cross-TU registry linkage on the two feature-extractor symbols, ADR-0461 caller-contract on the two getenv sites, ADR-1138 file-scoped modernize-use-nullptr brackets on the seven touched C TUs). Numeric paths are proven inert: --feature psnr --precision=max on the src01_hrc00 / src01_hrc01 pair is byte-identical before and after once the fps and version metadata lines are excluded, and the Netflix golden gate stays at 271 passed / 12 skipped / 0 failed. The pass also surfaced a real defect: core/test/dnn/test_cli.sh's DNN-availability probe never reached the check it was probing for, so the test failed instead of skipping on every -Denable_dnn=disabled build — fixed here and recorded in docs/state.md as T-DNN-TESTCLI-PROBE-NEVER-SKIPS-2026-09-05. scripts/ci/tidy-baseline-cpu.json is deliberately NOT updated here — see the "Baseline" note below. Deferred: core/src/feature/third_party/xiph/psnr_hvs.c (2 modernize-use-nullptr) is vendored Xiph code outside the brief's core/src/feature/*psnr*.c scope and is left for the vendored-code wave; the psnr test files (test_psnr_hvs_coverage.c 32, test_integer_psnr_coverage.c 31, …) belong to the test-tree bucket of the same epic.

C translation units keep NULL (ADR-1138)

The first revision of this branch rewrote 90 NULLs to the C23 nullptr keyword across the seven touched .c files. That is exactly the rewrite ADR-1138 forbids: Build — Windows MSVC + CUDA (build only) is a required status check, it compiles these translation units with cl.exe, and MSVC's documented /std:clatest C23 feature set does not include nullptr — PR #1192 had to revert the identical rewrite after all three Windows legs failed with "use of undeclared identifier nullptr". Commit 35ec49cfc restores NULL everywhere and gives each of the seven files the file-scoped /* NOLINTBEGIN(modernize-use-nullptr) … ADR-1138. *//* NOLINTEND */ bracket the ADR prescribes, worded as in core/src/dnn/ort_backend.c and core/src/feature/integer_adm.c. psnr_tools.cpp is C++ and keeps nullptr; ADR-0915's ratchet still covers it in full.

The revert re-opened one finding the keyword rewrite had masked — vmaf_dnn_session_open() at 114 lines against the 60-line readability-function-size budget. It is split into resolve_load_path() (the ADR-0174 int8-sibling lookup plus its fp32 fallback) and setup_luma_fast_path() (the NCHW [1,1,H,W] shape check and scratch allocation), which also retires the function's goto fail ladder. Behaviour is unchanged: same validation order, same ownership on every error path, same -ENAMETOOLONG / -ENOMEM / -ENOTSUP contracts, and all seven dnn meson tests (including test_dnn_session_api and test_model_loader) stay green.

Baseline — must be tightened from the CI artifact

The 60-warning drop needs scripts/ci/tidy-baseline-cpu.json tightened in this PR (ADR-1142 exit 3). That baseline cannot be produced on this workstation: .github/workflows/lint-and-format.yml measures with CC=gcc-14 CXX=g++-14 meson setup build core (build dir build/ at the repo root), and this machine has no gcc-14 (gcc 16.2.1 / gcc-15 only). A local --write run therefore produces two classes of false delta on top of the real ones: every generated model TU moves to a different build-dir path, and several C++ TUs the diff never touches drift upward purely from the newer libstdc++ headers. Committing that would encode paths CI never emits and would silently raise the ceiling on untouched files, so the local write is discarded and master's baseline is unchanged. ADR-1142 also forbids hand-editing a baseline.

The Tidy Ratchet job is expected to exit 3 on the first non-draft run and upload the correct measurement as the tidy-ratchet-cpu.json artifact — that file is the baseline to commit, exactly as the workflow step "Upload measurement (commit it as the new baseline when the ratchet asks)" describes, and exactly the flow PR #1192 used. All nine touched files measure 0 locally with clang-tidy 22.1.8 (the version the baseline records), so the CI measurement should show 0 for each of them and no increase anywhere else.

Type

  • refactor — lint-debt cleanup of the dnn + psnr buckets, plus one test-harness bug fix.

Checklist

  • Commits follow Conventional Commits.
  • make format-check green; pre-commit run --files green on every touched file (clang-format, markdownlint-cli2, shellcheck, semgrep, copyright, state.md-id and ADR guards).
  • Unit tests: meson test -C btOk 129 / Fail 0 on a CPU-only -Denable_cuda=false -Denable_sycl=false -Db_lto=false build, and make VENV=… test-netflix-golden (271 passed / 12 skipped / 0 failed). core/test/dnn/test_cli.sh now correctly reports meson-skip (77) on a DNN-disabled build instead of failing.
  • Docs — no docs needed: internal refactor plus a test-harness fix; no CLI flag, public C API, meson_options.txt entry, feature extractor, backend or output-schema change. The maintainer-facing notes land in the two AGENTS.md files and docs/rebase-notes.md.
  • SIMD/GPU, twins, new C sources, breaking change, ADR — n/a: no SIMD or GPU path touched (CPU scalar and shared code only), no twin drift (the CUDA/SYCL/HIP psnr twins are untouched), no new C source files, no API or behaviour change, and no new ADR (this is ratchet work under the existing ADR-1142 / ADR-0141 / ADR-0278 / ADR-1138).

Bug-status hygiene (ADR-0165)

  • docs/state.md — one new Recently closed row, T-DNN-TESTCLI-PROBE-NEVER-SKIPS-2026-09-05, covering the test_cli.sh probe defect, its root cause in configure_tiny_model()'s position in core/tools/vmaf.cpp, the fix and the rc=77 verification, citing PR #1323.

Netflix golden-data gate (ADR-0024)

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.

Deep-dive deliverables (ADR-0108)

  • Research digest — no digest needed: mechanical lint-debt cleanup against an already-decided policy (ADR-1142); every finding class already has a settled in-tree remedy.
  • Decision matrix — no alternatives: each clang-tidy finding has exactly one sanctioned remedy in this tree (refactor, or the ADR-0278 / ADR-0461 / ADR-1138 citation that already covers the identical construct elsewhere), and the task brief explicitly scopes this work as "no ADR".
  • AGENTS.md invariant notecore/src/dnn/AGENTS.md (model_loader lint shape, the ADR-1138 NULL bracket, and the test_cli.sh probe contract) and core/src/feature/AGENTS.md (psnr bucket lint shape + ADR-1138 bracket).
  • Reproducer / smoke-test command — below.
  • CHANGELOG fragmentchangelog.d/changed/tidy-wave2-dnn-psnr.md
  • Rebase notedocs/rebase-notes.md entry "core/src/feature/psnr_tools.cpp, psnr.c, integer_psnr.c, float_psnr.c — ADR-1142 tidy ratchet"

Reproducer

# 1. CPU build, the flags CI's tidy lane uses (-Db_lto=false: ADR-1172's
#    -flto=4 is rejected by clang and breaks clang-tidy on every TU).
meson setup bt core -Denable_cuda=false -Denable_sycl=false -Db_lto=false
nice -n 10 ninja -C bt -j 4          # expect: 0 warnings, 0 errors

# 2. Every touched source measures 0 clang-tidy warnings (clang-tidy 22.1.8).
for f in core/src/dnn/model_loader.c core/src/dnn/dnn_api.c \
         core/src/dnn/dnn_attach_api.c core/src/dnn/onnx_scan.c \
         core/src/dnn/op_allowlist.c core/src/feature/psnr_tools.cpp \
         core/src/feature/integer_psnr.c core/src/feature/float_psnr.c \
         core/src/feature/psnr.c; do
  echo "=== $f"; clang-tidy -p bt --quiet "$f" 2>/dev/null | grep -E 'warning:|error:'
done
# expect: nine "=== <file>" lines and nothing else.

# 3. No C translation unit uses the C23 keyword (ADR-1138 / Windows MSVC lane).
grep -rnE '(^|[^-A-Za-z_])nullptr([^A-Za-z_]|$)' core/src/dnn/*.c \
     core/src/feature/*psnr*.c | grep -v 'modernize-use-nullptr'
# expect: no output.

# 4. psnr is numerically inert — scores byte-identical before/after.
./bt/tools/vmaf \
  --reference python/test/resource/yuv/src01_hrc00_576x324.yuv \
  --distorted python/test/resource/yuv/src01_hrc01_576x324.yuv \
  --width 576 --height 324 --pixel_format 420 --bitdepth 8 \
  --feature psnr --precision=max --json --output /tmp/psnr.json
grep -vE '"(fps|version)"' /tmp/psnr.json | sha256sum

# 5. The test_cli.sh probe now skips instead of failing on a DNN-disabled build.
VMAF_BIN=$PWD/bt/tools/vmaf bash core/test/dnn/test_cli.sh; echo "rc=$?"
# expect: "libvmaf built without DNN support; skipping DNN CLI smoke", rc=77

# 6. Full suites.
meson test -C bt                             # expect: Ok 129, Fail 0
make VENV="$PWD/.venv" test-netflix-golden   # expect: 271 passed, 12 skipped

🤖 Generated with Claude Code

@lusoris lusoris added this to the 1.0.0 — First release milestone Sep 5, 2026
@lusoris
lusoris force-pushed the refactor/tidy-wave2-dnn-psnr branch 2 times, most recently from 66edbbb to 7eba02c Compare September 6, 2026 03:00
lusoris pushed a commit that referenced this pull request Sep 6, 2026
The wave-2 tidy pass rewrote 90 `NULL`s to the C23 `nullptr` keyword
across seven C translation units (`core/src/dnn/{dnn_api,
dnn_attach_api,model_loader,onnx_scan,op_allowlist}.c`,
`core/src/feature/{float_psnr,integer_psnr}.c`). ADR-1138 settled that
question for C: `Build — Windows MSVC + CUDA (build only)` is a required
status check and compiles these TUs with cl.exe, whose documented
/std:clatest C23 feature set does not include `nullptr`. PR #1192 had to
revert exactly this rewrite after all three Windows legs failed with
"use of undeclared identifier nullptr", which is why the ADR exists.

Restore `NULL` everywhere and give each of the seven files the
file-scoped `NOLINTBEGIN(modernize-use-nullptr)` … `NOLINTEND` bracket
the ADR prescribes, worded as in `core/src/dnn/ort_backend.c` and
`core/src/feature/integer_adm.c`. `psnr_tools.cpp` is C++ and keeps
`nullptr` — ADR-0915's ratchet still covers it in full.

The revert re-opened one finding the keyword rewrite had masked:
`vmaf_dnn_session_open()` is 114 lines against the 60-line
readability-function-size budget. Split it into `resolve_load_path()`
(the ADR-0174 int8 sibling lookup and its fp32 fallback) and
`setup_luma_fast_path()` (the NCHW [1,1,H,W] shape check and scratch
allocation), which also retires the `goto fail` ladder. Behaviour is
unchanged: the same validation order, the same ownership on every error
path, the same -ENAMETOOLONG / -ENOMEM / -ENOTSUP contracts.

Also record the invariant in `core/src/dnn/AGENTS.md` and
`core/src/feature/AGENTS.md`, correct the `docs/rebase-notes.md` bullet
that told a future rebaser to convert upstream `NULL`s to the keyword,
cite `PR #1323` rather than the branch name in the `docs/state.md` row,
and refresh the changelog fragment.

Verified: ninja 0 warnings; `meson test -C bt` 129/129 Ok, 0 Fail
(all 7 dnn tests included); clang-tidy -p bt reports 0 findings on all
nine touched sources; pre-commit clean on every touched file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the refactor/tidy-wave2-dnn-psnr branch from 7eba02c to 35ec49c Compare September 6, 2026 09:50
lusoris pushed a commit that referenced this pull request Sep 6, 2026
The wave-2 tidy pass rewrote 90 `NULL`s to the C23 `nullptr` keyword
across seven C translation units (`core/src/dnn/{dnn_api,
dnn_attach_api,model_loader,onnx_scan,op_allowlist}.c`,
`core/src/feature/{float_psnr,integer_psnr}.c`). ADR-1138 settled that
question for C: `Build — Windows MSVC + CUDA (build only)` is a required
status check and compiles these TUs with cl.exe, whose documented
/std:clatest C23 feature set does not include `nullptr`. PR #1192 had to
revert exactly this rewrite after all three Windows legs failed with
"use of undeclared identifier nullptr", which is why the ADR exists.

Restore `NULL` everywhere and give each of the seven files the
file-scoped `NOLINTBEGIN(modernize-use-nullptr)` … `NOLINTEND` bracket
the ADR prescribes, worded as in `core/src/dnn/ort_backend.c` and
`core/src/feature/integer_adm.c`. `psnr_tools.cpp` is C++ and keeps
`nullptr` — ADR-0915's ratchet still covers it in full.

The revert re-opened one finding the keyword rewrite had masked:
`vmaf_dnn_session_open()` is 114 lines against the 60-line
readability-function-size budget. Split it into `resolve_load_path()`
(the ADR-0174 int8 sibling lookup and its fp32 fallback) and
`setup_luma_fast_path()` (the NCHW [1,1,H,W] shape check and scratch
allocation), which also retires the `goto fail` ladder. Behaviour is
unchanged: the same validation order, the same ownership on every error
path, the same -ENAMETOOLONG / -ENOMEM / -ENOTSUP contracts.

Also record the invariant in `core/src/dnn/AGENTS.md` and
`core/src/feature/AGENTS.md`, correct the `docs/rebase-notes.md` bullet
that told a future rebaser to convert upstream `NULL`s to the keyword,
cite `PR #1323` rather than the branch name in the `docs/state.md` row,
and refresh the changelog fragment.

Verified: ninja 0 warnings; `meson test -C bt` 129/129 Ok, 0 Fail
(all 7 dnn tests included); clang-tidy -p bt reports 0 findings on all
nine touched sources; pre-commit clean on every touched file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the refactor/tidy-wave2-dnn-psnr branch from 35ec49c to ffc7cb8 Compare September 6, 2026 18:26
Lusoris and others added 11 commits September 7, 2026 08:56
…ions

Clean the psnr bucket of core to the ADR-1142 whole-tree clang-tidy
ratchet:

- psnr_tools.cpp: designated initialisers for the format table
  (modernize-use-designated-initializers, 24 warnings).
- integer_psnr.c / float_psnr.c: nullptr sentinels; the cross-TU
  feature-extractor registry symbols carry the ADR-0278 NOLINT
  citation already used by cambi.c and float_ssim.c.
- psnr.c: include its own psnr.h so compute_psnr()'s external
  linkage is declared, not inferred.

Numerically inert: the format table keeps identical peak / psnr_max
values and no arithmetic changed.
… presets

Clean core/src/dnn/model_loader.c to the ADR-1142 whole-tree clang-tidy
ratchet (29 baseline warnings):

- vmaf_dnn_sidecar_load (202 lines / 167 statements / 37 branches) is
  split into sidecar_json_path(), slurp_sidecar_json() and one
  parse_sidecar_*() helper per sidecar field group.
- vmaf_dnn_verify_signature (130 lines / 18 branches) is split into
  default_registry_path(), resolve_bundle_abs() and run_cosign_verify().
- codec_block_preset_ordinal (105 lines / 127 statements / 40 branches)
  becomes a table of (encoder family -> preset ordinal) rows; libsvtav1
  keeps its numeric parse in svtav1_preset_ordinal().
- vmaf_dnn_codec_block_fill loses a nesting level via lower_copy() and
  codec_vocab_index().
- extract_string_array / extract_float_array share json_array_begin().
- str_to_lower calls (tolower) parenthesised: glibc's five-level
  <ctype.h> macro was the only source of the nesting-depth finding.
- NULL -> nullptr throughout; the two getenv() call sites carry the
  ADR-0461 caller-contract NOLINT already used by gpu_dispatch_env.cpp
  and mcp/compute_vmaf.c.

Behaviour-preserving: every helper keeps the original control flow,
error codes and float arithmetic (ordinal / 9.0f) of the code it
replaces.
…ocation

The probe ran `vmaf --tiny-model /dev/null` and looked for the "built
without DNN support" diagnostic. That command never reaches the check:
configure_tiny_model() in core/tools/vmaf.cpp runs after argument
validation and after the inputs are opened, so the bare probe dies on
"Reference .y4m or .yuv (-r/--reference) is required".

On any -Denable_dnn=disabled build — what the CI CPU/tidy lanes
configure, and what 'auto' resolves to without ONNX Runtime — the script
therefore continued as if DNN were available and the ADR-0524 NR block
exited 1 instead of meson-skipping.

The probe now issues an otherwise-valid invocation (--no-reference with
the src01_hrc01 fixture as --distorted, --tiny-model /dev/null), which
reaches the availability check. DIST_YUV moves up to be the single
definition of the fixture path.

Verified: VMAF_BIN=core/build/tools/vmaf bash core/test/dnn/test_cli.sh
-> "libvmaf built without DNN support; skipping DNN CLI smoke", rc=77
(was rc=1).

Closes T-DNN-TESTCLI-PROBE-NEVER-SKIPS-2026-09-05.
extract_string_array() was still 10 lines over the ADR-1142 budget; the
per-element parse moves into json_dup_string_elem(). The quote check
still runs before the `cnt >= max` check so a malformed element past the
cap keeps returning -EINVAL rather than -ERANGE.

vmaf_dnn_verify_signature() was still 18 branches; the registry lookup
(default path, slurp, bundle lookup, path resolution) moves into
lookup_bundle_abs(), leaving the function as bundle -> stat -> cosign.

core/src/dnn/model_loader.c now measures 0 clang-tidy warnings.
- changelog.d/changed/tidy-wave2-dnn-psnr.md + regenerated CHANGELOG.md
  Unreleased block.
- docs/rebase-notes.md: the psnr bucket is upstream-mirrored; record the
  designated-initialiser table, the psnr.h self-include and the nullptr /
  ADR-0278 NOLINT shape so a future port-upstream-commit does not
  silently revert them.
- core/src/feature/AGENTS.md: same invariants, next to the existing
  ssim / ms_ssim cross-TU NOLINT note.
scripts/ci/assertion-density.sh flagged the post-split
vmaf_dnn_sidecar_load: at 30 lines it is still over the 20-line bar but
its precondition asserts had moved into the helpers. Re-assert the two
input pointers plus the two intermediate postconditions
(non-empty sidecar path, non-null slurped buffer) that the helpers
guarantee.

scripts/ci/assertion-density.sh: PASS — every fork-added function >=20
lines has >=1 assert (252 asserts / 151 functions, avg 1.67).
The wave-2 tidy pass rewrote 90 `NULL`s to the C23 `nullptr` keyword
across seven C translation units (`core/src/dnn/{dnn_api,
dnn_attach_api,model_loader,onnx_scan,op_allowlist}.c`,
`core/src/feature/{float_psnr,integer_psnr}.c`). ADR-1138 settled that
question for C: `Build — Windows MSVC + CUDA (build only)` is a required
status check and compiles these TUs with cl.exe, whose documented
/std:clatest C23 feature set does not include `nullptr`. PR #1192 had to
revert exactly this rewrite after all three Windows legs failed with
"use of undeclared identifier nullptr", which is why the ADR exists.

Restore `NULL` everywhere and give each of the seven files the
file-scoped `NOLINTBEGIN(modernize-use-nullptr)` … `NOLINTEND` bracket
the ADR prescribes, worded as in `core/src/dnn/ort_backend.c` and
`core/src/feature/integer_adm.c`. `psnr_tools.cpp` is C++ and keeps
`nullptr` — ADR-0915's ratchet still covers it in full.

The revert re-opened one finding the keyword rewrite had masked:
`vmaf_dnn_session_open()` is 114 lines against the 60-line
readability-function-size budget. Split it into `resolve_load_path()`
(the ADR-0174 int8 sibling lookup and its fp32 fallback) and
`setup_luma_fast_path()` (the NCHW [1,1,H,W] shape check and scratch
allocation), which also retires the `goto fail` ladder. Behaviour is
unchanged: the same validation order, the same ownership on every error
path, the same -ENAMETOOLONG / -ENOMEM / -ENOTSUP contracts.

Also record the invariant in `core/src/dnn/AGENTS.md` and
`core/src/feature/AGENTS.md`, correct the `docs/rebase-notes.md` bullet
that told a future rebaser to convert upstream `NULL`s to the keyword,
cite `PR #1323` rather than the branch name in the `docs/state.md` row,
and refresh the changelog fragment.

Verified: ninja 0 warnings; `meson test -C bt` 129/129 Ok, 0 Fail
(all 7 dnn tests included); clang-tidy -p bt reports 0 findings on all
nine touched sources; pre-commit clean on every touched file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the refactor/tidy-wave2-dnn-psnr branch from ffc7cb8 to 55dece8 Compare September 7, 2026 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant