Originally created by: fu351
The raise-only invariant on the pairwise primitive combine() (src/doberman/engine/decision_engine.py:93) is already exhaustively covered by tests/unit/test_verdict_ordering.py (a hypothesis-based property test plus a full VerdictxVerdict matrix, including commutativity and never-de-escalates checks). What's not covered by an exhaustive test is the actual production reduction loop that chains it: ObjectiveGuardrail.evaluate() (src/doberman/engine/objective.py), which folds every built-in rule's GuardrailResult through combine() one at a time. tests/unit/test_objective_guardrail.py only checks a handful of hand-picked rule combinations, not an exhaustive sweep.
A new test in tests/unit/ that builds a small set of stub Guardrail-shaped rules (each returning a fixed Verdict/Risk), sweeps every combination via itertools.product over a small Verdict list (2-3 stub rules is enough), runs them through ObjectiveGuardrail(rules=...), and asserts the final verdict/risk is never lower than max() over the stub verdicts/risks. Must not change combine(), ObjectiveGuardrail, or any built-in rule — this issue only adds a test.
src/doberman/engine/objective.py — ObjectiveGuardrail.evaluate() (the reduction loop under test).tests/unit/test_objective_guardrail.py — existing hand-picked-rule tests; extend or sit alongside this file.tests/unit/test_verdict_ordering.py — read first: this already exhaustively covers pairwise combine(), so don't duplicate it — this issue targets the loop, not the primitive.max() of the stub rules' individual verdicts/risks, across every combination the itertools.product sweep covers.combine(), ObjectiveGuardrail, or any built-in rule.ruff check . && ruff format --check . and lint-imports passpytest passespytest tests/unit/test_objective_guardrail.py -v
combine(), max_verdict(), or max_risk() in decision_engine.py.hypothesis as a new dependency — it's already in the dev extra if you want it, but a plain itertools.product loop is enough here.New here? Start with CONTRIBUTING.md. Issues are labelled level-1 (docs only) through level-10 (new subsystem) — pick one at your level and climb. Comment to claim an issue before starting.
Originally posted by: jasperdingg
Hi, I would love to work on this issue!
Ticket changed by: fu351