Skip to content

Cases with an unresolvable principal score recall 0.0 and drag down mean_recall #8

Description

@royalpinto007

Desired outcome

A case that correctly retrieves nothing does not count as recall 0.0, and the dead is not None filter goes away.

Why it matters

Two connected things in app/evaluate.py.

run_case() decides recall consistently for the normal path:

else:
    recall = 1.0  # nothing was expected; not retrieving anything is perfect

But the early return for an unresolvable principal never sets recall at all:

if principal is None:
    # An unknown user retrieving nothing is correct behaviour, not an error in the eval.
    return CaseResult(case_id=case.id, user_id=case.user_id, correct_refusal=not case.should_answer, llm_judged=llm_judged)

so it takes the dataclass default of 0.0. The comment says this is correct behaviour, and passed agrees, yet the case is averaged into mean_recall as a total miss. Add one gold case for an unknown user, which is a natural ACL test to write, and the headline recall number drops even though nothing regressed. The docstring calls recall "the metric that quietly dies when you tighten security", so a false drop here is expensive: it looks exactly like the failure mode the harness exists to detect.

Second, mean_recall filters on a condition that cannot be false:

scored = [c.recall for c in self.cases if c.recall is not None]

CaseResult.recall is typed float with default 0.0 and is never assigned None anywhere in the file. The filter reads as if some cases are deliberately excluded from the average, which is misleading given the bug above, where a case genuinely should have been excluded or scored 1.0.

Steps

  1. In the principal is None branch, pass recall=1.0 when case.expected_docs is empty and 0.0 otherwise, matching the logic further down. That keeps a genuinely missed case honest.
  2. Either drop the is not None filter in mean_recall, or make recall: float | None = None a real "not scored" signal and set it deliberately. Whichever, the type and the filter should agree.
  3. Add a test: a gold case for a user id that does not exist, with expected_docs=[], must not drag mean_recall below 1.0.

Claiming this

Comment below to claim it. A reply usually comes within a day.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions