Skip to content

chore: release v0.13.0 #189

chore: release v0.13.0

chore: release v0.13.0 #189

Workflow file for this run

name: CI
on:
push:
branches: ["main", "claude/**", "feature/**"]
pull_request:
branches: ["main"]
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- run: cargo fmt --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --all-targets --all-features -- -D warnings
test:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test --all-features
build:
name: Build release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --release
benchmark:
name: Benchmark regression
runs-on: ubuntu-latest
needs: [test]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build
run: cargo build --release
- name: Representative fixture — recall must be 1.0
run: |
out=$(./target/release/fuzzd benchmark --schema bench/mcptox_representative.json --output json)
fn=$(echo "$out" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['fn'])")
recall=$(echo "$out" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['recall'])")
echo "recall=$recall fn=$fn"
[ "$fn" = "0" ] || { echo "FAIL: fn=$fn (recall regression on representative fixture)"; exit 1; }
- name: Combined fixture — precision ≥ 0.90, recall 1.0
run: |
python3 - <<'EOF'
import json, subprocess, sys, tempfile, os
attacks = json.load(open("bench/mcptox_representative.json"))
clean = json.load(open("bench/clean_tools.json"))
combined = attacks + clean
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
json.dump(combined, f); fname = f.name
out = subprocess.check_output(
["./target/release/fuzzd", "benchmark", "--schema", fname, "--output", "json"]
)
os.unlink(fname)
d = json.loads(out)
print(f"precision={d['precision']:.3f} recall={d['recall']:.3f} fp={d['fp']} fn={d['fn']}")
if d["fn"] != 0:
print(f"FAIL: fn={d['fn']} (recall regression)"); sys.exit(1)
if d["precision"] < 0.90:
print(f"FAIL: precision={d['precision']:.3f} < 0.90 (new false positives)"); sys.exit(1)
EOF
- name: Actual dataset — no false positives
run: |
out=$(./target/release/fuzzd benchmark --schema bench/mcptox_actual.json --output json)
fp=$(echo "$out" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['fp'])")
recall=$(echo "$out" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['recall'])")
echo "fp=$fp recall=$recall"
[ "$fp" = "0" ] || { echo "FAIL: fp=$fp (false positives on actual dataset)"; exit 1; }