Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
# Pull requests that touch these files need a maintainer's approval (branch
# protection: "Require review from Code Owners"). They hold recorded results,
# the tests and the settings that decide which tests run, and the CI that runs
# them; a pull request must not edit them to make itself pass.
/test/ @Hananel-Hazan
/.github/ @Hananel-Hazan
/pyproject.toml @Hananel-Hazan
/poetry.lock @Hananel-Hazan
/pytest.ini @Hananel-Hazan
/.pytest.ini @Hananel-Hazan
/tox.ini @Hananel-Hazan
/setup.cfg @Hananel-Hazan
/.coveragerc @Hananel-Hazan
/conftest.py @Hananel-Hazan
# them; a pull request must not edit them to make itself pass. The rest run
# automatically (editor, container and build configuration), decide what gets
# installed, or define the learning rules the tests pin to their papers.
/test/ @Hananel-Hazan
/.github/ @Hananel-Hazan
/pyproject.toml @Hananel-Hazan
/poetry.lock @Hananel-Hazan
/pytest.ini @Hananel-Hazan
/.pytest.ini @Hananel-Hazan
/tox.ini @Hananel-Hazan
/setup.cfg @Hananel-Hazan
/.coveragerc @Hananel-Hazan
conftest.py @Hananel-Hazan
/.vscode/ @Hananel-Hazan
/.devcontainer/ @Hananel-Hazan
/.pre-commit-config.yaml @Hananel-Hazan
/Dockerfile @Hananel-Hazan
/.dockerignore @Hananel-Hazan
/.readthedocs.yaml @Hananel-Hazan
/docs/source/conf.py @Hananel-Hazan
/bindsnet/learning/ @Hananel-Hazan
/SECURITY.md @Hananel-Hazan
/CONTRIBUTING.md @Hananel-Hazan
10 changes: 9 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@
- `test/api_surface.json` (public API)
- `FIXED_BUGS` in `test/network/test_all_classes.py`
- [ ] I added an entry to the `Unreleased` section of `CHANGELOG.md`.
- [ ] If I used an AI tool to write or find this change, I name it here:

## AI assistance

<!-- Tick exactly one box (checked by the `AI statement` check). See "AI-assisted contributions" in CONTRIBUTING.md. -->

- [ ] No AI tools were used.
- [ ] AI tools were used, and I (a human) have read every changed line, run the tests myself, and can explain the change in my own words.

Tools used and for which parts:

## Why the results or the API changed (if they did)

Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/ai-statement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Checks that a pull request fills in the "AI assistance" section of the template
# (CONTRIBUTING.md, "AI-assisted contributions"). It reads the description only and
# runs no code from the pull request.
name: AI statement

on:
pull_request:
branches: [ master ]
types: [ opened, edited, synchronize, reopened ]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
ai-statement:
if: github.event.pull_request.user.login != 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
# The description is passed as an environment variable, never pasted into the
# script, so text in it cannot run as code.
- name: Check the AI assistance section
env:
PR_BODY: ${{ github.event.pull_request.body }}
shell: python
run: |
import os, re, sys

body = os.environ.get("PR_BODY") or ""
none = re.search(r"^- \[[xX]\] No AI tools were used", body, re.M)
used = re.search(r"^- \[[xX]\] AI tools were used, and I \(a human\) have read every changed line", body, re.M)
tools = re.search(r"^Tools used and for which parts:[ \t]*(\S.*)?$\n?((?:(?!^#).*\n?)*)", body, re.M)
described = bool(tools and ((tools.group(1) or "") + tools.group(2)).strip())
if bool(none) == bool(used):
sys.exit("Tick exactly one box in the 'AI assistance' section of the pull request description "
"(see CONTRIBUTING.md, 'AI-assisted contributions').")
if used and not described:
sys.exit("Say which AI tools were used and for which parts, under 'Tools used and for which parts:'.")
print("AI assistance section filled in.")
7 changes: 4 additions & 3 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # the base commit must be present for git worktree
persist-credentials: false
- name: Install Poetry
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
cache: poetry
Expand All @@ -49,7 +50,7 @@ jobs:
poetry run python .github/scripts/bench_ab.py
--base "$(git rev-parse HEAD^1)" --head "$HEAD_SHA" --fail-above 2
--out bench-out --summary "$GITHUB_STEP_SUMMARY"
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
if: always()
with:
name: bench-ab
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/black.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
# Use the black and isort versions pinned in poetry.lock, so CI and local
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Lists the packages a pull request adds or changes (pyproject.toml, poetry.lock,
# the Dockerfile's base image, GitHub Actions) and fails if any has a known
# vulnerability of moderate severity or worse. It reads GitHub's dependency graph
# only and runs no code from the pull request.
name: Dependency review

on:
pull_request:
branches: [ master ]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
fail-on-severity: moderate
comment-summary-in-pr: never
4 changes: 3 additions & 1 deletion .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# The image is about 7 GB (torch bundles its CUDA libraries); make room.
- name: Free runner disk space
run: sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
- name: Build sdist and wheel
Expand All @@ -30,7 +32,7 @@ jobs:
echo "Release tag $GITHUB_REF_NAME does not match pyproject version $version"
exit 1
fi
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: dist
path: dist/
Expand All @@ -44,8 +46,8 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v8
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: dist
path: dist/
- uses: pypa/gh-action-pypi-publish@release/v1
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
14 changes: 9 additions & 5 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ jobs:
name: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Poetry
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
cache: poetry
Expand All @@ -50,7 +52,7 @@ jobs:
# below the value recorded in the script (see its docstring).
- name: Check coverage floor
run: python .github/scripts/coverage_floor.py coverage.xml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: coverage-xml
path: coverage.xml
Expand All @@ -63,10 +65,12 @@ jobs:
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Poetry
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: ${{ matrix.python-version }}
cache: poetry
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/test-guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 2 # HEAD is the test merge; HEAD^1 is master it merges into
persist-credentials: false
- name: Install Poetry
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
cache: poetry
Expand All @@ -57,12 +58,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 2
persist-credentials: false
- name: Install Poetry
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
cache: poetry
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/workflow-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Audits the workflow files themselves: zizmor looks for unsafe patterns (untrusted
# text reaching a shell, unpinned actions, leaked credentials), actionlint for mistakes.
# Both run from version-pinned packages, not third-party actions.
name: Workflow lint

on:
push:
branches: [ master ]
paths: [ ".github/workflows/**" ]
pull_request:
branches: [ master ]
paths: [ ".github/workflows/**" ]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
workflow-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
- name: zizmor
run: pipx run "zizmor==1.30.1" --offline .github/workflows
- name: actionlint
run: |
go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.12
"$(go env GOPATH)/bin/actionlint"
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ see the [GitHub releases / tags](https://github.com/BindsNET/bindsnet/releases).

## [Unreleased]

### Added
- Contributor rules for AI-assisted work (`CONTRIBUTING.md`, "AI-assisted
contributions"): AI tools are welcome, a human must have read and run every change,
and autonomous agents may not submit. The pull request template has an "AI
assistance" section, and the `AI statement` workflow checks that it is filled in.
- `Workflow lint` workflow: zizmor 1.30.1 and actionlint 1.7.12 audit changes to
`.github/workflows/`.
- `Dependency review` workflow: fails a pull request that adds or updates a package
with a known vulnerability of moderate severity or worse.

### Changed
- CI actions are pinned to exact commits instead of version tags, and checkouts no
longer keep the GitHub token on disk.
- `SECURITY.md` now describes the repository controls as they are.
- `CODEOWNERS` also covers files that run automatically or define tested behaviour:
`.vscode/`, `.devcontainer/`, `.pre-commit-config.yaml`, `Dockerfile`,
`.dockerignore`, `.readthedocs.yaml`, `docs/source/conf.py`, every `conftest.py`,
`bindsnet/learning/`, `SECURITY.md` and `CONTRIBUTING.md`.

### Fixed
- The CUDA `test_transfer` tests in `test/network/test_nodes.py` and
`test/network/test_connections.py` are reported as skipped on machines without a
GPU; before, they returned early and were reported as passed.

## [0.3.5] - 2026-10-29

### Results changes (read this before upgrading)
Expand Down
26 changes: 26 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# Contributing Protocol

## AI-assisted contributions

You are welcome to use AI tools to find bugs in BindsNET and to improve it. A
person must stay responsible for the work:

- **You are the author.** The person who opens the pull request answers for every
line in it, whoever or whatever wrote it.
- **Read it and run it yourself.** Before you open the pull request, read every
changed line, run the tests on your own machine, and make sure you can explain
the change in your own words.
- **No autonomous agents.** An AI agent may not open pull requests, push commits or
post comments on its own. A pull request stating that no human has reviewed the
code is put on hold until its author has.
- **Say what you used.** Fill in the "AI assistance" section of the pull request
template: which tools, and for which parts. A CI check makes sure the section is
filled in.
- **Answer review questions yourself.** The maintainer may ask you about the design
of the change. Please answer in your own words, not with AI-generated text
(translation and grammar help are fine).

This follows the policies of NumPy
(https://numpy.org/devdocs/dev/ai_policy.html) and LLVM
(https://llvm.org/docs/AIToolPolicy.html).

## Getting started

To clone this project locally, issue

```shell
Expand Down
9 changes: 8 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ BindsNET is a research library, and its git history is part of what users rely
on. The following controls are in place on this repository:

- Force-pushes and branch deletions are blocked on every branch.
- `master` requires a pull request with an approving review.
- Changes reach `master` through pull requests with signed commits. Each needs
an approving review that covers its latest push, the code owners' review for
the paths in `.github/CODEOWNERS`, and passing test, formatting, test-guard
and speed checks. The maintainer reviews every pull request from an outside
contributor before it is merged.
- Workflows get a read-only token by default, every outside contributor's
pull request waits for the maintainer's approval before CI runs, and the
actions CI uses are pinned to exact commits.

A supply-chain incident affecting this repository was reported and remediated in
September 2026; see issue #781 for the full account. No PyPI release was
Expand Down
Loading
Loading