Repository navigation
Type-validate probe inputs against the declared signature (#135) - #162
Merged
Merged
Conversation
Probe inputs for probeable_code / probeable_spec problems were only checked by parameter name, so x="abc" against f(x: int) reached the oracle and either produced a misleading "successful" result or leaked the raw Python TypeError text to the student. Backend: validate_probe_input now checks int/float/bool/str values after the existing name checks (bool never accepted for int/float; int accepted for float; Any/containers unchecked). The message names the type only when show_function_signature is on; hidden mode returns a generic message, and both oracle exception branches are sanitised in hidden mode so no path can reveal a hidden type. The view goes through a new ProbeService.validate_input so the mode decision lives in the service. Refute shares the validator and always shows its signature, so its inputs are now type-checked too. Frontend: parseInputValue parses by declared type first instead of JSON-first, returning a per-field error that disables the Probe button. Untyped fields keep JSON-first parsing and accept Python-style True/False/None. Ints outside the safe-integer range and non-Python float literals are rejected client-side. Tests: new unit suite for the validator (no DB), probe round-trip and type-mismatch integration tests in visible, hidden and refute modes, a vitest matrix for parseInputValue, and a Playwright test against a new seeded double(n: int) problem. Closes #135 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
- Treat a `= None` default as an implicit Optional and skip the type check on both sides, matching `Optional[T]`. The fallback signature parser now keeps the default on the type so normalisation can see it. - Give out-of-range ints their own message instead of the misleading "must be a whole number"; JSON cannot carry them losslessly, so they are still refused. - Remove the dead `problems.probe.valuePlaceholder` key from en and es. Pre-existing refute gaps (graded path unchecked, RefuteInput's own parser) are tracked in #163. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Owner
Author
Ultrareview triage
🤖 Generated with Claude Code |
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.
Summary
Fixes #135. Probe inputs for
probeable_code/probeable_specwere only checked by parameter name, so probingx="abc"againstf(x: int)reached the oracle and either showed a misleading "successful" result ("abcabc") or leaked the raw PythonTypeErrortext to the student.Backend
validate_probe_inputnow checksint/float/bool/strvalues after the existing name checks.boolis never accepted forintorfloat;intis accepted forfloat;Any, containers and unknown hints are unchecked.show_function_signature=False): the error is generic ("That value is not valid for parameter 'x'") so the hidden type is not revealed, and both oracle exception branches return a generic message instead of raw Python text. Visible mode says "Parameter 'x' must be an int".ProbeOracleViewcalls a newProbeService.validate_input(problem, probe_input)so the mode decision lives in the service. Response bodies are unchanged.Frontend
parseInputValueparses by declared type first (not JSON-first) and returns a per-field error;ProbePanelshows it inline, marks the inputaria-invalid, and the Probe button is disabled while any field has an error.True/False/None.enandes.Tests
tests/unit/test_probe_input_validation.py(75 tests, no DB): every primitive, the bool-for-int trap, aliases, defaults, skipped types, hidden-mode messages, oracle sanitisation._record_probenot called on mismatch, refute mismatch 400.parseInputValue(57 tests) plus composable tests throughwithSetup.double(n: int)problem ine2e-codeand a strict inline-error test.Known limitations
5.0for anintparameter is sent as5and passes;5for astrparameter is rejected generically until quoted.Optionaltypes are unchecked; the naive signature parser (parse_function_signature splits on commas naively; breaks probing for container/tuple/default signatures (3 duplicate parsers) #160) is the blocker.Related issues filed during this work
reference_solution(the oracle) — security, needs-senior-reviewparse_function_signaturesplits on commas naivelyTest plan
pytest -m "unit or integration"— 2291 passedpytest -m architecture— 51 passedruff check .clean;ruff format --checkclean on changed filesnpx vitest run src/components/activities src/features/editor— 90 passednpm run lint:check— 0 errorsnpx playwright test --project=student— 64 passed, 1 pre-existing self-skip🤖 Generated with Claude Code