Skip to content

perf(analysis-engine): move numeric kernels to Rust (PyO3) with Python parity fallback#613

Open
seonghobae wants to merge 10 commits into
developfrom
perf/numeric-core-rust
Open

perf(analysis-engine): move numeric kernels to Rust (PyO3) with Python parity fallback#613
seonghobae wants to merge 10 commits into
developfrom
perf/numeric-core-rust

Conversation

@seonghobae

Copy link
Copy Markdown
Collaborator

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

Kernel Where it lived Rust function Python reference kept
Checkerboard SSM novelty — O(n·k²) diagonal convolution used for structural segmentation sections/segmenter.py::_checkerboard_novelty checkerboard_novelty _checkerboard_novelty_reference
Log-space Viterbi chord decoding — O(n_frames·n_states²) DP chords/chord_recognizer.py::_viterbi_decode viterbi_decode _viterbi_decode_reference

These 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-12 log floors, same first-index argmax tie-breaking as numpy.argmax). The observable analysis results do not change.

Parity is the acceptance gate

tests/test_numeric_parity.py asserts Rust ↔ Python equivalence over representative fixtures:

  • Novelty curve (f64): max |Δ| <= 1e-6
  • Viterbi decoded states (int): exact equality

tests/test_native_dispatch.py covers 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

  • New crate: services/analysis-engine/rust/ (maturin backend, module bandscope_numeric).
  • CI (ci.yml verify job) 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.
  • Existing gates stay green: ruff, ruff-format, mypy strict, bandit, and 100% pytest coverage.

Dependencies

Permissive only — PyO3, numpy, ndarray and 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

…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
Comment thread services/analysis-engine/rust/Cargo.lock Fixed
Comment thread services/analysis-engine/rust/Cargo.lock Fixed
Comment thread services/analysis-engine/rust/Cargo.lock Fixed
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

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head e2e0516e416c0f79253662b1697d7994340bbf6c.

  • 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"]

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: cf94b5bcf491a7c30740d2db1050aae96b8a58ba
  • Workflow run: 29173458008
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head cf94b5bcf491a7c30740d2db1050aae96b8a58ba.

  • 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"]

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head c9a8b0fc027e1e3b75ef35e9a71bd75a3ae595a7.

  • 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"]

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head d6c6fe8d5a09f2ee084b7120a7c94c4e23c93b50.

  • 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"]

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before 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 head cf94b5bcf491a7c30740d2db1050aae96b8a58ba.

  • 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"]

@seonghobae seonghobae enabled auto-merge (squash) July 12, 2026 12:31
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.

2 participants