Testing framework for FLUX bytecode agent policies
Project description
๐งช FLUX Policy Tester
Testing framework for FLUX bytecode agent policies โ verify behavior, fuzz edge cases, enforce conservation bounds.
FLUX policies are bytecode programs that govern AI agent behavior โ conservation laws enforced by a register-based VM. But bytecode is notoriously hard to test. A policy that correctly blocks 99% of violations but has an off-by-one in its budget calculation could let through a critical overflow. The FLUX Policy Tester brings disciplined testing to bytecode policies: unit tests with expected outcomes, adversarial fuzzing, property-based testing, and conservation bound verification. It uses the same VM as production โ not a mock โ so you're testing the real execution path.
What It Does
The Policy Tester provides a PolicyTester class that wraps a FLUX bytecode policy and runs it against test inputs. Three testing modes cover the full quality surface:
Unit testing โ define specific inputs with expected outputs. "Given temperature=72, the deadband controller should return action=idle." The tester executes the bytecode, reads the output registers, and compares to expected values. Fast, deterministic, and CI-friendly.
Adversarial fuzzing โ throw extreme, edge-case, and malformed inputs at the policy to find cracks. What happens with temperature=-999? temperature=NaN? An empty string? A megabyte of input? The fuzz tester generates adversarial inputs automatically based on the policy's declared input types and runs them, flagging any that cause crashes, hangs, or unexpected outputs.
Conservation bound verification โ given a policy and a corpus of inputs, verify that the policy never exceeds its declared conservation limits (max steps, memory budget, execution time). This catches policies that are correct in behavior but have performance pathologies on certain inputs โ a policy that loops 10,000 times on one specific input is a denial-of-service risk.
The tester includes an inline FLUX VM (the same one used in conservation-enforcer) with zero external dependencies. This means tests run in CI without installing additional packages, and test results are guaranteed to match production execution โ because it's the same VM.
Install
pip install flux-policy-tester
For development:
git clone https://github.com/SuperInstance/flux-policy-tester.git
cd flux-policy-tester
pip install -e ".[dev]"
Quick Start
from flux_policy_tester import PolicyTester
# Load a policy from the registry or from raw bytecode
tester = PolicyTester.from_registry("deadband-controller")
# โโ Unit Tests โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# Test specific inputs with expected outputs
tester.test_input(
inputs={"temperature": 72},
expected={"action": 0}, # idle
description="comfortable temperature โ idle",
)
tester.test_input(
inputs={"temperature": 80},
expected={"action": 1}, # cool
description="hot โ cool",
)
tester.test_input(
inputs={"temperature": 60},
expected={"action": 2}, # heat
description="cold โ heat",
)
# Run all unit tests
results = tester.run_unit_tests()
print(f"{results.passed}/{results.total} tests passed")
for failure in results.failures:
print(f" โ {failure.description}: {failure.error}")
Adversarial Testing
# Fuzz with extreme inputs
tester.test_adversarial(
inputs={"temperature": 99999},
description="extreme high temperature",
)
tester.test_adversarial(
inputs={"temperature": -99999},
description="extreme low temperature",
)
tester.test_adversarial(
inputs={"temperature": 0},
description="zero boundary",
)
# Auto-generate adversarial inputs based on declared types
fuzz_results = tester.fuzz_type(
input_name="temperature",
input_type="float",
strategies=["extremes", "boundaries", "nan", "negative"],
iterations=100,
)
print(f"Fuzz: {fuzz_results.crashed} crashes, {fuzz_results.unexpected} unexpected")
Conservation Bounds
# Verify the policy never exceeds conservation limits
tester.test_conservation_bounds(
corpus=all_test_inputs,
max_budget=100,
max_steps=1000,
max_memory=256,
)
# Test for performance pathologies
perf = tester.profile(
inputs=stress_test_inputs,
iterations=10000,
)
print(f"Avg cycles: {perf.avg_cycles}")
print(f"Max cycles: {perf.max_cycles}")
print(f"P99 cycles: {perf.p99_cycles}")
YAML Test Suites
# suites/deadband.yaml
policy: deadband-controller
unit_tests:
- inputs: {temperature: 72}
expected: {action: 0}
description: "comfortable โ idle"
- inputs: {temperature: 80}
expected: {action: 1}
description: "hot โ cool"
- inputs: {temperature: 60}
expected: {action: 2}
description: "cold โ heat"
adversarial:
- inputs: {temperature: 99999}
description: "extreme high"
- inputs: {temperature: -99999}
description: "extreme low"
conservation:
max_steps: 100
max_budget: 256
# Run a YAML suite
tester.run_suite("suites/deadband.yaml")
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ FLUX Policy Tester โ
โ โ
โ โโโโโโโโโโโโโโโโ โ
โ โ PolicyTester โ โ
โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ .test_input()โโโโโโถโ Inline FLUX VM โ โ
โ โ .fuzz_type() โ โ (zero-dep, from โ โ
โ โ .profile() โ โ conservation- โ โ
โ โ .run_suite() โ โ enforcer) โ โ
โ โโโโโโโโฌโโโโโโโโ โโโโโโโโโโโโฌโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Test Results โ โ Execution Trace โ โ
โ โ .passed โ โ .cycles โ โ
โ โ .failed โ โ .register_states โ โ
โ โ .errors[] โ โ .memory_accesses โ โ
โ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
API Reference
PolicyTester
class PolicyTester:
@classmethod
def from_registry(cls, policy_name: str) -> PolicyTester
@classmethod
def from_bytecode(cls, bytecode: bytes) -> PolicyTester
@classmethod
def from_file(cls, path: str | Path) -> PolicyTester
# Unit testing
def test_input(self, inputs: dict, expected: dict,
description: str = "") -> TestResult
def run_unit_tests(self) -> UnitTestResults
# Adversarial
def test_adversarial(self, inputs: dict,
description: str = "") -> AdversarialResult
def fuzz_type(self, input_name: str, input_type: str,
strategies: list[str] | None = None,
iterations: int = 100) -> FuzzResults
# Conservation
def test_conservation_bounds(self, corpus: list[dict],
max_budget: int,
max_steps: int = 1000,
max_memory: int = 256) -> ConservationResult
# Profiling
def profile(self, inputs: list[dict],
iterations: int = 1000) -> ProfileResult
# Suites
def run_suite(self, path: str | Path) -> SuiteResult
Result Types
@dataclass
class TestResult:
passed: bool
description: str
expected: dict
actual: dict
cycles: int # VM cycles consumed
@dataclass
class FuzzResults:
total_runs: int
crashed: int
unexpected: int # non-crash but wrong output
crashes: list[FuzzCrash]
coverage: float # 0.0-1.0
@dataclass
class ProfileResult:
avg_cycles: float
max_cycles: int
p99_cycles: int
avg_memory: float
max_memory: int
Testing
pip install -e ".[dev]"
# Run the tester's own tests
pytest tests/ -v
# Run a specific test suite
pytest tests/test_unit_testing.py -v
pytest tests/test_fuzzing.py -v
pytest tests/test_conservation.py -v
CLI
# Run a test suite from the command line
flux-test suites/deadband.yaml
# Run with verbose output
flux-test suites/deadband.yaml --verbose
# Run a single policy against auto-generated fuzz inputs
flux-test --policy deadband-controller --fuzz --iterations 1000
Cross-Implementation
This component exists in two languages:
- Python (
pip install flux-policy-tester) โ this repo - Rust (
cargo add flux-policy-tester) โ SuperInstance/flux-policy-tester-rs
Both implement the same specification. Choose based on your runtime.
Philosophy
Conservation enforcement is only as trustworthy as its tests. A policy with a single untested code path is a policy with a potential exploit. The FLUX Policy Tester applies the same rigor to bytecode policies that you'd apply to any safety-critical code: unit tests for expected behavior, adversarial testing for unexpected inputs, and conservation bound verification for performance safety.
This is the testing layer of the SuperInstance conservation enforcement stack. Policies are written, compiled to FLUX bytecode, tested with this framework, published to the flux-registry, and enforced at runtime by the conservation-enforcer. Each layer has a job; this layer's job is making sure policies do what they claim.
For the theoretical foundation, see AI-Writings.
Ecosystem
FLUX Runtime
- flux-vm โ Python VM (
pip install flux-vm) - flux-core โ Rust VM (
cargo add fluxvm) - flux-js โ JavaScript VM (
npm install flux-js)
Conservation
- conservation-enforcer โ Conservation-law enforcement for LLM outputs
- flux-registry โ Pre-compiled policy registry
- flux-policy-tester โ This repo โ testing framework
Philosophy
- AI-Writings โ Essays, fiction, poetry
- NEXT_HORIZONS โ Strategy
License
MIT โ see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flux_policy_tester-0.1.2.tar.gz.
File metadata
- Download URL: flux_policy_tester-0.1.2.tar.gz
- Upload date:
- Size: 28.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6908b52d37ed284f7c0e476e1c2938454cee2488d8ebc6826e4b1508fa756c2f
|
|
| MD5 |
97bf4896869b9a48352137897c3c299f
|
|
| BLAKE2b-256 |
077c632a0a8e501ca584fe61fe20449739275bbaf41645e4bd976b295f14964f
|
File details
Details for the file flux_policy_tester-0.1.2-py3-none-any.whl.
File metadata
- Download URL: flux_policy_tester-0.1.2-py3-none-any.whl
- Upload date:
- Size: 21.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f9fd36a55cb2b7cde83e47b38eec94c80034721227d167479cd2a81305cdddef
|
|
| MD5 |
37de05a23957f2eefdba6a5a142f8ebf
|
|
| BLAKE2b-256 |
b3fa51d11545b8c860d6b4f6fa0b23303d446b4ca3db0d43e1411b22e03021d2
|