Repository navigation
Phase 2, theme 2: number limits (refuse, never clamp; NUM-01..05) and the exit-code-3 rule - #31
Merged
Merged
Conversation
…ode 3 needs the import marker
A number typed into a form box is read as its text (a whole number as an exact integer, a decimal one compared
with the limits as exact decimal text). Beyond a limit (default or declared) it is refused with the worker's
sentence ('L' must be <= 9007199254740991), no run starts, nothing is sent, nothing is put at the limit.
The worker hint calls exit code 3 an import failure only when the last output has `cannot import tool module`.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
Contributor
Author
Sabotage checksEach row: production code broken in a copy of the final tree of this PR (a regular expression replaced one place), the PR's own body run on it (
Generated by Claude Code |
…th-number-limits Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
guijacquemet
changed the base branch from
claude/phase2-qupath-retention
to
main
October 13, 2026 19:02
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.
Theme 2 of the wrong-science wave for QuPath: number limits (SPEC_WRONG_SCIENCE section 6, NUM-01..05) and the worker exit-code rule (Tools PR #124). Reference: Napari #55.
This PR is based on PR #30 (
claude/phase2-qupath-retention), not on main: it needs theparts.txtfile split, therunstest app and the changedrun_gui_ci.shof that PR. Merge #30 as a merge commit first and retarget this PR to main.What changes
Number limits: refuse, never clamp; the text is the value
9007199254740993was sent as9007199254740991,1.0000000000000002e15as1e15, and a declaredMaxof 10 turned a typed 11 into 10 (and the README documented it as a feature).LcNumbers(LcNumbers.groovy):LcIntegerFactoryandLcDoubleFactory(replacingLcLongValueFactoryand JavaFX'sDoubleSpinnerValueFactory) whose converters refuse text outside the limits (LcNumberError), and number getters that read the text in the box: a whole number as an exact integer (BigInteger, never a double), a decimal number compared with the limits as its exact decimal text (so1.00000000000000001e15, which a double rounds to exactly1e15, is refused too). The request carries exactly what was typed.'L' must be <= 9007199254740991/'L' must be >= -9007199254740991; a declared Max gives'Capped' must be <= 10; a decimal limit is written the Python way ('Ratio' must be <= 1000000000000000.0). The text stays in the box (so what is refused is what is seen), the status says it when the box loses focus or Enter is pressed (Enter is handled, instead of raising the converter's error inside JavaFX), and again when Run is pressed. The arrows stop at the limits.'L': '12x' is not a number,'L': '5.0' is not a whole number,'L' must be a finite numberfornan/inf,'L' is requiredfor an empty box);+5and007are 5 and 7, surrounding spaces are not part of the number.Exit code 3 is an import failure only with the marker (Tools PR #124)
LcWorker.hintForExitcalled any exit code 3 "the app's tool module failed to import". It now needs the worker's last words to containcannot import tool module(the Tools marker,log.IMPORT_FAILED_MARKER); the Windows C runtime also ends a process with 3 forabort()and a raised SIGSEGV. Code 3 without the marker gets the plain sentencethe worker process stopped unexpectedly (exit code 3); a missing package is still named first.Tests
gui_test_numbers_body.groovy(101 checks): NUM-01..05 read from conformance.json (limitsform_integer_max,unbounded_float; templatesnumber_above_maximum/number_below_minimum; the case ids) and run through the real dialog against theNumberstool of therunstest app, which reports the text and Python type of what its request carried; also checked: the run record has the exact integer, Copy as command has it, a refusal starts no run (no new record folder, same worker) and leaves the text in the box and the value unchanged, a number beyond along, an exponent beyondBigDecimal, decimals a double cannot tell apart, the text rules, an optional number, focus lost and Enter, the arrows, and the helper functions (Python float text, exact read-back).gui_test_parity_host_body.groovy: new checks for the exit-code rule, and the live crash tests (fake interpreters that print and exit 3 with and without the marker).Existing tests changed (spec supersedes them)
gui_test_parity_form_body.groovy:a_typed_integer_beyond_the_limit_stops_at_itand..._on_enter(they asserted the clamping) now assert the refusal, the status sentence and that the text is kept;a_typed_non_integer_is_said_and_the_value_keptalso asserts that the run refuses it.gui_test_parity_host_body.groovy:hint_tool_import_failed(code 3 with an empty tail was an import failure) andlive_crash_import_failed_with_the_last_words(the fake interpreter now prints the marker);hint_tool_import_failed_needs_the_markerreplaces the first.tests/run_gui_ci.sh: the new body and its scratch home.Nothing was skipped or loosened.
Sabotage checks
(see the comment on this PR)
Spec gaps and conservative choices
'L' must be <= 1000000000000000.0, Python repr of the limit), the sentences for text that is not a number and theis requiredsentence for an empty box are this host's wording.PixelSizeOf) is a text field with its own rules (positive, finite) and does not use these limits.+5/007are accepted (the HOST_PARITYnumber_textsketch rejects surrounding spaces; it is a proposal, not decided, and a GUI box is friendlier this way).Not verified
Spinnerkey handling was exercised by firing the Enter key event at the editor, not with a real keyboard.🤖 Generated with Claude Code
https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
Generated by Claude Code