Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion .codex/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ make test-netflix-golden # Netflix CPU golden-data gate (see §8)
## 4. Lint / format

```text
make preflight # CI compiler matrix locally: clang, 32-bit, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make preflight # CI compiler matrix locally: clang, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make lint # configured native + Python, shell, Markdown, Go and docs checks
make format # clang-format + black + ruff (writes)
make format-check # dry-run (CI / pre-commit)
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/hiss-invariants.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ make test-netflix-golden # Netflix CPU golden-data gate (see §8)
## 4. Lint / format

```text
make preflight # CI compiler matrix locally: clang, 32-bit, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make preflight # CI compiler matrix locally: clang, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make lint # configured native + Python, shell, Markdown, Go and docs checks
make format # clang-format + black + ruff (writes)
make format-check # dry-run (CI / pre-commit)
Expand Down
2 changes: 1 addition & 1 deletion .gemini/GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ make test-netflix-golden # Netflix CPU golden-data gate (see §8)
## 4. Lint / format

```text
make preflight # CI compiler matrix locally: clang, 32-bit, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make preflight # CI compiler matrix locally: clang, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make lint # configured native + Python, shell, Markdown, Go and docs checks
make format # clang-format + black + ruff (writes)
make format-check # dry-run (CI / pre-commit)
Expand Down
74 changes: 31 additions & 43 deletions .github/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ must keep enumerating from `meson test --list`.

## Windows CUDA setup path (ADR-0664)

`libvmaf-build-matrix.yml` installs CUDA 13.2.0 directly in
`Build — Windows MSVC + CUDA (build only)` leg. Never restore
`Jimver/cuda-toolkit` for that Windows leg without superseding ADR
and green required Windows CUDA run: v0.2.35 failed before setup on
`libvmaf-build-matrix.yml` installs CUDA 13.3.1 directly in the
`Windows MSVC+CUDA` leg. Do not restore
`Jimver/cuda-toolkit` for that Windows leg without a superseding ADR
and a green required Windows CUDA run: v0.2.35 failed before setup on
PR #1463, blocked merge train without Meson or compiler output.

Linux CUDA legs still use `Jimver/cuda-toolkit`; ADR-0664 only
Expand Down Expand Up @@ -439,14 +439,13 @@ step in `libvmaf-build` job:

Rebase-sensitive invariants:

- `if:` triple condition is load-bearing. **All three clauses must be
preserved together.** Dropping `github.event_name == 'workflow_dispatch'`
causes step to open blocking SSH session on every failing PR push,
stranding macOS runner for up to 30 minutes per failure.
- Step must remain **after** `Run tests` step and **before**
`Run Vulkan smoke tests (macOS MoltenVK)` step so it fires only when
test failure has already set job status to `failure()`.
- Action is pinned to commit SHA per fork's Renovate
- `if:` triple condition load-bearing. **All three clauses preserved
together.** Dropping `github.event_name == 'workflow_dispatch'` causes step
to open blocking SSH session on every failing PR push. Strands macOS runner
up to 30 minutes per failure.
- Step stays **after** `Run tests` step -> fires only when test failure already
set job status to `failure()`.
- Action pinned to commit SHA per fork's Renovate
`helpers:pinGitHubActionDigests` policy. Renovate will propose digest bumps;
accept only after verifying new SHA corresponds to signed release tag.
- Step is intentionally present in shared matrix job (not separate
Expand All @@ -456,33 +455,19 @@ Rebase-sensitive invariants:
See [ADR-0626](../docs/adr/0626-macos-ci-tmate-debug-on-failure.md) and
[`docs/development/ci-tmate-debug.md`](../docs/development/ci-tmate-debug.md).

## macOS Vulkan-via-MoltenVK lane (ADR-0338)

`libvmaf-build-matrix.yml` carries advisory lane
`Build — macOS Vulkan via MoltenVK (advisory)` that runs on
`macos-latest` (Apple Silicon). Rebase-sensitive invariants:

- Lane is gated `continue-on-error: ${{ matrix.experimental ==
true && matrix.moltenvk == true }}`. Compound predicate is
load-bearing — matrix has other `experimental: true` rows
(macOS DNN lane) that must keep their default fail-fast
behaviour. Naive simplification to `${{ matrix.experimental }}`
would silently make those other rows advisory.
- `VK_ICD_FILENAMES` MUST point at
`/opt/homebrew/etc/vulkan/icd.d/MoltenVK_icd.json` — homebrew
formula `molten-vk` lays JSON under `etc/vulkan/`, NOT
`share/vulkan/`. Never "fix" path; verify against
`Formula/m/molten-vk.rb` if in doubt.
- Lane must NOT be added to `required-aggregator.yml` until one
green run lands on `master`. See ADR-0338 §Decision.
- Existing `Run tests` / cache / tox steps gate on
`!matrix.moltenvk` — moltenvk lane runs its own dedicated
Vulkan-only smoke step. Never unify or lane will try to run
tox tests against Apple-Vulkan build, which is not lane's
contract.

See [ADR-0338](../docs/adr/0338-macos-vulkan-via-moltenvk-lane.md)
and [`docs/backends/vulkan/moltenvk.md`](../docs/backends/vulkan/moltenvk.md).
## Build matrix of record (ADR-1259)

[ADR-1259](../docs/adr/1259-ci-build-matrix-as-it-runs.md) lists every lane in
`libvmaf-build-matrix.yml` and `build.yml` and which ones are required.
ADR-0689, ADR-0691, ADR-0710 and ADR-0728 are superseded: do not remove a lane
on their authority, and do not let a merge resolution drop or restore a lane
without an ADR. That is how `384d97d03` undid two of them.

The MoltenVK lane (ADR-0338) went with the Vulkan backend (ADR-0726). The
`libvmaf-build` job's `continue-on-error` is now
`${{ matrix.experimental == true }}`, so the two `experimental: true` rows,
`macOS clang` and `macOS clang+DNN`, are advisory: their failure does not
fail the workflow run. Neither is a required check.

## Renovate (ADR-0363) supersedes Dependabot

Expand All @@ -495,7 +480,9 @@ Note: pin updates to `codeql-action/upload-sarif` now arrive via Renovate
- [ADR-1247](../docs/adr/1247-scorecard-exact-head-gates.md) — current OSSF
Scorecard policy; ADR-0263 is superseded
- [ADR-0338](../docs/adr/0338-macos-vulkan-via-moltenvk-lane.md) — macOS
Vulkan-via-MoltenVK advisory lane
Vulkan-via-MoltenVK advisory lane (removed with the Vulkan backend, ADR-0726)
- [ADR-1259](../docs/adr/1259-ci-build-matrix-as-it-runs.md) — the CI build
matrix as it runs
- [Research-0002](../docs/research/0002-automated-rule-enforcement.md) — investigation
- [Research-0053](../docs/research/0053-ossf-scorecard-investigation.md) —
OSSF Scorecard per-check breakdown
Expand Down Expand Up @@ -593,9 +580,10 @@ Unknown attribute kind (102)
```

Pass `-Db_lto=false` on every icpx/SYCL `meson setup` in CI. Both SYCL legs of
`libvmaf-build-matrix.yml` already do, and `Clang-Tidy SYCL (Changed Files,
Advisory)` now does too. Pinning older oneAPI does not help — mismatch
is against *system* linker plugin, not specific compiler release.
`libvmaf-build-matrix.yml` already do, as do `build.yml`'s `Linux Intel LLVM`
row and the `Tidy SYCL (advisory)` job. Pinning an older oneAPI does not
help — the mismatch is against the *system* linker plugin, not a specific
compiler release.

## Scorecard scope and report authenticity (ADR-1247)

Expand Down
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ make test-netflix-golden # Netflix CPU golden-data gate (see §8)
## 4. Lint / format

```text
make preflight # CI compiler matrix locally: clang, 32-bit, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make preflight # CI compiler matrix locally: clang, sanitizers, MSVC-hostile constructs, tidy, cppcheck
make lint # configured native + Python, shell, Markdown, Go and docs checks
make format # clang-format + black + ruff (writes)
make format-check # dry-run (CI / pre-commit)
Expand Down
26 changes: 15 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# VMAFX build matrix — 1 job per OS (ADR-0710)
# VMAFX build matrix — 1 job per OS (ADR-0710, recorded in ADR-1259)
#
# Supersedes libvmaf-build-matrix.yml (ADR-0689 dedup pass → ADR-0710 slim-down).
# Three matrix rows only:
# - linux-full: Intel LLVM + ALL Linux backends (CUDA + SYCL + HIP + CPU + DNN)
# - macos-cpu-metal: Apple Clang + CPU + Metal scaffold
# - windows-msvc-cuda: MSVC + CPU + CUDA
# Runs alongside libvmaf-build-matrix.yml, which keeps the per-backend, ARM,
# static, DNN and required lanes; ADR-0710 meant this file to replace it, but
# that never happened and ADR-1259 records both as they run.
# Three matrix rows, none of them a required check:
# - Linux Intel LLVM: Intel LLVM + ALL Linux backends (CUDA + SYCL + HIP + CPU + DNN)
# - macOS Clang+Metal: Apple Clang + CPU + Metal scaffold
# - Windows MSVC+CUDA (full): MSVC + CPU + CUDA, static, with the CPU
# tests. Named apart from the required `Windows MSVC+CUDA` lane in
# libvmaf-build-matrix.yml: the aggregator keeps one run per name, so a
# shared name let either job mask the other's failure
# (scripts/ci/check-aggregator-names.sh now rejects a shared required name).
#
# Rationale: container-first VMAFX philosophy (ADR-0686, ADR-0701) means the
# production artefact is the `vmafx-dev-mcp` image, not a per-backend binary.
# Per-backend build legs (SYCL-only, CUDA-only, HIP-only, Vulkan-only, etc.)
# are folded into the single Linux full build. ARM, i686, static-only, DNN-
# only, and MoltenVK advisory legs are retired. See ADR-0710.
# production artefact is the `vmafx-dev-mcp` image, not a per-backend binary;
# these rows prove the whole stack builds on each OS.
#
# Netflix golden assertions are pinned to the dedicated CPU/GCC jobs in
# tests-and-quality-gates.yml and libvmaf-build-matrix.yml. The all-backend
Expand Down Expand Up @@ -98,7 +102,7 @@ jobs:
# windows-2025 runner). CPU-only meson tests are run after build.
# ──────────────────────────────────────────────────────────────
- os: windows-2025
name: Windows MSVC+CUDA
name: Windows MSVC+CUDA (full)
cuda: true
windows: true
meson_extra: >-
Expand Down
68 changes: 21 additions & 47 deletions .github/workflows/libvmaf-build-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,6 @@ jobs:
CXX: ccache clang++-22
name: Ubuntu ARM clang

# --- i686 (32-bit x86) build — reproduces Netflix#1481 ---
# Verifies libvmaf still compiles on 32-bit x86 with
# -Denable_asm=false. The documented workaround for the
# `_mm256_extract_epi64` implicit-declaration failure on
# 32-bit x86 is to disable the asm path; this job pins
# that contract so any future 32-bit-only regression trips
# the matrix. Tests are skipped (meson cross-build marks
# them SKIP 77 — host can run i686 binaries natively but
# meson doesn't know that). See ADR-0151.
- os: ubuntu-latest
CC: ccache gcc-14
CXX: ccache g++-14
i686: true
meson_extra: --cross-file=build-aux/i686-linux-gnu.ini -Denable_asm=false
name: Ubuntu i686 gcc

# --- DNN-enabled builds (ADR-0120) ---
# Build with -Denable_dnn=enabled across compiler/OS combinations
# to ensure the ORT C-API surface compiles on every CPU leg, not
Expand Down Expand Up @@ -273,7 +257,7 @@ jobs:
pip install meson

- name: Install dependencies (ubuntu)
if: ${{ (startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.i686 && !matrix.hip) && steps.impact.outputs.c_core == 'true' }}
if: ${{ (startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip) && steps.impact.outputs.c_core == 'true' }}
run: |
sudo apt-get update
sudo -E apt-get -yq install ccache ninja-build nasm libomp-dev pkg-config
Expand All @@ -297,14 +281,6 @@ jobs:
*clang) sudo -E apt-get -yq install clang ;;
esac

- name: Install dependencies (ubuntu i686)
if: ${{ (matrix.i686) && steps.impact.outputs.c_core == 'true' }}
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo -E apt-get -yq install ccache ninja-build pkg-config \
gcc g++ gcc-multilib g++-multilib

- name: Install dependencies (mac)
if: ${{ (matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true' }}
env:
Expand Down Expand Up @@ -378,7 +354,7 @@ jobs:
# to preserve the rest of the DNN suite for macOS coverage.
brew install -q onnxruntime
ORT_PREFIX=$(brew --prefix onnxruntime)
echo "PKG_CONFIG_PATH=${ORT_PREFIX}/lib/pkgconfig" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=${ORT_PREFIX}/lib/pkgconfig" >> "$GITHUB_ENV"

# ---------- Intel oneAPI (SYCL) ----------
# Pinned to oneAPI 2025.3 (icpx 2025.3.x) and Level Zero v1.28.0.
Expand Down Expand Up @@ -415,10 +391,10 @@ jobs:
git clone --depth=1 --branch "v${LEVEL_ZERO_VERSION}" \
https://github.com/oneapi-src/level-zero.git /tmp/level-zero
cmake -S /tmp/level-zero -B /tmp/level-zero/build -DCMAKE_INSTALL_PREFIX=/usr
cmake --build /tmp/level-zero/build -j$(nproc)
cmake --build /tmp/level-zero/build -j"$(nproc)"
sudo cmake --install /tmp/level-zero/build
rm -rf /tmp/level-zero
echo "/opt/intel/oneapi/compiler/latest/bin" >> $GITHUB_PATH
echo "/opt/intel/oneapi/compiler/latest/bin" >> "$GITHUB_PATH"
echo "/opt/intel/oneapi/compiler/latest/lib" | sudo tee /etc/ld.so.conf.d/oneapi.conf
sudo ldconfig

Expand Down Expand Up @@ -525,7 +501,7 @@ jobs:
source /opt/intel/oneapi/setvars.sh
fi
meson setup core core/build --buildtype release \
--prefix $PWD/install \
--prefix "$PWD/install" \
-Denable_float=true \
${{ matrix.meson_extra }}

Expand All @@ -552,7 +528,7 @@ jobs:
run: |
export PKG_CONFIG_PATH=$PWD/install/lib/pkgconfig:$PWD/install/lib/x86_64-linux-gnu/pkgconfig
echo "=== libvmaf.pc ==="
cat $PWD/install/lib/pkgconfig/libvmaf.pc || cat $PWD/install/lib/x86_64-linux-gnu/pkgconfig/libvmaf.pc
cat "$PWD/install/lib/pkgconfig/libvmaf.pc" || cat "$PWD/install/lib/x86_64-linux-gnu/pkgconfig/libvmaf.pc"
echo ""
echo "=== pkg-config --static --libs libvmaf ==="
pkg-config --static --libs libvmaf
Expand Down Expand Up @@ -585,8 +561,12 @@ jobs:
# SYCL/CUDA legs, so the archive holds plain objects rather than LTO
# IR — a plugin mismatch is not in play, but matching the compiler
# still costs nothing.)
${CC:-cc} /tmp/pc_static_smoke.c $(pkg-config --cflags libvmaf) \
$(pkg-config --static --libs libvmaf) -o /tmp/pc_static_smoke
# pkg-config prints space-separated flags; read them into arrays
# rather than relying on unquoted word splitting.
read -ra pc_cflags <<< "$(pkg-config --cflags libvmaf)"
read -ra pc_libs <<< "$(pkg-config --static --libs libvmaf)"
${CC:-cc} /tmp/pc_static_smoke.c "${pc_cflags[@]}" "${pc_libs[@]}" \
-o /tmp/pc_static_smoke
echo "static link OK"

# DNN legs: run the dedicated dnn suite first so its logs are easy
Expand All @@ -600,14 +580,11 @@ jobs:
# user's $HOME so a bare `sudo meson` reports "command not found".
# Sudo is needed because the preceding `sudo ninja install` step
# left build artifacts owned by root.
run: sudo $(which meson) test -C core/build --suite=dnn --print-errorlogs
run: sudo "$(which meson)" test -C core/build --suite=dnn --print-errorlogs

# CPU-only: full test suite + tox (skipped for i686 cross-build
# because meson marks cross-compiled tests SKIP 77 regardless of
# whether the host can actually run them; the build itself is
# what Netflix#1481 needs to pin).
# CPU-only: full test suite + tox.
- name: Run tests
if: ${{ (!matrix.sycl && !matrix.cuda && !matrix.hip && !matrix.i686) && steps.impact.outputs.c_core == 'true' }}
if: ${{ (!matrix.sycl && !matrix.cuda && !matrix.hip) && steps.impact.outputs.c_core == 'true' }}
run: sudo ninja -vC core/build test

# ---------- SSH debug session (macOS × workflow_dispatch only) ----------
Expand Down Expand Up @@ -650,7 +627,7 @@ jobs:
# Insulates the tox lanes from the recurring HTTP-502s on
# raw.githubusercontent.com when fetching python/test/resource/
# fixtures via download_reactively (compat/python-vmaf/config.py).
if: ${{ ((startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip && !matrix.i686) || matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true' }}
if: ${{ ((startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip) || matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: python/test/resource
Expand All @@ -666,20 +643,20 @@ jobs:
# never repaired and the test fails with "no frames decoded". The
# success()-gated save below stops new poisoning; this heals caches
# already poisoned, which otherwise need a manual cache deletion.
if: ${{ ((startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip && !matrix.i686) || matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true' }}
if: ${{ ((startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip) || matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true' }}
run: bash scripts/ci/prune-corrupt-fixtures.sh python/test/resource

- name: Run tox tests (ubuntu)
if: ${{ (startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip && !matrix.i686) && steps.impact.outputs.c_core == 'true' }}
if: ${{ (startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip) && steps.impact.outputs.c_core == 'true' }}
run: |
mkdir -p ~/.ccache && sudo chown -R $(whoami) ~/.ccache
mkdir -p ~/.ccache && sudo chown -R "$(whoami)" ~/.ccache
pip install tox
tox -c python

- name: Run tox tests (mac)
if: ${{ (matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true' }}
run: |
mkdir -p ~/.ccache && sudo chown -R $(whoami) ~/.ccache
mkdir -p ~/.ccache && sudo chown -R "$(whoami)" ~/.ccache
pip install tox
PATH=$(brew --prefix)/opt/llvm/bin:$PATH \
CC=$(brew --prefix)/opt/llvm/bin/clang \
Expand All @@ -689,7 +666,7 @@ jobs:
- name: Save Netflix vmaf_resource fixtures
# success() only: a cancelled or failing run must never publish a
# partial fixture tree under this key. Placed after both tox legs.
if: ${{ success() && (((startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip && !matrix.i686) || matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true') && steps.fixtures.outputs.cache-hit != 'true' }}
if: ${{ success() && (((startsWith(matrix.os, 'ubuntu') && !matrix.sycl && !matrix.cuda && !matrix.hip) || matrix.os == 'macos-latest') && steps.impact.outputs.c_core == 'true') && steps.fixtures.outputs.cache-hit != 'true' }}
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: python/test/resource
Expand Down Expand Up @@ -745,9 +722,6 @@ jobs:
fail-fast: false
matrix:
include:
# - msystem: MINGW32
# MINGW_PACKAGE_PREFIX: mingw-w64-i686
# CFLAGS: -msse2 -mfpmath=sse -mstackrealign
# required-aggregator
- name: Windows MinGW64
msystem: MINGW64
Expand Down
Loading
Loading