perf(analysis-engine): move numeric kernels to Rust (PyO3) with Python parity fallback#613
perf(analysis-engine): move numeric kernels to Rust (PyO3) with Python parity fallback#613seonghobae wants to merge 10 commits into
Conversation
…y fallback Port the two hottest pure-numeric kernels of the analysis engine to a PyO3/maturin Rust extension (`bandscope_numeric`), keeping the NumPy reference implementations intact for parity testing and runtime fallback: - Checkerboard SSM novelty (structural segmentation) -> `bandscope_numeric.checkerboard_novelty` - Log-space Viterbi chord decoding -> `bandscope_numeric.viterbi_decode` The math is ported line-for-line, not re-derived. Rust<->Python numerical parity is asserted over representative fixtures (novelty <= 1e-6 max abs diff; Viterbi decoded states exact) as the acceptance gate. Callers use the Rust path by default and fall back to the reference when the extension is absent. CI builds and installs the extension before the Python suite. Dependencies are permissive only (PyO3/numpy/ndarray, MIT/Apache-2.0). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
Upgrades the Rust numeric extension's pyo3 (0.23.5 -> 0.29.0) and the matching numpy crate (0.23 -> 0.29) to remediate three Trivy code-scanning findings on the transitive pyo3 dependency: - GHSA-36hh-v3qg-5jq4 (HIGH): OOB read in nth/nth_back for PyList/PyTuple iterators (fixed 0.29.0) - GHSA-chgr-c6px-7xpp (MEDIUM): missing Sync bound on PyCFunction::new_closure closures (fixed 0.29.0) - GHSA-pph8-gcv7-4qj5 (LOW): buffer overflow in PyString::from_object (fixed 0.24.1) ndarray stays at 0.16 (numpy 0.29 requires >=0.15,<=0.17). The kernel source already uses the Bound API, so no code changes were needed; cargo check/clippy are clean and all 23 numeric-parity tests pass, confirming the checkerboard-novelty and Viterbi kernels are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current heade2e0516e416c0f79253662b1697d7994340bbf6c. -
Head SHA:
e2e0516e416c0f79253662b1697d7994340bbf6c -
Workflow run: 28982113337
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
e2e0516e416c0f79253662b1697d7994340bbf6c - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Python project dependencies (services/analysis-engine)
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12
Creating virtual environment at: services/analysis-engine/.venv
Resolved 49 packages in 0.59ms
Building bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloading soundfile (1.3MiB)
Downloading pygments (1.2MiB)
Downloading llvmlite (53.7MiB)
Downloading scipy (33.6MiB)
Downloading scikit-learn (8.5MiB)
Downloading numpy (15.8MiB)
Downloading mypy (13.0MiB)
Downloading yt-dlp (3.0MiB)
Downloading numba (3.6MiB)
Downloading ruff (10.7MiB)
Downloaded soundfile
Downloaded pygments
Built bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloaded numba
Downloaded ruff
Downloaded scikit-learn
Downloaded yt-dlp
Downloaded numpy
Downloaded llvmlite
Downloaded scipy
Downloaded mypy
Prepared 44 packages in 2.06s
Installed 44 packages in 66ms
+ audioread==3.1.0
+ bandit==1.9.4
+ bandscope-analysis==0.1.0 (from file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine)
+ certifi==2026.2.25
+ cffi==2.0.0
+ charset-normalizer==3.4.6
+ coverage==7.13.4
+ decorator==5.2.1
+ idna==3.18
+ iniconfig==2.3.0
+ joblib==1.5.3
+ lazy-loader==0.5
+ librosa==0.11.0
+ librt==0.8.1
+ llvmlite==0.45.1
+ markdown-it-py==4.0.0
+ mdurl==0.1.2
+ msgpack==1.2.1
+ mypy==1.19.1
+ mypy-extensions==1.1.0
+ numba==0.62.1
+ numpy==2.3.5
+ packaging==26.0
+ pathspec==1.0.4
+ platformdirs==4.9.4
+ pluggy==1.6.0
+ pooch==1.9.0
+ pycparser==3.0
+ pygments==2.20.0
+ pytest==9.0.3
+ pytest-cov==7.0.0
+ pyyaml==6.0.3
+ requests==2.33.0
+ rich==15.0.0
+ ruff==0.15.5
+ scikit-learn==1.8.0
+ scipy==1.17.1
+ soundfile==0.13.1
+ soxr==1.0.0
+ stevedore==5.7.0
+ threadpoolctl==3.6.0
+ typing-extensions==4.15.0
+ urllib3==2.7.0
+ yt-dlp==2026.6.9
- Result: PASS
Python coverage with missing-line report (services/analysis-engine)
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0
rootdir: /home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
configfile: pyproject.toml
plugins: cov-7.0.0
collected 458 items
tests/test_activity.py ........ [ 1%]
tests/test_anchors.py .... [ 2%]
tests/test_api.py ......................... [ 8%]
tests/test_chord_recognizer.py .................... [ 12%]
tests/test_chords.py ......................... [ 17%]
tests/test_cli.py ................. [ 21%]
tests/test_extractor.py ...... [ 22%]
tests/test_health.py . [ 23%]
tests/test_native_dispatch.py .. [ 23%]
tests/test_numeric_parity.py sssssssssssssssssssssss [ 28%]
tests/test_pipeline_integration.py ......... [ 30%]
tests/test_pitch_tracker.py ............... [ 33%]
tests/test_priority.py ........... [ 36%]
tests/test_ranges.py ................... [ 40%]
tests/test_release_asset_selection.py ........ [ 42%]
tests/test_release_metadata.py ....... [ 43%]
tests/test_release_packaging.py ......... [ 45%]
tests/test_roles.py ....... [ 47%]
tests/test_roles_ml.py ... [ 47%]
tests/test_segmenter.py ..................... [ 52%]
tests/test_separation.py .................................. [ 59%]
tests/test_supply_chain_policy.py ...................................... [ 68%]
........................................................................ [ 83%]
......................................... [ 92%]
tests/test_temporal.py ......... [ 94%]
tests/test_transcription.py ... [ 95%]
tests/test_tuning.py ..... [ 96%]
tests/test_youtube.py ................ [100%]
=============================== warnings summary ===============================
tests/test_pipeline_integration.py::test_pipeline_without_detected_sections_falls_back
tests/test_roles.py::test_role_extractor_falls_back_when_activity_detection_fails
/home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine/.venv/lib/python3.12/site-packages/librosa/core/pitch.py:103: UserWarning: Trying to estimate tuning from empty frequency set.
return pitch_tuning(
tests/test_roles.py::test_role_extractor_falls_back_when_activity_detection_fails
/home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine/.venv/lib/python3.12/site-packages/librosa/core/spectrum.py:266: UserWarning: n_fft=2048 is too large for input signal of length=100
warnings.warn(
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============ 435 passed, 23 skipped, 3 warnings in 84.74s (0:01:24) ============
Name Stmts Miss Cover Missing
------------------------------------------------------------------------------------
src/bandscope_analysis/__init__.py 3 0 100%
src/bandscope_analysis/_native.py 11 0 100%
src/bandscope_analysis/api.py 571 0 100%
src/bandscope_analysis/chords/__init__.py 5 0 100%
src/bandscope_analysis/chords/analyzer.py 116 0 100%
src/bandscope_analysis/chords/capo.py 10 0 100%
src/bandscope_analysis/chords/chord_recognizer.py 195 0 100%
src/bandscope_analysis/chords/model.py 15 0 100%
src/bandscope_analysis/cli.py 68 0 100%
src/bandscope_analysis/health.py 7 0 100%
src/bandscope_analysis/ranges/__init__.py 4 0 100%
src/bandscope_analysis/ranges/analyzer.py 77 0 100%
src/bandscope_analysis/ranges/model.py 19 0 100%
src/bandscope_analysis/ranges/pitch_tracker.py 54 0 100%
src/bandscope_analysis/roles/__init__.py 4 0 100%
src/bandscope_analysis/roles/activity.py 59 0 100%
src/bandscope_analysis/roles/extractor.py 118 0 100%
src/bandscope_analysis/roles/model.py 58 0 100%
src/bandscope_analysis/roles/priority.py 13 0 100%
src/bandscope_analysis/roles/tuning.py 11 0 100%
src/bandscope_analysis/sections/__init__.py 6 0 100%
src/bandscope_analysis/sections/anchors.py 5 0 100%
src/bandscope_analysis/sections/extractor.py 38 0 100%
src/bandscope_analysis/sections/model.py 35 0 100%
src/bandscope_analysis/sections/segmenter.py 143 0 100%
src/bandscope_analysis/sections/utils.py 8 0 100%
src/bandscope_analysis/separation/__init__.py 4 0 100%
src/bandscope_analysis/separation/audio_separator.py 145 0 100%
src/bandscope_analysis/separation/model.py 31 0 100%
src/bandscope_analysis/separation/separator.py 34 0 100%
src/bandscope_analysis/temporal/__init__.py 3 0 100%
src/bandscope_analysis/temporal/analyzer.py 49 0 100%
src/bandscope_analysis/temporal/model.py 9 0 100%
src/bandscope_analysis/transcription/__init__.py 2 0 100%
src/bandscope_analysis/transcription/api.py 11 0 100%
src/bandscope_analysis/youtube.py 81 0 100%
------------------------------------------------------------------------------------
TOTAL 2022 0 100%
- Result: PASS
Python docstring coverage
- Result: DEFERRED
- Reason: package.json defines check:python-docstrings; repository-owned docstring coverage runs after package dependency setup.
Rust coverage tooling (cargo-llvm-cov)
Updating crates.io index
Downloading crates ...
Downloaded cargo-llvm-cov v0.8.7
Installing cargo-llvm-cov v0.8.7
Updating crates.io index
Updating crates.io index
Downloading crates ...
Downloaded autocfg v1.5.0
Downloaded fs-err v3.3.0
Downloaded cfg-if v1.0.4
Downloaded os_pipe v1.2.3
Downloaded bitflags v2.11.1
Downloaded lcov2cobertura v1.0.9
Downloaded anyhow v1.0.102
Downloaded xattr v1.6.1
Downloaded shared_thread v0.2.0
Downloaded glob v0.3.3
Downloaded shared_child v1.1.1
Downloaded filetime v0.2.29
Downloaded shell-escape v0.1.5
Downloaded serde_spanned v1.1.1
Downloaded zmij v1.0.21
Downloaded duct v1.1.1
Downloaded serde_core v1.0.228
Downloaded unicode-ident v1.0.24
Downloaded toml_parser v1.1.2+spec-1.1.0
Downloaded tar v0.4.45
Downloaded memchr v2.8.0
Downloaded ruzstd v0.8.3
Downloaded aho-corasick v1.1.4
Downloaded serde_json v1.0.149
Downloaded regex v1.12.3
Downloaded winnow v1.0.2
Downloaded bstr v1.12.1
Downloaded serde v1.0.228
Downloaded quick-xml v0.39.4
Downloaded proc-macro2 v1.0.106
Downloaded cargo-config2 v0.1.44
Downloaded syn v2.0.117
Downloaded toml v1.1.2+spec-1.1.0
Downloaded serde_derive v1.0.228
Downloaded regex-syntax v0.8.10
Downloaded opener v0.8.4
Downloaded camino v1.2.2
Downloaded walkdir v2.5.0
Downloaded toml_datetime v1.1.1+spec-1.1.0
Downloaded rustix v1.1.4
Downloaded termcolor v1.4.1
Downloaded rustc-demangle v0.1.27
Downloaded quote v1.0.45
Downloaded lexopt v0.3.2
Downloaded same-file v1.0.6
Downloaded regex-automata v0.4.14
## Changed-File Evidence Map
```mermaid
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: ci.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: ci.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (10 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (10 files)"]
R2 --> V2["required checks"]
Evidence --> S3["Test (2 files)"]
S3 --> I3["regression suite"]
I3 --> R3["Review risk: Test (2 files)"]
R3 --> V3["targeted test run"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage Evidence
Implementation completeness scan
Python project dependencies (services/analysis-engine)
Python coverage with missing-line report (services/analysis-engine) |
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current headc9a8b0fc027e1e3b75ef35e9a71bd75a3ae595a7. -
Head SHA:
c9a8b0fc027e1e3b75ef35e9a71bd75a3ae595a7 -
Workflow run: 29168410503
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
c9a8b0fc027e1e3b75ef35e9a71bd75a3ae595a7 - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Python implementation completeness scan
$ python3 /home/runner/work/bandscope/bandscope/scripts/ci/implementation_completeness_scan.py --repo-root . --changed-files /tmp/tmp.Ld9Ke99eFa
# Implementation Completeness Scan
- Checked runtime Python files: 3
- Declaration handling: typing.Protocol, abc.ABC, @abstractmethod, and @overload placeholders are treated as contracts, not executable missing implementations.
- Result: PASS
- Reason: no executable placeholder implementations were found in changed runtime Python files.
- Result: PASS
Python project dependencies (services/analysis-engine)
$ uv sync --project services/analysis-engine --group dev
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12
Creating virtual environment at: services/analysis-engine/.venv
Resolved 91 packages in 0.71ms
Building bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloading nvidia-nvshmem-cu13 (57.6MiB)
Downloading nvidia-curand (56.8MiB)
Downloading nvidia-cuda-cupti (10.2MiB)
Downloading pygments (1.2MiB)
Downloading nvidia-cufile (1.2MiB)
Downloading nvidia-cublas (403.5MiB)
Downloading nvidia-nccl-cu13 (196.4MiB)
Downloading mypy (13.0MiB)
Downloading nvidia-cuda-runtime (2.1MiB)
Downloading networkx (2.0MiB)
Downloading soundfile (1.3MiB)
Downloading setuptools (1.0MiB)
Downloading nvidia-cudnn-cu13 (349.2MiB)
Downloading nvidia-cusparselt-cu13 (162.3MiB)
Downloading sympy (6.0MiB)
Downloading llvmlite (53.7MiB)
Downloading nvidia-cufft (204.2MiB)
Downloading numba (3.6MiB)
Downloading triton (188.6MiB)
Downloading nvidia-cuda-nvrtc (86.0MiB)
Downloading ruff (10.7MiB)
Downloading nvidia-nvjitlink (38.8MiB)
Downloading torchaudio (1.7MiB)
Downloading scipy (33.6MiB)
Downloading yt-dlp (3.0MiB)
Downloading numpy (15.8MiB)
Downloading torch (507.6MiB)
Downloading nvidia-cusparse (139.2MiB)
Downloading nvidia-cusolver (191.6MiB)
Downloading scikit-learn (8.5MiB)
Downloading cuda-bindings (6.3MiB)
Downloaded soundfile
Downloaded nvidia-cufile
Building antlr4-python3-runtime==4.9.3
Building dora-search==0.1.12
Building demucs==4.0.1
Downloaded torchaudio
Downloaded nvidia-cuda-runtime
Downloaded pygments
Downloaded setuptools
Built bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloaded networkx
Downloaded numba
Downloaded yt-dlp
Built antlr4-python3-runtime==4.9.3
Downloaded cuda-bindings
Built dora-search==0.1.12
Built demucs==4.0.1
Downloaded nvidia-cuda-cupti
Downloaded ruff
Downloaded scikit-learn
Downloaded sympy
Downloaded numpy
Downloaded nvidia-nvjitlink
Downloaded scipy
Downloaded nvidia-curand
Downloaded llvmlite
Downloaded nvidia-nvshmem-cu13
Downloaded mypy
Downloaded nvidia-cuda-nvrtc
Downloaded nvidia-cusparse
Downloaded nvidia-cusparselt-cu13
Downloaded nvidia-cusolver
Downloaded nvidia-nccl-cu13
Downloaded nvidia-cufft
Downloaded triton
Downloaded nvidia-cudnn-cu13
Downloaded nvidia-cublas
Downloaded torch
Prepared 86 packages in 18.43s
Installed 86 packages in 426ms
+ antlr4-python3-runtime==4.9.3
+ audioread==3.1.0
+ bandit==1.9.4
+ bandscope-analysis==0.1.0 (from file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine)
+ certifi==2026.2.25
+ cffi==2.0.0
+ charset-normalizer==3.4.6
+ cloudpickle==3.1.2
+ coverage==7.13.4
+ cuda-bindings==13.3.1
+ cuda-pathfinder==1.5.6
+ cuda-toolkit==13.0.2
+ decorator==5.2.1
+ demucs==4.0.1
+ dora-search==0.1.12
+ einops==0.8.2
+ filelock==3.29.5
+ fsspec==2026.6.0
+ idna==3.18
+ iniconfig==2.3.0
+ jinja2==3.1.6
+ joblib==1.5.3
+ julius==0.2.8
+ lameenc==1.8.4
+ lazy-loader==0.5
+ librosa==0.11.0
+ librt==0.8.1
+ llvmlite==0.45.1
+ markdown-it-py==4.0.0
+ markupsafe==3.0.3
+ mdurl==0.1.2
+ mpmath==1.3.0
+ msgpack==1.2.1
+ mypy==1.19.1
+ mypy-extensions==1.1.0
+ networkx==3.6.1
+ numba==0.62.1
+ numpy==2.3.5
+ nvidia-cublas==13.1.1.3
+ nvidia-cuda-cupti==13.0.85
+ nvidia-cuda-nvrtc==13.0.88
+ nvidia-cuda-runtime==13.0.96
+ nvidia-cudnn-cu13==9.20.0.48
+ nvidia-cufft==12.0.0.61
+ nvidia-cufile==1.15.1.6
+ nvidia-curand==10.4.0.35
+ nvidia-cusolver==12.0.4.66
+ nvidia-cusparse==12.6.3.3
+ nvidia-cusparselt-cu13==0.8.1
+ nvidia-nccl-cu13==2.29.7
+ nvidia-nvjitlink==13.0.88
+ nvidia-nvshmem-cu13==3.4.5
+ nvidia-nvtx==13.0.85
+ omegaconf==2.3.1
+ openunmix==1.3.0
+ packaging==26.0
+ pathspec==1.0.4
+ platformdirs==4.9.4
+ pluggy==1.6.0
+ pooch==1.9.0
+ pycparser==3.0
+ pygments==2.20.0
+ pytest==9.0.3
+ pytest-cov==7.0.0
+ pyyaml==6.0.3
+ requests==2.33.0
+ retrying==1.4.2
+ rich==15.0.0
+ ruff==0.15.5
+ scikit-learn==1.8.0
+ scipy==1.17.1
+ setuptools==81.0.0
+ soundfile==0.13.1
+ soxr==1.0.0
+ stevedore==5.7.0
+ submitit==1.5.4
+ sympy==1.14.0
+ threadpoolctl==3.6.0
+ torch==2.12.1
+ torchaudio==2.11.0
+ tqdm==4.68.3
+ treetable==0.2.6
+ triton==3.7.1
+ typing-extensions==4.15.0
+ urllib3==2.7.0
+ yt-dlp==2026.6.9
- Result: PASS
Python coverage with missing-line report (services/analysis-engine)
$ bash -c cd\ \"\$1\"\ \&\&\ PYTHONPATH=.\ uv\ run\ --with\ coverage\ --with\ pytest\ coverage\ run\ -m\ pytest\ tests\ \&\&\ uv\ run\ --with\ coverage\ coverage\ report\ --show-missing bash services/analysis-engine
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0
rootdir: /home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
configfile: pyproject.toml
plugins: cov-7.0.0
collected 675 items
tests/test_activity.py ........ [ 1%]
tests/test_anchors.py .... [ 1%]
tests/test_api.py ........................... [ 5%]
tests/test_articulation.py .......... [ 7%]
tests/test_chart_export.py ........................... [ 11%]
tests/test_chord_recognizer.py .................... [ 14%]
tests/test_chords.py ............................. [ 18%]
tests/test_cli.py ................. [ 21%]
tests/test_extractor.py ...... [ 21%]
tests/test_function_analyzer.py ........................................ [ 27%]
......... [ 29%]
tests/test_groove.py ......... [ 30%]
tests/test_health.py . [ 30%]
tests/test_hits.py ....... [ 31%]
tests/test_key_detector.py ........ [ 32%]
tests/test_native_dispatch.py .. [ 33%]
tests/test_numeric_parity.py sssssssssssssssssssssss [ 36%]
tests/test_pipeline_integration.py ......... [ 37%]
tests/test_pitch_tracker.py ............... [ 40%]
tests/test_priority.py ........... [ 41%]
tests/test_range_pressure.py ............ [ 43%]
tests/test_ranges.py ......................... [ 47%]
tests/test_register_overlap.py ............... [ 49%]
tests/test_release_asset_selection.py ........ [ 50%]
tests/test_release_metadata.py ....... [ 51%]
tests/test_release_packaging.py ......... [ 53%]
tests/test_roles.py ....... [ 54%]
tests/test_roles_ml.py ... [ 54%]
tests/test_section_harmony.py ........... [ 56%]
tests/test_segmenter.py .......................... [ 60%]
tests/test_separation.py ..............................s. [ 64%]
tests/test_supply_chain_policy.py ...................................... [ 70%]
........................................................................ [ 81%]
............................................. [ 87%]
tests/test_tempo_stability.py ............. [ 89%]
tests/test_temporal.py ............ [ 91%]
tests/test_transcription.py ......... [ 92%]
tests/test_transposition.py ............................ [ 96%]
tests/test_tuning.py ..... [ 97%]
tests/test_youtube.py ................ [100%]
## Changed-File Evidence Map
```mermaid
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: ci.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: ci.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (10 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (10 files)"]
R2 --> V2["required checks"]
Evidence --> S3["Test (2 files)"]
S3 --> I3["regression suite"]
I3 --> R3["Review risk: Test (2 files)"]
R3 --> V3["targeted test run"]
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current headd6c6fe8d5a09f2ee084b7120a7c94c4e23c93b50. -
Head SHA:
d6c6fe8d5a09f2ee084b7120a7c94c4e23c93b50 -
Workflow run: 29171866467
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
d6c6fe8d5a09f2ee084b7120a7c94c4e23c93b50 - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Python implementation completeness scan
$ python3 /home/runner/work/bandscope/bandscope/scripts/ci/implementation_completeness_scan.py --repo-root . --changed-files /tmp/tmp.RnZQS8eHW4
# Implementation Completeness Scan
- Checked runtime Python files: 3
- Declaration handling: typing.Protocol, abc.ABC, @abstractmethod, and @overload placeholders are treated as contracts, not executable missing implementations.
- Result: PASS
- Reason: no executable placeholder implementations were found in changed runtime Python files.
- Result: PASS
Python project dependencies (services/analysis-engine)
$ uv sync --project services/analysis-engine --group dev
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12
Creating virtual environment at: services/analysis-engine/.venv
Resolved 91 packages in 0.96ms
Building bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloading nvidia-cuda-nvrtc (86.0MiB)
Downloading scipy (33.6MiB)
Downloading networkx (2.0MiB)
Downloading nvidia-cufile (1.2MiB)
Downloading nvidia-cusparse (139.2MiB)
Downloading nvidia-cuda-runtime (2.1MiB)
Downloading nvidia-curand (56.8MiB)
Downloading nvidia-cuda-cupti (10.2MiB)
Downloading pygments (1.2MiB)
Downloading nvidia-nvshmem-cu13 (57.6MiB)
Downloading nvidia-nvjitlink (38.8MiB)
Downloading nvidia-cublas (403.5MiB)
Downloading soundfile (1.3MiB)
Downloading nvidia-cusolver (191.6MiB)
Downloading numba (3.6MiB)
Downloading nvidia-cusparselt-cu13 (162.3MiB)
Downloading sympy (6.0MiB)
Downloading nvidia-cufft (204.2MiB)
Downloading triton (188.6MiB)
Downloading numpy (15.8MiB)
Downloading nvidia-cudnn-cu13 (349.2MiB)
Downloading setuptools (1.0MiB)
Downloading nvidia-nccl-cu13 (196.4MiB)
Downloading cuda-bindings (6.3MiB)
Downloading yt-dlp (3.0MiB)
Downloading mypy (13.0MiB)
Downloading torchaudio (1.7MiB)
Downloading scikit-learn (8.5MiB)
Downloading llvmlite (53.7MiB)
Downloading torch (507.6MiB)
Downloading ruff (10.7MiB)
Building dora-search==0.1.12
Building antlr4-python3-runtime==4.9.3
Downloaded nvidia-cufile
Downloaded soundfile
Building demucs==4.0.1
Downloaded setuptools
Downloaded pygments
Downloaded torchaudio
Downloaded nvidia-cuda-runtime
Downloaded networkx
Built bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloaded yt-dlp
Downloaded numba
Built antlr4-python3-runtime==4.9.3
Built demucs==4.0.1
Built dora-search==0.1.12
Downloaded cuda-bindings
Downloaded sympy
Downloaded scikit-learn
Downloaded nvidia-cuda-cupti
Downloaded ruff
Downloaded numpy
Downloaded mypy
Downloaded scipy
Downloaded nvidia-nvjitlink
Downloaded llvmlite
Downloaded nvidia-curand
Downloaded nvidia-nvshmem-cu13
Downloaded nvidia-cuda-nvrtc
Downloaded nvidia-cusparse
Downloaded nvidia-cusparselt-cu13
Downloaded triton
Downloaded nvidia-cusolver
Downloaded nvidia-nccl-cu13
Downloaded nvidia-cufft
Downloaded nvidia-cudnn-cu13
Downloaded nvidia-cublas
Downloaded torch
Prepared 86 packages in 20.84s
Installed 86 packages in 1.42s
+ antlr4-python3-runtime==4.9.3
+ audioread==3.1.0
+ bandit==1.9.4
+ bandscope-analysis==0.1.0 (from file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine)
+ certifi==2026.2.25
+ cffi==2.0.0
+ charset-normalizer==3.4.6
+ cloudpickle==3.1.2
+ coverage==7.13.4
+ cuda-bindings==13.3.1
+ cuda-pathfinder==1.5.6
+ cuda-toolkit==13.0.2
+ decorator==5.2.1
+ demucs==4.0.1
+ dora-search==0.1.12
+ einops==0.8.2
+ filelock==3.29.5
+ fsspec==2026.6.0
+ idna==3.18
+ iniconfig==2.3.0
+ jinja2==3.1.6
+ joblib==1.5.3
+ julius==0.2.8
+ lameenc==1.8.4
+ lazy-loader==0.5
+ librosa==0.11.0
+ librt==0.8.1
+ llvmlite==0.45.1
+ markdown-it-py==4.0.0
+ markupsafe==3.0.3
+ mdurl==0.1.2
+ mpmath==1.3.0
+ msgpack==1.2.1
+ mypy==1.19.1
+ mypy-extensions==1.1.0
+ networkx==3.6.1
+ numba==0.62.1
+ numpy==2.3.5
+ nvidia-cublas==13.1.1.3
+ nvidia-cuda-cupti==13.0.85
+ nvidia-cuda-nvrtc==13.0.88
+ nvidia-cuda-runtime==13.0.96
+ nvidia-cudnn-cu13==9.20.0.48
+ nvidia-cufft==12.0.0.61
+ nvidia-cufile==1.15.1.6
+ nvidia-curand==10.4.0.35
+ nvidia-cusolver==12.0.4.66
+ nvidia-cusparse==12.6.3.3
+ nvidia-cusparselt-cu13==0.8.1
+ nvidia-nccl-cu13==2.29.7
+ nvidia-nvjitlink==13.0.88
+ nvidia-nvshmem-cu13==3.4.5
+ nvidia-nvtx==13.0.85
+ omegaconf==2.3.1
+ openunmix==1.3.0
+ packaging==26.0
+ pathspec==1.0.4
+ platformdirs==4.9.4
+ pluggy==1.6.0
+ pooch==1.9.0
+ pycparser==3.0
+ pygments==2.20.0
+ pytest==9.0.3
+ pytest-cov==7.0.0
+ pyyaml==6.0.3
+ requests==2.33.0
+ retrying==1.4.2
+ rich==15.0.0
+ ruff==0.15.5
+ scikit-learn==1.8.0
+ scipy==1.17.1
+ setuptools==81.0.0
+ soundfile==0.13.1
+ soxr==1.0.0
+ stevedore==5.7.0
+ submitit==1.5.4
+ sympy==1.14.0
+ threadpoolctl==3.6.0
+ torch==2.12.1
+ torchaudio==2.11.0
+ tqdm==4.68.3
+ treetable==0.2.6
+ triton==3.7.1
+ typing-extensions==4.15.0
+ urllib3==2.7.0
+ yt-dlp==2026.6.9
- Result: PASS
Python coverage with missing-line report (services/analysis-engine)
$ bash -c cd\ \"\$1\"\ \&\&\ PYTHONPATH=.\ uv\ run\ --with\ coverage\ --with\ pytest\ coverage\ run\ -m\ pytest\ tests\ \&\&\ uv\ run\ --with\ coverage\ coverage\ report\ --show-missing bash services/analysis-engine
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0
rootdir: /home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
configfile: pyproject.toml
plugins: cov-7.0.0
collected 675 items
tests/test_activity.py ........ [ 1%]
tests/test_anchors.py .... [ 1%]
tests/test_api.py ........................... [ 5%]
tests/test_articulation.py .......... [ 7%]
tests/test_chart_export.py ........................... [ 11%]
tests/test_chord_recognizer.py .................... [ 14%]
tests/test_chords.py ............................. [ 18%]
tests/test_cli.py ................. [ 21%]
tests/test_extractor.py ...... [ 21%]
tests/test_function_analyzer.py ........................................ [ 27%]
......... [ 29%]
tests/test_groove.py ......... [ 30%]
tests/test_health.py . [ 30%]
tests/test_hits.py ....... [ 31%]
tests/test_key_detector.py ........ [ 32%]
tests/test_native_dispatch.py .. [ 33%]
tests/test_numeric_parity.py sssssssssssssssssssssss [ 36%]
tests/test_pipeline_integration.py ......... [ 37%]
tests/test_pitch_tracker.py ............... [ 40%]
tests/test_priority.py ........... [ 41%]
tests/test_range_pressure.py ............ [ 43%]
tests/test_ranges.py ......................... [ 47%]
tests/test_register_overlap.py ............... [ 49%]
tests/test_release_asset_selection.py ........ [ 50%]
tests/test_release_metadata.py ....... [ 51%]
tests/test_release_packaging.py ......... [ 53%]
tests/test_roles.py ....... [ 54%]
tests/test_roles_ml.py ... [ 54%]
tests/test_section_harmony.py ........... [ 56%]
tests/test_segmenter.py .......................... [ 60%]
tests/test_separation.py ..............................s. [ 64%]
tests/test_supply_chain_policy.py ...................................... [ 70%]
........................................................................ [ 81%]
............................................. [ 87%]
tests/test_tempo_stability.py ............. [ 89%]
tests/test_temporal.py ............ [ 91%]
tests/test_transcription.py ......... [ 92%]
tests/test_transposition.py ............................ [ 96%]
tests/test_tuning.py ..... [ 97%]
tests/test_youtube.py ................ [100%]
## Changed-File Evidence Map
```mermaid
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: ci.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: ci.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (10 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (10 files)"]
R2 --> V2["required checks"]
Evidence --> S3["Test (2 files)"]
S3 --> I3["regression suite"]
I3 --> R3["Review risk: Test (2 files)"]
R3 --> V3["targeted test run"]
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current headcf94b5bcf491a7c30740d2db1050aae96b8a58ba. -
Head SHA:
cf94b5bcf491a7c30740d2db1050aae96b8a58ba -
Workflow run: 29173458008
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
cf94b5bcf491a7c30740d2db1050aae96b8a58ba - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Implementation completeness scan
$ python3 /home/runner/work/bandscope/bandscope/scripts/ci/implementation_completeness_scan.py --repo-root . --changed-files /tmp/tmp.AkZE6QObb9
# Implementation Completeness Scan
- Checked runtime source files: 4
- Declaration handling: typing.Protocol, abc.ABC, @abstractmethod, and @overload placeholders are treated as contracts, not executable missing implementations.
- Result: PASS
- Reason: no executable placeholder implementations were found in changed runtime source files.
- Result: PASS
Python project dependencies (services/analysis-engine)
$ uv sync --project services/analysis-engine --group dev
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12
Creating virtual environment at: services/analysis-engine/.venv
Resolved 91 packages in 0.72ms
Building bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloading sympy (6.0MiB)
Downloading nvidia-nccl-cu13 (196.4MiB)
Downloading nvidia-cuda-nvrtc (86.0MiB)
Downloading nvidia-cufft (204.2MiB)
Downloading nvidia-nvshmem-cu13 (57.6MiB)
Downloading nvidia-cudnn-cu13 (349.2MiB)
Downloading nvidia-cusparse (139.2MiB)
Downloading nvidia-nvjitlink (38.8MiB)
Downloading triton (188.6MiB)
Downloading scipy (33.6MiB)
Downloading nvidia-cuda-runtime (2.1MiB)
Downloading networkx (2.0MiB)
Downloading nvidia-cusolver (191.6MiB)
Downloading nvidia-cublas (403.5MiB)
Downloading nvidia-cufile (1.2MiB)
Downloading setuptools (1.0MiB)
Downloading pygments (1.2MiB)
Downloading soundfile (1.3MiB)
Downloading nvidia-curand (56.8MiB)
Downloading nvidia-cusparselt-cu13 (162.3MiB)
Downloading numpy (15.8MiB)
Downloading torchaudio (1.7MiB)
Downloading nvidia-cuda-cupti (10.2MiB)
Downloading mypy (13.0MiB)
Downloading scikit-learn (8.5MiB)
Downloading cuda-bindings (6.3MiB)
Downloading llvmlite (53.7MiB)
Downloading yt-dlp (3.0MiB)
Downloading numba (3.6MiB)
Downloading ruff (10.7MiB)
Downloading torch (507.6MiB)
Downloaded nvidia-cufile
Downloaded soundfile
Building antlr4-python3-runtime==4.9.3
Building dora-search==0.1.12
Building demucs==4.0.1
Downloaded torchaudio
Downloaded nvidia-cuda-runtime
Downloaded pygments
Downloaded setuptools
Built bandscope-analysis @ file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
Downloaded networkx
Downloaded numba
Built antlr4-python3-runtime==4.9.3
Built dora-search==0.1.12
Downloaded yt-dlp
Built demucs==4.0.1
Downloaded cuda-bindings
Downloaded nvidia-cuda-cupti
Downloaded ruff
Downloaded scikit-learn
Downloaded sympy
Downloaded numpy
Downloaded nvidia-nvjitlink
Downloaded scipy
Downloaded llvmlite
Downloaded nvidia-curand
Downloaded nvidia-nvshmem-cu13
Downloaded mypy
Downloaded nvidia-cuda-nvrtc
Downloaded nvidia-cusparse
Downloaded nvidia-cusparselt-cu13
Downloaded nvidia-cusolver
Downloaded nvidia-nccl-cu13
Downloaded nvidia-cufft
Downloaded triton
Downloaded nvidia-cublas
Downloaded nvidia-cudnn-cu13
Downloaded torch
Prepared 86 packages in 19.66s
Installed 86 packages in 322ms
+ antlr4-python3-runtime==4.9.3
+ audioread==3.1.0
+ bandit==1.9.4
+ bandscope-analysis==0.1.0 (from file:///home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine)
+ certifi==2026.2.25
+ cffi==2.0.0
+ charset-normalizer==3.4.6
+ cloudpickle==3.1.2
+ coverage==7.13.4
+ cuda-bindings==13.3.1
+ cuda-pathfinder==1.5.6
+ cuda-toolkit==13.0.2
+ decorator==5.2.1
+ demucs==4.0.1
+ dora-search==0.1.12
+ einops==0.8.2
+ filelock==3.29.5
+ fsspec==2026.6.0
+ idna==3.18
+ iniconfig==2.3.0
+ jinja2==3.1.6
+ joblib==1.5.3
+ julius==0.2.8
+ lameenc==1.8.4
+ lazy-loader==0.5
+ librosa==0.11.0
+ librt==0.8.1
+ llvmlite==0.45.1
+ markdown-it-py==4.0.0
+ markupsafe==3.0.3
+ mdurl==0.1.2
+ mpmath==1.3.0
+ msgpack==1.2.1
+ mypy==1.19.1
+ mypy-extensions==1.1.0
+ networkx==3.6.1
+ numba==0.62.1
+ numpy==2.3.5
+ nvidia-cublas==13.1.1.3
+ nvidia-cuda-cupti==13.0.85
+ nvidia-cuda-nvrtc==13.0.88
+ nvidia-cuda-runtime==13.0.96
+ nvidia-cudnn-cu13==9.20.0.48
+ nvidia-cufft==12.0.0.61
+ nvidia-cufile==1.15.1.6
+ nvidia-curand==10.4.0.35
+ nvidia-cusolver==12.0.4.66
+ nvidia-cusparse==12.6.3.3
+ nvidia-cusparselt-cu13==0.8.1
+ nvidia-nccl-cu13==2.29.7
+ nvidia-nvjitlink==13.0.88
+ nvidia-nvshmem-cu13==3.4.5
+ nvidia-nvtx==13.0.85
+ omegaconf==2.3.1
+ openunmix==1.3.0
+ packaging==26.0
+ pathspec==1.0.4
+ platformdirs==4.9.4
+ pluggy==1.6.0
+ pooch==1.9.0
+ pycparser==3.0
+ pygments==2.20.0
+ pytest==9.0.3
+ pytest-cov==7.0.0
+ pyyaml==6.0.3
+ requests==2.33.0
+ retrying==1.4.2
+ rich==15.0.0
+ ruff==0.15.5
+ scikit-learn==1.8.0
+ scipy==1.17.1
+ setuptools==81.0.0
+ soundfile==0.13.1
+ soxr==1.0.0
+ stevedore==5.7.0
+ submitit==1.5.4
+ sympy==1.14.0
+ threadpoolctl==3.6.0
+ torch==2.12.1
+ torchaudio==2.11.0
+ tqdm==4.68.3
+ treetable==0.2.6
+ triton==3.7.1
+ typing-extensions==4.15.0
+ urllib3==2.7.0
+ yt-dlp==2026.6.9
- Result: PASS
Python coverage with missing-line report (services/analysis-engine)
$ bash -c cd\ \"\$1\"\ \&\&\ PYTHONPATH=.\ uv\ run\ --with\ coverage\ --with\ pytest\ coverage\ run\ -m\ pytest\ tests\ \&\&\ uv\ run\ --with\ coverage\ coverage\ report\ --show-missing bash services/analysis-engine
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0
rootdir: /home/runner/work/bandscope/bandscope/pr-head/services/analysis-engine
configfile: pyproject.toml
plugins: cov-7.0.0
collected 675 items
tests/test_activity.py ........ [ 1%]
tests/test_anchors.py .... [ 1%]
tests/test_api.py ........................... [ 5%]
tests/test_articulation.py .......... [ 7%]
tests/test_chart_export.py ........................... [ 11%]
tests/test_chord_recognizer.py .................... [ 14%]
tests/test_chords.py ............................. [ 18%]
tests/test_cli.py ................. [ 21%]
tests/test_extractor.py ...... [ 21%]
tests/test_function_analyzer.py ........................................ [ 27%]
......... [ 29%]
tests/test_groove.py ......... [ 30%]
tests/test_health.py . [ 30%]
tests/test_hits.py ....... [ 31%]
tests/test_key_detector.py ........ [ 32%]
tests/test_native_dispatch.py .. [ 33%]
tests/test_numeric_parity.py sssssssssssssssssssssss [ 36%]
tests/test_pipeline_integration.py ......... [ 37%]
tests/test_pitch_tracker.py ............... [ 40%]
tests/test_priority.py ........... [ 41%]
tests/test_range_pressure.py ............ [ 43%]
tests/test_ranges.py ......................... [ 47%]
tests/test_register_overlap.py ............... [ 49%]
tests/test_release_asset_selection.py ........ [ 50%]
tests/test_release_metadata.py ....... [ 51%]
tests/test_release_packaging.py ......... [ 53%]
tests/test_roles.py ....... [ 54%]
tests/test_roles_ml.py ... [ 54%]
tests/test_section_harmony.py ........... [ 56%]
tests/test_segmenter.py .......................... [ 60%]
tests/test_separation.py ..............................s. [ 64%]
tests/test_supply_chain_policy.py ...................................... [ 70%]
........................................................................ [ 81%]
............................................. [ 87%]
tests/test_tempo_stability.py ............. [ 89%]
tests/test_temporal.py ............ [ 91%]
tests/test_transcription.py ......... [ 92%]
tests/test_transposition.py ............................ [ 96%]
tests/test_tuning.py ..... [ 97%]
tests/test_youtube.py ................ [100%]
## Changed-File Evidence Map
```mermaid
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Workflow: ci.yml"]
S1 --> I1["GitHub Actions review job"]
I1 --> R1["Review risk: Workflow: ci.yml"]
R1 --> V1["actionlint plus required checks"]
Evidence --> S2["Changed file (10 files)"]
S2 --> I2["repository behavior"]
I2 --> R2["Review risk: Changed file (10 files)"]
R2 --> V2["required checks"]
Evidence --> S3["Test (2 files)"]
S3 --> I3["regression suite"]
I3 --> R3["Review risk: Test (2 files)"]
R3 --> V3["targeted test run"]
Summary
Software with both Python and Rust should do its numeric/mathematical computation on the Rust side. This PR moves the two hottest pure-numeric kernels of the Python analysis engine (
services/analysis-engine) into a new PyO3/maturin Rust extension crate,bandscope_numeric, while keeping the NumPy reference implementations intact for parity testing and runtime fallback.Kernels moved to Rust
sections/segmenter.py::_checkerboard_noveltycheckerboard_novelty_checkerboard_novelty_referencechords/chord_recognizer.py::_viterbi_decodeviterbi_decode_viterbi_decode_referenceThese were the genuinely numeric, Python-loop-heavy kernels. Everything else that looked numeric is a thin wrapper around librosa (chroma/CQT, HPSS, pYIN, beat tracking, RMS) — that DSP already runs in compiled code, so it was left in place on purpose. Trivial/heuristic/IO code (label heuristics, priority scoring, matrix builders sized 25×25, stem-activity RMS gating) was also left as-is.
Ported, not re-derived
The Rust code is a line-for-line port of the reference math (same
1e-12log floors, same first-indexargmaxtie-breaking asnumpy.argmax). The observable analysis results do not change.Parity is the acceptance gate
tests/test_numeric_parity.pyasserts Rust ↔ Python equivalence over representative fixtures:max |Δ| <= 1e-6tests/test_native_dispatch.pycovers the pure-Python fallback branch. The engine calls the Rust path by default and transparently falls back to the reference when the extension is not installed.Build / CI
services/analysis-engine/rust/(maturin backend, modulebandscope_numeric).ci.ymlverifyjob) now installs a stable Rust toolchain, builds the extension with maturin against the project venv, installs it, then runs the existing Python suite — so the Rust path and its parity gate are exercised on every run.strict, bandit, and 100% pytest coverage.Dependencies
Permissive only — PyO3,
numpy,ndarrayand their 27 transitive crates are all MIT / Apache-2.0 / BSD-2 / Unicode-3.0 / LLVM-exception. No GPL/AGPL/LGPL.Not included
Does not touch the Tauri desktop crate or any analysis formulas. No merge intended.
🤖 Generated with Claude Code
https://claude.ai/code/session_01RTAMs4bpSZS77Xe3RQjv9P