ADR-1474: A fork-created header that replays upstream arithmetic is EUPL-1.2 AND the licences of exactly that code, and the relicensing check becomes a required CI job¶
- Status: Accepted
- Date: 2026-10-02
- Deciders: lusoris
- Tags:
license,compliance,ci,rc3,fork-local
Context¶
ADR-1250 decides every file's licence by provenance and makes the decision executable: scripts/dev/relicense_fork_files.py --check fails when a file's header disagrees with it. ADR-1250 left the check out of CI ("until it is, a new fork-authored file can arrive with the wrong tag and nothing will say so"), and two weeks of work showed what that costs: on 2026-10-02 the check reported 41 pending files on master. Ten were fork files with the wrong tag (PR #1876). The other 31 exposed three things ADR-1250 does not settle.
Helper headers created under EUPL-1.2 inside kernel directories. ADR-1250 says a file that carries someone else's code "keeps the terms it has" and does not move to EUPL-1.2. Seven headers were created after the relicensing with an EUPL-1.2 tag in a kernel directory whose family names an upstream origin, so the tool wanted to add that origin's notices to all seven. Read against their sources they are two kinds:
- three reproduce a piece of a reference extractor's arithmetic for a GPU twin:
hip/float_ssim/ssim_decimate.h(the boundary rule and window loop ofiqa/convolve.candiqa/decimate.c, onpicture_copy()values withssim.c's box tap),metal/float_ms_ssim_option_semantics.h(themax_dbformula offloat_ms_ssim.c) andsycl/sycl_integer_ssim_math.h(the per-pixel term ofinteger_ssim.c::ssim_reduce_row_range()on 64-bit integers). They have EUPL terms, so "keeps the terms it has" keeps EUPL; they carry upstream code, so the upstream notice and licence are owed. The tool's answer, the upstream notices plusEUPL-1.2 AND <upstream licences>, was one of three readings; - four hold none of the reference's code:
cuda/speed/speed_cuda_params.his the kernel argument block and thread counts of the fork's CUDA SpEED chain, andhip/float_adm/float_adm_hip_math.h,hip/integer_ciede/ciede_hip_math.handsycl/sycl_ciede_math.hdefine the device's primitives as macros and include a shared header (float_adm_gpu_common.h,ciede_ff_math.h) that holds the arithmetic and already carries the upstream notices. A notice added to them would name a copyright holder for code that is not in the file.
All paths are under core/src/feature/.
Family rules are coarser than helper headers. A family credits a kernel file with every origin of its metric: the CUDA, HIP and SYCL SSIM files cross the float (Netflix, IQA) and integer (Xiph.Org) lineages, so the gpu-ssim family names all three. A helper header holds one part. The family would have credited sycl_integer_ssim_math.h (the integer term only) to Netflix and Tom Distler, ssim_decimate.h and sycl_ssim_terms.h (IQA and Netflix float code) to Xiph.Org, and, through a pattern that needs the file name to start with ssimulacra2, sycl_ssimulacra2_math.h to all three instead of libjxl.
Files the tool misread. The scripts/ci/exact_twins.d/*.hip fragments are data whose suffix names a backend; two files are praetor's byte-locked managed files; scripts/sync-pelorus-interop.sh embeds the header of the mirrored Pelorus files as a string. The tool wanted to give the first two groups a header and to rewrite the third's template.
Decision¶
- A fork-created header that replays upstream arithmetic carries
EUPL-1.2 ANDthe licences of the code it reproduces, with that code's copyright notices added above the fork's, which stays. The expression lists exactly the licences of the code actually reproduced, read from the header's file read against its source, not the family default. This is the three headers of the first kind. - A fork-created header that holds none of the reference's code stays
EUPL-1.2, with a[not_ports]entry that says why: an argument block, or macros and an include of a shared header that carries the notices itself. This is the four headers of the second kind; they are not changed. - A
[ports]entry names a helper header's origins when its family is coarser than the header. Families remain the default for kernel files. - Fork-added headers that carry only an upstream notice stay as they are (
core/src/feature/integer_ssim.h,core/src/feature/iqa/ssim_simd.h): no fork notice is added. - The tool does not manage exact-twin fragments, praetor's byte-locked files, or a licence grant below a file's own header (the first 60 lines).
relicense_fork_files.py --checkis a required CI job. It runs against the Netflix/vmaf commit the repository already records as the upstream head it is at parity with (the heading of that name indocs/development/known-upstream-bugs.md), with the full history it needs for the author veto. The pin moves where it always moved: with an upstream sync or port.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
All seven stay EUPL-1.2 ([not_ports]) | Nothing changes | Three of them reproduce reference arithmetic line for line and say so; the notices of that code would not travel with it | The licences of the reproduced code require the notice |
The three become BSD-2-Clause-Patent AND ..., dropping EUPL, like their sibling kernels | One convention for every file in a kernel directory | Removes terms the files were published under and the fork's reciprocity on its own part of them | Rejected by the maintainer in favour of the mixed expression |
EUPL-1.2 AND <upstream licences> for the three (chosen) | Credits the reproduced code, keeps the terms the fork gave its own part | A mixed expression per file | The maintainer's decision |
| The mixed expression for all seven, by family | One rule per directory, no per-file review | Adds Netflix's and Joshua Holmer's copyright notices to four files that hold none of their code | A tag and its notices describe the file; the maintainer confirmed EUPL-1.2 for the four |
Widen the ssimulacra2 family pattern instead of [ports] entries | One line | Changes how every future file with ssimulacra2 in its name resolves; does nothing for the three SSIM headers | Per-file entries change exactly the files reviewed |
| Run the check as a pre-commit hook | Feedback before the push | It reads every candidate's history (265 CPU seconds, about 30 s on 16 jobs) and needs the upstream tree | Too slow and too history-dependent for a commit hook; the tag-against-notice scan is the pre-commit side |
Run the check against upstream's moving master | No pin to maintain | A file added upstream would turn the job red on an unrelated pull request | The pin moves with the reviewed upstream sync |
Consequences¶
- Positive:
--checkexits 0 and stays there; a new fork file with the wrong tag, a new helper header without its upstream notice, and a stale provenance entry fail a required job; the three headers credit the code they reproduce, and no header credits code it does not hold. - Negative: one more required job with a full-history checkout; an upstream sync has one more value to move.
- Neutral / follow-ups: a helper header added to a kernel directory needs a
[ports]entry when its family names origins it does not reproduce and a[not_ports]entry when it reproduces none; the job says so when it fails.
References¶
- ADR-1250: the provenance rule and the tool.
- ADR-1351: praetor's byte-locked files.
- ADR-1428: the exact-twin fragment files.
T-RELICENSE-CHECK-PENDING-2026-10-02, PR #1876 (the 41 pending entries).- Source: popup answer of the maintainer, relayed by the session coordinator on 2026-10-02. Q: how the seven EUPL-tagged helper headers that replay upstream arithmetic are licensed. A: "Mixed: EUPL-1.2 AND the upstream licence". Given for the group of seven, before the per-file check.
- Source: popup answer of the maintainer, relayed by the session coordinator on 2026-10-02. Q: asked with the per-file findings, what the four headers that contain no upstream code carry. A: "EUPL-1.2 only (Recommended)". The correction for the four; the three that reproduce code keep the mixed expression.
- Source: popup answer of the maintainer, relayed by the session coordinator on 2026-10-02. Q: whether the fork-added
integer_ssim.handiqa/ssim_simd.halso credit the fork. A: "Leave them as they are".