Skip to content

chore: prepare 0.0.15 release - #31

Merged
MattyB95 merged 14 commits into
mainfrom
develop
Aug 10, 2026
Merged

chore: prepare 0.0.15 release#31
MattyB95 merged 14 commits into
mainfrom
develop

Conversation

@MattyB95

Copy link
Copy Markdown
Owner

Summary

  • Security: closes CVE-2025-3000 (torch, torch.jit.script memory corruption) by raising the floor to >=2.13.0, and GHSA-h35f-9h28-mq5c (setuptools MANIFEST.in NFC/NFD bypass) by locking to 84.0.0
  • Fixed: RawNet2 now resamples/pads audio to the model's expected 16kHz/64600-sample window instead of feeding it raw, mismatched-rate audio
  • Fixed: Spectra0 and SpectraAASIST now use lab260's documented calibrated decision threshold instead of naive softmax argmax (SpectraAASIST3 intentionally left unchanged — no trustworthy threshold exists upstream)
  • Fixed: AST pipeline now passes sampling_rate, matching HuBERT/Wav2Vec2/WavLM; EnumAction no longer falls through after parser.error()
  • Changed: dependencies refreshed to latest compatible versions; VIT pipeline loader and device-selection boilerplate deduplicated; stale CI/pre-commit pins bumped

See CHANGELOG.md [0.0.15] for full details.

Test plan

  • All 162 tests pass (uv run pytest)
  • Ruff, Black, and ty checks pass (uv run ruff check ., uv run black --check ., uv run ty check src/)
  • uv build produces a clean sdist/wheel
  • CI green on develop (lint, full test matrix, TestPyPI pre-release publish)

Copilot AI lite review requested due to automatic review settings August 10, 2026 14:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prepares the 0.0.15 release by updating dependency floors/pins for security advisories, fixing several model inference correctness issues (RawNet2 input normalization, Spectra calibrated thresholds, AST sampling rate), and deduplicating common model-loading/device-selection utilities across the codebase.

Changes:

  • Raise/refresh dependency versions (notably torch>=2.13.0) and bump release metadata (pyproject.toml, README.md, CITATION.cff, CHANGELOG.md).
  • Fix model inference behavior: RawNet2 now resamples/pads/trims to the expected 16kHz/64600-sample window; AST passes sampling_rate; Spectra0/SpectraAASIST use calibrated thresholds.
  • Deduplicate shared utilities (VIT load_pipeline() caching, shared get_device()), and update CI/pre-commit pins.

Reviewed changes

Copilot reviewed 20 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/test_models.py Updates mocks/patch points for shared VIT loader; adds coverage for calibrated Spectra thresholds and RawNet2 resample/length normalization.
src/Jabberjay/Utilities/enum_handler.py Prevents fallthrough after parser.error() by returning explicitly.
src/Jabberjay/Utilities/device.py Introduces shared get_device() helper to centralize device selection + logging.
src/Jabberjay/Models/Transformer/VIT/utility.py Adds shared cached load_pipeline() for VIT and removes redundant canvas draw.
src/Jabberjay/Models/Transformer/VIT/MFCC/run.py Switches to shared load_pipeline() utility.
src/Jabberjay/Models/Transformer/VIT/MelSpectrogram/run.py Switches to shared load_pipeline() utility.
src/Jabberjay/Models/Transformer/VIT/ConstantQ/run.py Switches to shared load_pipeline() utility.
src/Jabberjay/Models/Transformer/AST/run.py Passes sampling_rate=16000 to shared transformers pipeline runner.
src/Jabberjay/Models/SpectraAASIST3/run.py Uses shared get_device() for device selection.
src/Jabberjay/Models/SpectraAASIST/run.py Uses shared get_device() and applies documented calibrated threshold logic.
src/Jabberjay/Models/Spectra0/run.py Uses shared get_device() and applies calibrated threshold logic.
src/Jabberjay/Models/RawNet2/run.py Adds resampling + trim/pad to fixed window and uses shared get_device().
src/Jabberjay/jabberjay.py Updates RawNet2 handler to pass sr through to RawNet2 predict().
README.md Bumps cited version to 0.0.15.
pyproject.toml Bumps package version and refreshes dependency constraints and dev tools.
CITATION.cff Updates release version/date metadata.
CHANGELOG.md Adds 0.0.15 release notes and comparison link.
.pre-commit-config.yaml Bumps pre-commit hook revisions.
.gitignore Adds venv/ and .venv/ ignores.
.github/workflows/docs.yml Bumps setup-uv action pin.
.github/workflows/ci.yml Bumps setup-uv action pin across jobs.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Jabberjay/Models/RawNet2/run.py Outdated
Comment thread src/Jabberjay/Models/RawNet2/run.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 22 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings August 10, 2026 14:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 22 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/Jabberjay/Models/RawNet2/run.py:61

  • The empty-audio guard happens after the optional resample. If y is empty and sr != _TARGET_SR, torchaudio.functional.resample() is called first and will likely raise a low-level RuntimeError, bypassing the intended ValueError with a clear message. Check for zero-length input before resampling so empty input is handled consistently regardless of sr.
    audio = torch.from_numpy(y).float()
    if sr != _TARGET_SR:
        audio = torchaudio.functional.resample(audio, int(sr), _TARGET_SR)
    audio_len = audio.shape[0]
    if audio_len == 0:

dependabot Bot and others added 14 commits August 10, 2026 16:00
Bumps the uv group with 1 update in the / directory: [torch](https://github.com/pytorch/pytorch).

Updates `torch` from 2.12.1 to 2.13.0
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](pytorch/pytorch@v2.12.1...v2.13.0)

---
updated-dependencies:
- dependency-name: torch
  dependency-version: 2.13.0
  dependency-type: direct:production
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the uv group with 1 update in the / directory: [torch](https://github.com/pytorch/pytorch).

Updates `torch` from 2.12.1 to 2.13.0
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](pytorch/pytorch@v2.12.1...v2.13.0)

---
updated-dependencies:
- dependency-name: torch
  dependency-version: 2.13.0
  dependency-type: direct:production
  dependency-group: uv
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matthew Boakes <Matthew.Boakes@Gmail.com>
Closes GHSA-h35f-9h28-mq5c (setuptools MANIFEST.in bypass) and raises the
torch floor to >=2.13.0 so a fresh install can never resolve the
CVE-2025-3000-vulnerable 2.12.x line. Also refreshes transitive deps
(huggingface-hub, transformers, ruff, ty, mkdocs-material, etc.) and bumps
stale pre-commit hook pins and the setup-uv GitHub Action from major v7 to
v9.
RawNet2's SincConv filters are hardcoded to 16kHz and the model was
trained on fixed 64600-sample windows, but predict() fed it raw audio
at whatever rate Jabberjay.load() produced (22050Hz by default) with no
length normalization. This silently miscalibrated the sinc bandpass and
produced wrong scores with no error, unlike every other torch backend
(Spectra family) which already resamples and pads/trims correctly.
_load_pipeline() (image-classification, cached_loader) was copy-pasted
identically across ConstantQ/, MFCC/, and MelSpectrogram/ run.py. Moved
to Transformer/VIT/utility.py as load_pipeline(), matching the pattern
already used by Models/Spectra/shared.py, and widened the shared cache
from 3x maxsize=4 to a single maxsize=8 covering the full
dataset x visualisation matrix.
"cuda" if torch.cuda.is_available() else "cpu" plus a matching debug
log line was duplicated independently across RawNet2, Spectra0,
SpectraAASIST, and SpectraAASIST3. Consolidated into
Utilities/device.get_device().
parser.error() always raises SystemExit in normal argparse usage, but
EnumAction.__call__() fell through to setattr() with an unassigned
value on invalid input, relying entirely on that contract. Add an
explicit return so the failure mode is a clean control-flow guarantee
rather than an implicit assumption about argparse internals.
HuBERT, Wav2Vec2, and WavLM all pass sampling_rate=16000 to
run_pipeline(); AST was the one outlier omitting it despite the
underlying AST feature extractor expecting the same 16kHz input.
plt.savefig() redraws the canvas internally, so the explicit
fig.canvas.draw() beforehand was wasted work on every VIT inference
call.
predict() derived the Bonafide/Spoof verdict via softmax+argmax, which
is equivalent to thresholding the bonafide logit at 0. But lab260's own
classify() method (and model cards) document a different, EER-tuned
decision boundary: -1.0625009 for Spectra0, -1.140625 for SpectraAASIST.
Argmax silently used the wrong boundary for borderline samples.

SpectraAASIST3 is intentionally left unchanged: its classify() default
(-1.0625009) is undocumented on its model card and identical to
Spectra0's value in both Jabberjay's and lab260's own upstream model.py
— almost certainly a stale copy-paste rather than a real calibration,
so there's no trustworthy threshold to adopt for that model yet.
Bumps version and adds the CHANGELOG entry covering this session's
work: two CVE closures (torch/CVE-2025-3000, setuptools/GHSA-h35f),
the RawNet2 resampling fix, the Spectra0/AASIST calibrated-threshold
fix, and the AST/EnumAction/VIT/device cleanups.

Also gitignores venv/ and .venv/ — an untracked local venv/ directory
was getting swept into `uv build`'s sdist (via hatchling's default
git-based file selection, which only skips gitignored paths) and
crashing the pack step on an absolute symlink. Harmless in CI's clean
checkout, but broke local `uv build`.
astral-sh/setup-uv@v9 doesn't resolve — only the exact v9.0.0 release
tag exists upstream, the floating major alias hasn't been published
yet. Broke CI immediately after pushing the v7->v9 bump.
Co-authored-by: MattyB95 <5563995+MattyB95@users.noreply.github.com>
Copilot's assert->raise and zero-length-audio fixes weren't
black-formatted, which was failing CI's format-check job. Also adds a
test for the empty-audio ValueError path and marks the _CONFIG-is-None
branch pragma: no cover — that invariant is guaranteed by _load_model()
and unreachable in practice, same as the EnumAction fallthrough guard.
@MattyB95
MattyB95 merged commit 0cdd423 into main Aug 10, 2026
19 checks passed
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.

3 participants