Skip to content

fix: green-light CI — Dense fit-flag tracer, buffer-donation test pollution, L1 loss contract; Codecov token#855

Merged
chaoming0625 merged 1 commit into
masterfrom
fix/ci-fit-flag-tracer
Jun 19, 2026
Merged

fix: green-light CI — Dense fit-flag tracer, buffer-donation test pollution, L1 loss contract; Codecov token#855
chaoming0625 merged 1 commit into
masterfrom
fix/ci-fit-flag-tracer

Conversation

@chaoming0625

@chaoming0625 chaoming0625 commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary

Makes the full pytest brainpy/ suite (the CI command on Linux/macOS/Windows,
Py 3.13, against braintools>=0.3.0) fully green: 4180 passed, 13 skipped, 0
failed
. Fixes one real source bug, one test-isolation defect, and two stale
test contracts; also wires the Codecov token/slug into CI.

Source fix — brainpy/dnn/linear.py

Dense.update did if share.load('fit', False) and self.online_fit_by is not None:.
Inside a grad-/jit-traced fit step (BPFF/BPTT) the fit share value is a JAX
tracer, so bool(tracer) raised TracerBoolConversionError, breaking the
canonical Dense/RNNCell back-prop training example. Reordered to check the static
*_fit_by config first so the and short-circuits before the tracer is forced
when online/offline fitting is not configured. This also eliminates a cross-test
pollution: a fit that raised mid-trace left a stale traced fit in the global
share store, breaking the next test that ran Dense.update.

Test isolation — brainpy/running/jax_multiprocessing_test.py

test_vectorize_map_partial_chunk_clear_buffer called
jax_vectorize_map(..., clear_buffer=True), which triggers the process-global
bm.clear_buffer_memory() — deleting every live device buffer and poisoning
later test modules with "deleted/donated buffer" errors. Patched the wipe to a
no-op for the call (the same guard already used in boost_misc_test and
train_analysis_glue_fixes_test), keeping the code path covered without nuking
the shared session.

Test contracts

  • brainpy/train/back_propagation_test.py — rewrote the pinned-defect test
    into a regression test: asserts Dense trains under BPFF (finite losses,
    weight moves) and a subsequent plain forward pass does not raise (pollution
    guard).
  • brainpy/losses/comparison_coverage_test.pyl1_loss delegates to
    braintools.metric.l1_loss (>=0.3.0, the required/CI dependency), which reduces
    each sample to its mean absolute error then applies the batch reduction.
    Updated L1 expectations (none -> [1.5, 3.5], sum -> 5.0, mean -> 2.5) and
    comments to the 0.3.0 contract; the prior numbers pinned stale 0.1.10 behaviour.

CI — .github/workflows/CI.yml

Codecov upload now passes token: ${{ secrets.CODECOV_TOKEN }} and
slug: brainpy/BrainPy (kept files: ./coverage.xml, fail_ci_if_error: false).

Test plan

  • Full pytest brainpy/ against braintools 0.3.0: 4180 passed, 13 skipped, 0 failed.
  • Targeted: running/ + the two former victims pass (polluter neutralised);
    losses/ 85 passed; dnn/ + back_propagation_test.py + transform_test.py pass.

Summary by Sourcery

Fix Dense layer fit-flag handling to work under gradient/JIT tracing, align L1 loss tests with the current braintools contract, prevent JAX multiprocessing tests from clearing global buffers, and wire Codecov token/slug into CI coverage uploads.

Bug Fixes:

  • Ensure bp.dnn.Dense update logic only consults the traced fit flag when online/offline fitting is configured, avoiding TracerBoolConversionError during BPFF/BPTT training.
  • Prevent the JAX multiprocessing clear-buffer test from deleting process-global device buffers and contaminating subsequent tests.

Enhancements:

  • Convert the Dense fit-flag pinned-defect test into a regression test that verifies successful BPFF training, finite losses, weight updates, and absence of global share pollution.

CI:

  • Configure the Codecov GitHub Action to use the repository slug and a secret token for uploading coverage reports.

Tests:

  • Update L1 loss reduction expectations and comments to match the braintools>=0.3.0 mean-absolute-error contract.
  • Strengthen Dense BPFF regression coverage to check loss finiteness, weight changes, and a clean post-fit forward pass.
  • Guard the JAX multiprocessing clear-buffer test so it still exercises the clear_buffer path without affecting other tests.

…donation pollution, L1 loss; Codecov token

Source fix
----------
brainpy/dnn/linear.py: ``Dense.update`` did
``if share.load('fit', False) and self.online_fit_by is not None:``. Inside a
grad-/jit-traced fit step (BPFF/BPTT) the ``fit`` share value is a JAX tracer,
so converting it to a Python bool raised ``TracerBoolConversionError`` and broke
the canonical Dense/RNNCell back-prop training example. Reordered to consult the
static ``*_fit_by`` configuration first; the ``and`` then short-circuits before
the tracer is forced when online/offline fitting is not configured.

This also removes a cross-test pollution: when the fit raised mid-trace it left
a stale traced ``fit`` in the global ``share`` store, so the next test running
``Dense.update`` (e.g. ``LoopOverTime`` over a ``Dense``) also raised.

Test isolation
--------------
brainpy/running/jax_multiprocessing_test.py: ``test_vectorize_map_partial_chunk_clear_buffer``
ran ``jax_vectorize_map(..., clear_buffer=True)``, which invokes the process-global
``bm.clear_buffer_memory()`` and deletes EVERY live device buffer, poisoning later
test modules ("deleted/donated buffer" errors). Patched the wipe to a no-op for the
duration of the call (same guard already used in boost_misc_test and
train_analysis_glue_fixes_test) so the code path stays covered without nuking the
shared session.

Test contract updates
---------------------
brainpy/train/back_propagation_test.py: rewrote the pinned-defect test into a
regression test that asserts ``Dense`` trains under BPFF (finite losses, weight
moves) and that a subsequent plain forward pass does not raise (pollution guard).

brainpy/losses/comparison_coverage_test.py: ``l1_loss`` delegates to
``braintools.metric.l1_loss`` (>=0.3.0, the required/CI dependency), which reduces
each sample to its mean absolute error then applies the batch reduction. Updated
the L1 expectations (none -> [1.5, 3.5], sum -> 5.0, mean -> 2.5) and comments to
the 0.3.0 contract; the previous numbers pinned stale braintools 0.1.10 behaviour.

CI
--
.github/workflows/CI.yml: Codecov upload now passes
``token: ${{ secrets.CODECOV_TOKEN }}`` and ``slug: brainpy/BrainPy``.
@sourcery-ai

sourcery-ai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Reviewer's Guide

Makes Dense.update safe under JAX tracing, fixes a test that globally clears JAX buffers, updates L1 loss tests to match the current braintools contract, strengthens the Dense/BPFF regression test, and wires Codecov token/slug into CI so the full pytest brainpy/ suite passes under braintools>=0.3.0.

Sequence diagram for Dense.update fit-flag handling under JAX tracing

sequenceDiagram
    actor User
    participant BPFF as BPFF.fit
    participant Share as share
    participant Dense as Dense.update

    User->>BPFF: fit(...)
    BPFF->>Share: Share.save fit = tracer

    rect rgb(245,245,245)
    note over BPFF,Dense: Pre-fix behaviour
    BPFF->>Dense: update(x)
    Dense->>Share: load fit, False
    Share-->>Dense: tracer
    Dense->>Dense: [bool(tracer)]
    Dense-->>BPFF: TracerBoolConversionError
    end

    rect rgb(235,255,235)
    note over BPFF,Dense: Post-fix behaviour
    BPFF->>Dense: update(x)
    alt [online_fit_by is not None]
        Dense->>Share: load fit, False
        Share-->>Dense: tracer
        Dense->>Dense: [record fit data]
    else [online_fit_by is None]
        Dense-->>BPFF: return res (no tracer bool)
    end
    end
Loading

File-Level Changes

Change Details Files
Guard Dense.update fit-flag handling against JAX tracer bool conversion and avoid leaking traced fit flags between tests.
  • Reordered Dense.update fit-recording conditionals to check static *_fit_by configuration before consulting the dynamic share 'fit' flag, preventing TracerBoolConversionError under grad/jit tracing.
  • Kept online and offline fit recording behavior intact while ensuring that when *_fit_by is None (typical back-prop use) the tracer-backed fit flag is never converted to a Python bool.
  • Clarified inline comments documenting the tracer behavior, short-circuit rationale, and impact on the canonical RNNCell/Dense BPTT training path.
brainpy/dnn/linear.py
Convert the pinned Dense fit-flag defect test into a positive regression that asserts clean BPFF training and no global share pollution.
  • Renamed and rewrote the Dense fit-flag test to assert that BPFF training completes without tracer errors for a simple Dense model.
  • Captured Dense weights before training and asserted that losses are finite and weights change after a short BPFF fit, confirming effective training.
  • Added a pollution guard by running a post-fit forward pass and asserting it succeeds with finite outputs, ensuring no stale traced 'fit' remains in the global share store.
brainpy/train/back_propagation_test.py
Prevent test-induced global buffer clearing in JAX multiprocessing tests while still exercising the clear_buffer code path.
  • Wrapped jax_vectorize_map(..., clear_buffer=True) in a monkeypatch-style override of bm.clear_buffer_memory to a no-op during the test.
  • Restored the original bm.clear_buffer_memory in a finally block to avoid side effects on other tests.
  • Documented that the patch avoids deleting all live device arrays, which previously caused "deleted/donated buffer" errors in later tests.
brainpy/running/jax_multiprocessing_test.py
Update L1 loss tests to match the braintools>=0.3.0 mean-absolute-error semantics for all reductions.
  • Adjusted expectations for l1_loss reduction='none' to check per-sample mean absolute errors [1.5, 3.5] instead of L1 norms.
  • Updated sum and mean reduction expectations to 5.0 and 2.5 respectively, and synchronized the L1Loss class test to sum to 5.0.
  • Rewrote comments to explicitly describe the braintools 0.3.0 contract and remove references to the older 0.1.10 behavior.
brainpy/losses/comparison_coverage_test.py
Enable authenticated Codecov uploads in CI with explicit repo slug while keeping existing coverage behavior.
  • Renamed the Codecov step to clarify that it uploads coverage reports.
  • Configured the codecov-action with CODECOV_TOKEN from secrets and the brainpy/BrainPy slug for correct association.
  • Left coverage file path and fail_ci_if_error=false unchanged to preserve current CI behavior.
.github/workflows/CI.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In test_vectorize_map_partial_chunk_clear_buffer, consider using pytest's monkeypatch fixture (or a context manager helper reused where you already guard clear_buffer_memory) instead of manually reassigning bm.clear_buffer_memory to reduce the risk of leaks or interference if the test is ever parallelized or extended.
  • The new regression test test_dense_layer_fit_flag_under_grad_trace mixes several assertions (loss finiteness, weight movement, pollution guard) in one test; you might consider splitting the pollution guard into a separate test to isolate failure modes and make future regressions easier to localize.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `test_vectorize_map_partial_chunk_clear_buffer`, consider using pytest's `monkeypatch` fixture (or a context manager helper reused where you already guard `clear_buffer_memory`) instead of manually reassigning `bm.clear_buffer_memory` to reduce the risk of leaks or interference if the test is ever parallelized or extended.
- The new regression test `test_dense_layer_fit_flag_under_grad_trace` mixes several assertions (loss finiteness, weight movement, pollution guard) in one test; you might consider splitting the pollution guard into a separate test to isolate failure modes and make future regressions easier to localize.

## Individual Comments

### Comment 1
<location path=".github/workflows/CI.yml" line_range="57-61" />
<code_context>
         run: |
           pytest --cov=brainpy --cov-report=xml brainpy/
-      - name: Upload coverage to Codecov
+      - name: Upload coverage reports to Codecov
         uses: codecov/codecov-action@v5
         with:
+          token: ${{ secrets.CODECOV_TOKEN }}
+          slug: brainpy/BrainPy
           files: ./coverage.xml
           fail_ci_if_error: false
</code_context>
<issue_to_address>
**🚨 question (security):** Explicit Codecov token usage in CI might be unnecessary for a public repo and increases secret surface area.

Using `token: ${{ secrets.CODECOV_TOKEN }}` adds an extra secret to manage and expose to this workflow. For public repos, recent `codecov/codecov-action` versions typically work with just the GitHub-provided token, which simplifies configuration and slightly reduces risk.

If this repo is public and not using private uploads or advanced Codecov features, consider verifying whether the explicit `token` and `slug` are required and removing them if they’re not.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread .github/workflows/CI.yml
Comment on lines +57 to +61
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: brainpy/BrainPy

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 question (security): Explicit Codecov token usage in CI might be unnecessary for a public repo and increases secret surface area.

Using token: ${{ secrets.CODECOV_TOKEN }} adds an extra secret to manage and expose to this workflow. For public repos, recent codecov/codecov-action versions typically work with just the GitHub-provided token, which simplifies configuration and slightly reduces risk.

If this repo is public and not using private uploads or advanced Codecov features, consider verifying whether the explicit token and slug are required and removing them if they’re not.

@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

@chaoming0625 chaoming0625 merged commit 6acb75e into master Jun 19, 2026
16 checks passed
@chaoming0625 chaoming0625 deleted the fix/ci-fit-flag-tracer branch June 19, 2026 03:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant