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
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
85 changes: 85 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

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

jobs:
quality:
name: ${{ matrix.os }} / Python ${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
python-version: "3.10"
- os: ubuntu-latest
python-version: "3.11"
- os: ubuntu-latest
python-version: "3.12"
- os: ubuntu-latest
python-version: "3.13"
- os: windows-latest
python-version: "3.11"

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: requirements-dev.txt
- name: Install package and development tools
run: python -m pip install -e . -r requirements-dev.txt
- name: Check formatting
run: python -m ruff format --check neural_mesh tests examples
- name: Lint
run: python -m ruff check neural_mesh tests examples
- name: Type check
run: python -m mypy neural_mesh tests examples
- name: Test
run: python -m pytest

distribution:
name: Distribution smoke test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
cache: pip
cache-dependency-path: requirements-dev.txt
- name: Install build tools
run: python -m pip install -r requirements-dev.txt
- name: Build and validate metadata
run: |
python -m build
python -m twine check dist/*
- name: Inspect wheel contents
run: python -m zipfile -l dist/neural_mesh-0.2.0-py3-none-any.whl
- name: Install wheel outside the checkout
run: |
python -m venv "${RUNNER_TEMP}/neural-mesh-smoke"
"${RUNNER_TEMP}/neural-mesh-smoke/bin/python" -m pip install --no-deps dist/neural_mesh-0.2.0-py3-none-any.whl
cd "${RUNNER_TEMP}"
"${RUNNER_TEMP}/neural-mesh-smoke/bin/python" -c "import neural_mesh; print(neural_mesh.__version__)"
"${RUNNER_TEMP}/neural-mesh-smoke/bin/neural-mesh" --version
Comment on lines +73 to +80

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Derive the wheel path instead of hardcoding 0.2.0.

The job builds the version declared by package metadata but inspects and installs only neural_mesh-0.2.0-py3-none-any.whl. The next version bump will make CI fail before validating the newly built artifact.

Use a metadata- or glob-derived wheel path for both inspection and installation.

As per the release workflow contract, package versions are read from pyproject.toml rather than fixed in automation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 73 - 80, Update the wheel inspection
and installation steps to derive the artifact path from the built files or
package metadata instead of hardcoding neural_mesh-0.2.0-py3-none-any.whl. Reuse
the derived path for both python -m zipfile -l and pip install, while preserving
the existing smoke-test commands in the Install wheel outside the checkout step.

"${RUNNER_TEMP}/neural-mesh-smoke/bin/python" -m neural_mesh --version
- name: Run installed offline demo
run: |
cd "${RUNNER_TEMP}"
"${RUNNER_TEMP}/neural-mesh-smoke/bin/neural-mesh" demo
93 changes: 93 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Release

on:
release:
types: [published]

permissions:
contents: read

concurrency:
group: release-${{ github.event.release.tag_name }}
cancel-in-progress: false

jobs:
build:
name: Verify and build distributions
if: ${{ !github.event.release.prerelease && !github.event.release.draft }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
ref: ${{ github.event.release.tag_name }}
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.11"
cache: pip
cache-dependency-path: requirements-dev.txt
Comment on lines +26 to +30

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
if [ -f .github/workflows/release.yml ]; then
  nl -ba .github/workflows/release.yml | sed -n '1,220p'
else
  echo ".github/workflows/release.yml not found"
fi

echo
echo "== all release workflow references =="
rg -n "setup-python|cache=|pip|build|attest|publish|permissions:" .github/workflows/release.yml || true

echo
echo "== zizmor references if any =="
rg -n "zizmor|cache|poison|pip cache" -S . || true

echo
echo "== git status/stat =="
git status --short
git diff --stat

Repository: Deathcharge/neural-mesh

Length of output: 1932


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repo availability =="
pwd
git rev-parse --show-toplevel || true
git status --short 2>/dev/null || true
git ls-files 2>/dev/null | head -50 || true

echo
echo "== workflow excerpt =="
if [ -f .github/workflows/release.yml ]; then
  nl -ba .github/workflows/release.yml | sed -n '1,220p'
else
  echo ".github/workflows/release.yml not found"
fi

echo
echo "== setup/cache/build references in release workflow =="
rg -n "setup-python|cache=|pip|build|attest|publish|permissions:" .github/workflows/release.yml || true

echo
echo "== zizmor references in repo =="
rg -n "zizmor|cache poisoning|cache-poisoning|pip cache|cache-dependency-path" -S . || true

Repository: Deathcharge/neural-mesh

Length of output: 1932


🌐 Web query:

GitHub Actions pip cache poisoning setup-python cache cache-dependency-path cache key cache poisoning

💡 Result:

GitHub Actions cache poisoning occurs when an untrusted workflow (such as one triggered by a Pull Request) writes malicious or corrupted dependencies into the shared action cache [1][2]. Subsequent, more privileged workflows (like those on the main branch) may then restore this poisoned cache, potentially leading to unauthorized code execution [1][2]. For actions/setup-python, the cache input enables built-in caching for package managers like pip, pipenv, and poetry [3][4]. By default, this action calculates a cache key based on the hash of dependency files (e.g., requirements.txt or pyproject.toml) [3][5]. The cache-dependency-path input allows you to specify custom dependency files or directories to include in this hash, providing more granular control over what triggers a cache miss or hit [3][6]. To mitigate cache poisoning risks, follow these practices: 1. Use Read-Only Mode: When running workflows on untrusted code (e.g., Pull Requests), configure the action to use the cache without writing to it [7]. The actions/setup-python action supports a cache-write input (or similar mechanisms depending on the version) that can be set to false for PRs [7][2]. Example configuration: - uses: actions/setup-python@v6 with: python-version: "3.12" cache: pip cache-write: ${{ github.event_name!= 'pull_request' }} 2. Separate Caches: Ensure that sensitive, privileged workflows (like those that publish packages or artifacts) do not share write access to the same cache keys used by PR-triggered workflows [8][2]. 3. Validate Dependencies: Always review code changes in PRs before labeling them as safe for execution in environments where secrets or sensitive permissions are present [1]. By disabling cache writes on untrusted PRs, you prevent them from modifying the shared cache that the main branch relies on, effectively neutralizing the poisoning vector [7][2].

Citations:


🌐 Web query:

actions/setup-python cache-write input version 7.0.0

💡 Result:

The actions/setup-python action does not currently have a cache-write input. While a pull request was proposed to add a cache-write input to support read-only cache mode [1][2], this feature has not been merged into the official release as of version 7.0.0 [3][4][5]. In version 7.0.0, which was released on July 20, 2026, the action continues to manage caching automatically based on the cache input and the cache-dependency-path configuration [3][5]. Recent updates in this version include migrating to ESM, removing the pip-install input, and upgrading the underlying @actions/cache dependency to version 6.2.0 [3]. If you are looking to control cache behavior in GitHub Actions to mitigate risks like cache poisoning, the current recommended practice remains using standard GitHub Actions caching patterns, and monitoring official repository updates for future changes to input parameters [1].

Citations:


🌐 Web query:

zizmor cache-poisoning setup-python cache pip cache-dependency-path

💡 Result:

zizmor is a static analysis tool for GitHub Actions that includes a specific audit rule called cache-poisoning [1][2]. This rule flags potential vulnerabilities where release workflows—typically triggered by events like release or push (tags)—leverage cached build states that could be manipulated by attackers to achieve unauthorized code execution during the release process [1]. When using actions/setup-python, enabling caching via cache: pip can trigger this finding because it creates a cache entry that might be persisted across different workflow runs [3][1]. Key points regarding the interaction between zizmor and actions/setup-python: 1. The Risk: An attacker with write access to the repository (e.g., via a compromised GITHUB_TOKEN or a malicious PR) could potentially poison the GitHub Actions cache [1]. If a release workflow subsequently restores and uses that poisoned cache to build or publish artifacts, it could result in supply chain compromises [3][1]. 2. Using cache-dependency-path: This input allows you to specify exactly which dependency files (e.g., requirements.txt, poetry.lock) dictate the cache key [4][5]. While cache-dependency-path is best practice for ensuring cache accuracy, it does not inherently prevent cache-poisoning [6]. 3. Remediation: To resolve zizmor cache-poisoning findings in release workflows, the primary strategy is to disable cache restoration when the workflow is running in a release context [1]. You can do this by: * Conditional Execution: Use an if condition on the step or job to skip caching when the event is a release or tag [1]. * Lookup-Only: For some actions, setting a flag like lookup-only (or equivalent) to true when a release/tag is detected can prevent the action from writing to the cache while still allowing it to look up existing entries [7]. * Disabling Caching: Simply remove caching entirely from workflows that produce official release artifacts [3][1]. If you are seeing a false positive (e.g., a release workflow that is already safely guarded), you can often suppress the finding by using appropriate conditional logic that zizmor understands, such as checking github.ref or github.event_name to explicitly disable caching during release events [7][1][8].

Citations:


Remove pip caching from the release artifact build.

cache: pip can restore dependency files whose cache key is not bound to this release commit, so the build may use poisoned cached packages before attestation/publishing. Keep caching in CI if needed, but disable it for this release workflow or enforce provenance/content hashes for cached dependency artifacts.

🧰 Tools
🪛 zizmor (1.28.0)

[error] 26-26: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): this step

(cache-poisoning)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 26 - 30, Remove the cache: pip
setting from the actions/setup-python step in the release workflow, while
retaining the Python version and cache-dependency-path configuration only if
still valid without caching. Do not alter unrelated CI workflows or release
build steps.

Source: Linters/SAST tools

- name: Verify release tag matches package version
run: >-
python -c "import os, pathlib, tomllib;
version=tomllib.loads(pathlib.Path('pyproject.toml').read_text(encoding='utf-8'))['project']['version'];
actual=os.environ['GITHUB_REF_NAME']; expected=f'v{version}';
assert actual == expected, f'release tag {actual!r} must equal {expected!r}'"
- name: Install package and pinned development tools
run: python -m pip install -e . -r requirements-dev.txt
- name: Verify source
run: |
python -m ruff format --check neural_mesh tests examples
python -m ruff check neural_mesh tests examples
python -m mypy neural_mesh tests examples
python -m pytest
- name: Build and validate distributions
run: |
python -m build
python -m twine check dist/*
- name: Upload distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-distributions
path: dist/*
if-no-files-found: error
retention-days: 7

attest:
name: Attest distributions
needs: build
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
attestations: write
Comment on lines +61 to +64

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the sensitive release permissions.

Add inline rationale for id-token: write and attestations: write in the attestation job, and for id-token: write in the publish job. This makes future least-privilege reviews explicit and prevents accidental permission expansion.

As per static analysis, zizmor reported undocumented permissions at these locations.

Also applies to: 83-85

🧰 Tools
🪛 zizmor (1.28.0)

[warning] 62-62: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 61 - 64, Document the sensitive
permissions in the attestation and publish jobs of the workflow: add concise
inline rationale comments for each id-token: write and attestations: write
entry, including the publish job’s id-token: write. Keep the existing permission
values and scopes unchanged.

Source: Linters/SAST tools

steps:
- name: Download distributions
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: python-distributions
path: dist
- name: Generate build provenance
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: "dist/*"

publish:
name: Publish distributions to PyPI
needs: [build, attest]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/neural-mesh/
permissions:
id-token: write
contents: read
steps:
- name: Download distributions
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: python-distributions
path: dist
- name: Publish distributions
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ venv.bak/
*.swo
*~
.DS_Store
.coverage
.mypy_cache/
.pytest_cache/
.ruff_cache/
coverage.xml
htmlcov/
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Changelog

All notable changes are recorded here. This project follows semantic versioning after the first
independently installable release.

## 0.2.0 - 2026-07-28

### Added

- Provider-agnostic async consensus engine with explicit request bounds.
- Deterministic normalized-token agreement clustering and quorum handling.
- Structured success, error, invalid-response, and timeout outcomes.
- Optional privacy-minimized bounded JSONL usage persistence.
- Typed public package, runnable offline example, tests, and CI/release verification.
- Installed `neural-mesh` CLI with version reporting and a credential-free demo.
- Security policy and trusted-publishing release workflow.

### Changed

- Replaced the private `helix-unified` provider dependency with an injectable provider protocol.
- Corrected consensus semantics: successful calls no longer count as agreement.
- Consolidated package metadata in `pyproject.toml` and removed unrelated runtime dependencies.
- Set the supported Python range to 3.10 through 3.13.
- Updated current company, support, package, and license identity to Samsarix LLC.

### Fixed

- Classify `asyncio.wait_for` timeouts correctly on Python 3.10 as well as newer Python versions.

### Removed

- Nonfunctional provider-specific compatibility clients whose API keys were ignored.
- Undocumented writes to `Helix/state/consensus_usage.jsonl`.

## 0.1.0 - 2026-06-16

- Initial source extraction from `helix-unified`; not independently installable.
Loading