ADR-0546: Audit bundle — Vulkan motion dispatch wiring, saliency hard-fail, model-card placeholder¶
- Status: Accepted
- Date: 2026-05-18
- Deciders: lusoris, Claude (Anthropic)
- Tags:
vulkan,vmaf-tune,ai,build,docs
Context¶
Three independent audit findings were grouped into a single PR because they touch entirely different files and have no coupling, yet each is small enough that a dedicated PR per finding would add more review overhead than value.
Vulkan-01 — integer_motion_vulkan extractor missing from dispatch list. core/src/feature/vulkan/integer_motion_vulkan.c exports the symbol vmaf_fex_integer_motion_vulkan_impl and its source comment states that feature_extractor.c "registers both" this extractor and the legacy motion_vulkan one. The extern declaration (line 99) existed in feature_extractor.c, but no corresponding entry was ever added to feature_extractor_list[]. Consequence: vmaf_get_feature_extractor_by_name("integer_motion_vulkan") returned NULL on every Vulkan-enabled build, making the extractor unreachable from user code.
saliency-tune-01 — saliency ROI silently falls back for unsupported codecs. saliency_aware_encode() in vmaftune/saliency.py dispatched only the five codecs wired in _SALIENCY_DISPATCH (libx264, libaom-av1, libx265, libsvtav1, libvvenc). For every other encoder (NVENC, QSV, AMF, VideoToolbox, libvpx-vp9, and nine others) it emitted only a WARNING log and produced a plain encode. A caller requesting --saliency combined with h264_nvenc would receive an unbiased encode with no indication that the ROI pass was skipped — a half-measure inconsistent with the ADR-0498 hard-fail posture adopted for other requested-but-unavailable features in this fork.
ai-01 — synthetic-stub model card emits literal PLACEHOLDER. predictor_train.py:_write_model_card() emitted the string "PLACEHOLDER — the synthetic stub ships unsigned" for the Sigstore signing note when a synthetic corpus was used. The word PLACEHOLDER is a development artifact; it signals to readers that the field was never filled in rather than communicating the actual design intent (synthetic stubs are intentionally unsigned; production models are signed at the release-please tag step).
Decision¶
Vulkan-01: Add &vmaf_fex_integer_motion_vulkan_impl to the Vulkan block of feature_extractor_list[] in feature_extractor.c, guarded by the existing #if HAVE_VULKAN.
saliency-tune-01: Change the default behaviour when --saliency is requested for a codec not in _SALIENCY_DISPATCH:
- Default: raise
SaliencyUnsupportedEncoderError(inherits fromSystemExit(2)), which exits the CLI with code 2 and a structured error message listing the supported codecs and the requested encoder. - Opt-in fallback: if
SaliencyConfig.allow_unsupported_encoder_fallback=True(set via--saliency-fallback-plain) or the environment variableVMAFTUNE_SALIENCY_FALLBACK_OK=1is set, demote to a plain encode and emit an ERROR log (instead of the former WARNING).
ai-01: Replace the literal PLACEHOLDER with the factual statement "not applicable (synthetic-stub model card; production models are signed via Sigstore — see docs/development/release.md)". Add --emit-stub-card-only to predictor_train.py to expose a smoke-test hook that emits a stub card without a full training run.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
Vulkan-01 alt: remove the dead extern declaration and the comment that references it | Reduces confusion about the number of registered extractors | Silently drops an extractor that the source already implements and any downstream user may name explicitly | Symbol already exists and is valid — registering it is the correct fix |
saliency-tune-01 alt A: keep the WARNING + fallback as the default, add a hard-fail flag (--saliency-strict) | Preserves backward compatibility for callers that pass unsupported encoders without noticing | Inverts the ADR-0498 posture; the default remains a half-measure | The ADR-0498 rule is "hard-fail by default, opt-in to lenient"; this option violates it |
| saliency-tune-01 alt B: hard-fail unconditionally with no escape hatch | Cleaner API surface | Breaks CI pipelines or wrapper scripts that legitimately want to run all-codecs sweeps where some codecs lack ROI support | The env-var escape hatch costs ~5 LOC and preserves the principle without trapping scripts |
| ai-01 alt: delete the signing note for synthetic stubs entirely | Shorter card | Readers have no indication of the fork's signing policy for production models | The note is useful orientation; replacing it with a factual statement is preferable to removing it |
Consequences¶
- Positive:
vmaf_get_feature_extractor_by_name("integer_motion_vulkan")now returns the correct extractor on Vulkan builds; the dispatch table has no silent holes. Callers requesting--saliencyon unsupported codecs receive an actionable error (exit 2, named codec, named supported list) instead of a silent degraded encode. Synthetic model cards no longer contain stale development artifact text. - Negative: Any caller that previously relied on the silent fallback behaviour for unsupported saliency codecs will now receive exit code 2. They must add
--saliency-fallback-plainto restore the old behaviour. - Neutral / follow-ups: The pre-existing
test_saliency_aware_encode_unknown_encoder_falls_back_to_plaintest was updated to opt in toallow_unsupported_encoder_fallback=Trueto preserve its original intent (verify the fallback path still works when explicitly requested). Three new tests cover the hard-fail path and the env-var escape hatch.
References¶
req: "When--saliencyis requested on a codec NOT in_SALIENCY_DISPATCH, exit code 2 with a structured error message listing the supported codecs and the requested codec, instead of silently logging a WARNING"req: "Replace with: 'not applicable (synthetic-stub model card; production models are signed via Sigstore…)'. The literal PLACEHOLDER is misleading"req: "Add the entry tofeature_extractor_list[]guarded by the same#ifdef HAVE_VULKAN/enable_vulkanmechanism as the other Vulkan entries"- ADR-0498: enforcement posture for requested-but-unavailable features.
- ADR-0293: saliency-aware encode design.
- ADR-0370: x265 / SVT-AV1 / VVenC ROI dispatch.
- ADR-0042: tiny-AI docs 5-point bar.
- ADR-0108: deep-dive deliverables rule.
- ADR-0165:
docs/state.mdbug-tracking rule.