fix(rank): report malformed scoring results in apply instead of a traceback (#635)

* fix(rank): report malformed scoring results in apply instead of a traceback

A result that is not an object, a non-string key or a non-object scores value
raised AttributeError/TypeError and discarded the batch. They now become
errors rows and valid results in the same file still apply.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* changelog: place the #635 entry under [Unreleased]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Mads Lorentzen <madslorentzen_17@hotmail.com>
This commit is contained in:
authored and GitHub committed 2026-10-19 19:31:34 +02:00
1 parent 3c97e7bc93
commit 9b24a8a123
3 files changed
+40 -1

No files matched your search

+28
View File
@@ -805,6 +805,34 @@ class Unreachable(RankStateCase):
self.assertIn("unknown status 'unreachble'", out["errors"][0]["error"])
self.assertEqual(self.read_state()["a"]["status"], "new", "a rejected result never half-writes an entry")
def test_malformed_results_are_errors_not_a_traceback(self):
self.write_state({"a": entry(), "b": entry(title="Other")})
out = self.run_tool(
"apply",
"--results",
self.results(
[
7,
"a",
{"key": ["a"], "scores": {}},
{"key": "a", "scores": [90, 80]},
{"key": "b", "scores": {"technical": 80, "experience": 80, "behavioral": 80, "career": 80}},
]
),
expect=1,
)
self.assertEqual(
[e["error"] for e in out["errors"]],
[
"result is not an object",
"result is not an object",
"no such key in seen_jobs.json",
"scores must be an object",
],
)
self.assertEqual([r["key"] for r in out["ranked"]], ["b"], "valid results in the same batch still apply")
self.assertEqual(self.read_state()["a"]["status"], "new")
if __name__ == "__main__":
unittest.main()