Summary
tools/skill-evals/src/skill_evals/runner.py reads the assertion negate key
with a truthiness check, so any non-empty value inverts the assertion.
Background
negate: true inverts a predicate so a case can assert the absence of
something, which is how several suites test that injected content was not
obeyed. The current check accepts any truthy value, so "negate": "false",
"negate": 0.1 or "negate": [] all silently do something other than what the
fixture author meant. A typo flips the assertion instead of erroring, and an
inverted security assertion passes for the wrong reason.
Where to look
runner.py line 719 - if spec.get("negate") and holds is not None:.
Lines 39 and 712 document the key as "negate": true.
tools/skill-evals/tests/ - where a regression test belongs.
Acceptance criteria
Estimated effort
~1 hour for someone new to the codebase.
Summary
tools/skill-evals/src/skill_evals/runner.pyreads the assertionnegatekeywith a truthiness check, so any non-empty value inverts the assertion.
Background
negate: trueinverts a predicate so a case can assert the absence ofsomething, which is how several suites test that injected content was not
obeyed. The current check accepts any truthy value, so
"negate": "false","negate": 0.1or"negate": []all silently do something other than what thefixture author meant. A typo flips the assertion instead of erroring, and an
inverted security assertion passes for the wrong reason.
Where to look
runner.pyline 719 -if spec.get("negate") and holds is not None:.Lines 39 and 712 document the key as
"negate": true.tools/skill-evals/tests/- where a regression test belongs.Acceptance criteria
negateis honoured only when it is the booleantrue.uv run --directory tools/skill-evals --group dev pytestpasses.Estimated effort
~1 hour for someone new to the codebase.