reqfence
An agent regression firewall. When you change a prompt, model, or tool,
reqfencereplays saved agent traces and flags regressions by checking whether outputs still satisfy their requirements — not by text-diffing. Every check returns PASS / FAIL / UNCERTAIN.
Standalone package. Does not depend on ariadx or fie-sdk: the requirement
critic + trace schema are vendored and dependency-cleaned. Milestone 1 (CLI).
Why two tiers
Validated by the Milestone 0 derisking experiment
(🟢 GREEN): text-diff can't tell a harmless reword from a confidently-wrong
answer. reqfence uses two tiers over developer-declared requirements:
Each declared requirement has exactly one owner, decided by decidability:
| Tier | Owns | Role |
|---|---|---|
Deterministic (checks.py) |
every checkable item (JSON-valid, field-present, tool-called, word-count, …) | Primary hard gate, ~100% precision by construction |
Semantic (semantic.py) |
only the uncheckable items (factual correctness) | Catches confidently-wrong outputs; abstains (UNCERTAIN) when the judge isn't unanimous |
The semantic judge is never asked to grade a checkable item — that alone removed the false alarms an earlier "grade everything" design produced (the LLM can't reliably count words). See RESULTS.md.
Final verdict (engine.py, schema.combine): each requirement resolves to
one PASS/FAIL/UNCERTAIN; the candidate FAILs if any requirement fails,
PASSes iff all pass, else UNCERTAIN. A semantic UNCERTAIN never fails the
build; a deterministic FAIL always does.
Install
pip install -e ".[groq]" # or ".[anthropic]"; core installs with just pydantic+click
Python ≥ 3.11 (uses stdlib tomllib).
The three commands
reqfence init
Scaffolds reqfence.toml + empty fixtures.jsonl / candidates.jsonl.
reqfence record — save a baseline
Stores a frozen baseline trace + its developer-declared requirement checklist. Ingests an already-captured trace (it does not execute an agent):
# requirements.json: [{"id":"json","desc":"valid JSON","check":{"type":"valid_json"}}, ...]
reqfence record --id weather --task "Return weather as JSON" \
--requirements requirements.json --from-trace baseline_trace.json
# or convert a framework trace:
reqfence record --id t1 --task "..." --requirements reqs.json --from-langgraph messages.json
reqfence record --id t1 --task "..." --requirements reqs.json --from-openai steps.json --openai-format run_steps
reqfence check — gate a change
Replays candidate traces against baselines, runs both tiers, prints a per-requirement table, and exits non-zero if any FAIL (UNCERTAIN does not):
reqfence check # uses paths from reqfence.toml
reqfence check --no-semantic # deterministic gate only (no API key needed)
The semantic tier runs only when enabled and a key is in the environment
(GROQ_API_KEY / ANTHROPIC_API_KEY). Keys are read from the environment only;
check will also read a nearby .env for convenience but never prints or writes it.
Requirement checks (catalog)
Core six (the reliable gate, unit-tested for precision):
valid_json, contains_substring (+ regex), max_words, contains_field,
tool_called, no_tool_error.
Extended (thin, tested): min_words, min_sources, json_array_len, file_written.
Special: semantic — always abstains deterministically; only the LLM tier judges it.
Fixtures format
Versioned JSONL, one record per line (fixtures.jsonl = baselines + checklists,
candidates.jsonl = labeled candidate traces). The Milestone 0 benchmark is
migrated in under fixtures/ via python scripts/migrate_m0.py.
The format is a first-class artifact designed to grow.
Tests
pip install -e ".[dev]" && pytest # 26 tests: checks, union/abstention, fixtures, CLI
Metadata
Release files for reqfence 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| reqfence-0.1.0.tar.gz | 29.5 kB | Without provenance | Details for reqfence-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| reqfence-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for reqfence-0.1.0-py3-none-any.whl |
Total release size: 56.2 kB
Release files / reqfence-0.1.0.tar.gz
| Download URL | reqfence-0.1.0.tar.gz |
|---|---|
| Size | 29.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0119255eca8dd9480ecc3e8f7ce30b5b9d6f77673278c0343e33da779b261528
|
|
BLAKE2b-256 checksum How to use checksums |
cd090cc4663a28982c54e18514fc8dca085e8160e1415652606348ec2cc689e0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.0
|
Release files / reqfence-0.1.0-py3-none-any.whl
| Download URL | reqfence-0.1.0-py3-none-any.whl |
|---|---|
| Size | 26.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
397c16bbceed2ff7191355499df7e01485e13721a46cb9491d8b8330360065fc
|
|
BLAKE2b-256 checksum How to use checksums |
7a46e82bd8ff7a330e4ba33c754b93f887e92e778366953fe1cb12d39c65275c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.0
|
Security for reqfence 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.