Repository navigation
Harden input validation and error handling across CLI, adapters, and runner - #1
Merged
Merged
Conversation
`memeval[tui]` declared textual>=0.80, but render/tui.py imports textual.markup, which first shipped in textual 2.0.0. Installing the extra at the declared floor gave ModuleNotFoundError (verified against 0.80.0, 1.0.0 and 2.0.0). matplotlib>=3.8 was verified good as is. Add a `dev` extra (pytest, pytest-asyncio, ruff) so CI and contributors install the same thing, and run the test job on every supported minor (requires-python is >=3.10; CI only exercised 3.12). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nc5DZiN4NhcQ9mBX2SL2yP
…rors wait_ready checked only the first 10 docs. Stores retain in batches (Hindsight: 20 per POST), so a batch dropped at the tail of the 125-doc bundled corpus was invisible to the very check that exists to catch silent write loss. Sample up to 10 docs spread evenly across the corpus, first and last always included. The `#i` fallback label in `missing` stays the corpus index. Runner.query retried on OSError, and urllib's HTTPError is an OSError, so a 401/404/422 was re-issued --retries times per query: no chance of success, an inflated latency on the error row, and N extra requests to a misconfigured store. Retry HTTPError only for 5xx/408/425/429. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nc5DZiN4NhcQ9mBX2SL2yP
A foreign .jsonl in runs/ whose line parses to an array or scalar took down `memeval runs`, `memeval chart` and the replay TUI with AttributeError on .get(). Every event is an object, so drop anything else the same way a truncated line is dropped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nc5DZiN4NhcQ9mBX2SL2yP
…emeval A gold row without `answer`, a corpus row without `content`, or a probe without `checks` was a KeyError traceback after retain had already written into the store. load_corpus/load_gold/validate_probe now reject malformed input with a row number before anything is written, and load_jsonl reports the line of a JSON syntax error. A malformed gold regex is still an error row at query time, per the README contract; probe regexes are compiled at load since the probe is one small file. `memeval replay` and `memeval chart` on a missing path were tracebacks; they exit with a message. `chart RUN --ab A B` silently ignored RUN; it is now rejected. `memeval adapters` crashed on an adapter with an empty docstring. `python -m memeval` works (there was no __main__). Replace test_negation_correction_not_flagged_as_fabrication, which only asserted the negation regex matched a string, with a run against a store that recalls the negated correction (must stay clean) and one that recalls the affirmative claim (must be flagged). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nc5DZiN4NhcQ9mBX2SL2yP
…failures The five bundled adapters each carried a copy of the urllib request/ decode code, and only mem0, letta and zep folded the server's error body into the exception; hindsight and example-rest surfaced a bare status line. adapters/_http.request_json is the one copy, so a 4xx from any store says why in the run log. Request shapes are unchanged (existing FakeHTTP tests pass as-is); example-rest gains its first test. HINDSIGHT_BATCH=0 raised `range() arg 3 must not be zero` on the first retain; clamp to >= 1. HindsightAdapter.consolidate swallowed every exception, so an adversarial run against an unreachable server, or a bank that rejects the call, logged consolidate ok=true and reported the fabrication check as if consolidation had happened. Runner.consolidate already guards the call, records ok=false with the error, and continues, and doctor reports it as informational; let it propagate so the log tells the truth. Verified with mocked HTTP only, not against a live instance. README: quote the extras in the install lines so they work under zsh, and point adapter authors at the shared helper. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nc5DZiN4NhcQ9mBX2SL2yP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR significantly improves robustness by adding comprehensive input validation at load time and better error handling throughout the codebase.
Summary
The changes add early validation of corpus, gold standard, and adversarial probe files to catch configuration errors before they cause runtime failures. HTTP adapter code is consolidated into a shared module to ensure consistent error reporting. The readiness polling is improved to sample across the entire corpus rather than just the head. Query retry logic is refined to avoid retrying client errors that will fail identically.
Key Changes
Input Validation
load_corpus()andload_gold()functions that validate row structure at load time, reporting line numbers and specific missing fieldsvalidate_probe()for adversarial probes, checking corpus/checks/corrections structure and regex validity before the run startsload_jsonl()to report line numbers on JSON decode errorsHTTP Adapter Consolidation
memeval/adapters/_http.pymodule with sharedrequest_json()helperRunner Improvements
_spread()function to sample corpus docs evenly across the entire range (first and last always included) rather than just the head, catching silent write losses at the tail_retryable()to distinguish between retryable errors (5xx, 408, 425, 429) and client errors (4xx) that fail identicallyCLI and Event Handling
cli.pyto use newload_corpus()andload_gold()functionscmd_adapters()to handle adapters with empty docstrings without IndexErrorread_events()robustness to skip non-object lines in run logs (arrays, scalars, etc.)python -m memevalentry point via__main__.pyTest Coverage
Dependencies
>=0.80to>=2.0devoptional dependency group with pytest and pytest-asyncioNotable Implementation Details
range()errors