Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
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