Enforce numeric bounds in tool schemas #237
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nsaspy/prolog-rlm!237
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/234-numeric-schema-bounds"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #234.
RAGE slice
TDD-first from exact canonical
main267697bef10a3fffff7c093e1435ece770e7444b. Current exact candidate head isbdc8bd25faacb7c6f056f88aa18c6c536ef700f8.The bug was that
rlm_toolaccepted declarative numeric schema bounds but only checked primitiveinteger/numbertype at invocation. This made real core schemas such asminimum:1, maximum:32and #175'sexclusiveMinimum:0provider-visible but unenforced by the canonical tool boundary.TDD contract
The first branch commit (
86bbc93d866e2e409206617ac5670a70197c334b) pinned the behavior before implementation. Negative cases assert the expected structured rejection while the suite stays green; no xfail, skip, swallowed error, caller-side workaround, or CI weakening is used.Focused contracts cover:
exclusiveMinimum:0rejects zero and negatives before handler execution;minimum/maximumboundaries are exact;exclusiveMaximumrejects the exact boundary;Analyze / research
Live source showed this is not an
exclusiveMinimum-only feature gap:rlm_prompt_compileralready publishes the realsearch_toolslimit schema withminimum:1andmaximum:32. The smallest coherent dialect is therefore the four numeric bound keywords already represented by current contracts:minimummaximumexclusiveMinimumexclusiveMaximumNo matching downstream implementation/ownership was found in
lost-rob0t/a0-symbolicsorlost-rob0t/agentProlog; this is generic runtime behavior.Design / realization
The fix stays inside the existing
validate_schema_definition/1+validate_schema_value/3path:integer|numberduring registration;tool_error{phase:schema,kind:schema_validation_failed,...}envelope and nested path;type:numberas before.No second schema subsystem, provider validator, authority path, effect path, scheduler, or downstream product logic was added.
Adversarial review
The first realization used a code-owned constructed comparison goal. Although the comparator was not model-controlled, that introduced unnecessary meta-call surface. It was replaced with closed explicit predicates for each supported bound, so no bound key or comparator becomes callable data.
A later adversarial pass found one unrelated
metadata_context/2no-op/singleton contaminating the branch. The cleanup was built as a detached Git object, inspected before the branch moved, then fast-forwarded asbdc8bd25faacb7c6f056f88aa18c6c536ef700f8. That cleanup commit changes exactly one hunk: it restores the canonical session metadata clause from!, Context = session(Session).to!.The complete candidate diff is now scope-clean and changes only:prolog/rlm_tool.pltest/rlm_tool_test.pldocs/tools.mddocs/tools.mdalso corrects a stale ordering statement: the executable runtime intentionally validates arguments before capability authorization, and existing tests already enforce that behavior.Exact-head verification
The exact candidate head
bdc8bd25faacb7c6f056f88aa18c6c536ef700f8was tested through synthetic merge commitb70bace37df7854178bddf076001301b840d5705, which merges that exact head into unchanged canonicalmain267697bef10a3fffff7c093e1435ece770e7444b.All returned required workflows are green on this head:
Current
mainhas not moved from the tested base. Current PR review submissions and unresolved review threads are empty. Any changed candidate head invalidates this evidence.Non-goals
RAGE adversarial review HOLD on exact head
07b552e2c0eb47faf9c9c48635cc1879f99b5a8d.The numeric-bound implementation and exact-head gates are green, but the branch currently contains an unrelated no-op/singleton change in
metadata_context/2:Contextis not the clause output; the second argument is alreadysession(Session). Canonicalmainends that clause at!.This line does not belong to #234, introduces a stray singleton variable, and should be removed before promotion. Keep the PR draft until the diff is scope-clean, then rerun the full exact-head gate because any cleanup commit invalidates the current SHA evidence.No weakening of the numeric tests: the failure contracts should continue to assert structured rejection while CI stays green.
RAGE recovery update on exact head
33a76a820aa86187b86a88fefbde604a847a3605: the failed whole-file cleanup attempt was fully reverted as a fast-forward restore.07b552e2...->33a76a82...has zero net file changes, and the restored exact head is green across CI, Paid OpenRouter, Nix flake, Clean SWI pack install, and Tree-sitter FFI. The prior adversarial HOLD still stands because the unrelatedContext = session(Session)no-op remains inmetadata_context/2. Do not promote/merge until that line is removed without changing the numeric-bound contract, followed by a fresh exact-head gate.RAGE adversarial HOLD resolved on exact head
bdc8bd25faacb7c6f056f88aa18c6c536ef700f8.The unrelated
metadata_context/2contaminant is gone. The cleanup commit was constructed as a detached Git object, inspected before the branch moved, and its entire diff is one hunk restoring the canonical session clause from!, Context = session(Session).to!.The complete PR remains limited toprolog/rlm_tool.pl,test/rlm_tool_test.pl, anddocs/tools.md.Fresh exact-head verification is green on the synthetic merge ref into unchanged
main267697bef10a3fffff7c093e1435ece770e7444b: 895/895 deterministic PlUnit tests, benchmark/conformance, deep recursion, CLI/trace, restart checks, credential-backed REAL OpenRouter, pinned Paid OpenRouter, Nix flake, clean SWI pack install, Tree-sitter FFI, and whitespace all passed.Adversarial decision: GO from the engineering side. The negative numeric-bound contracts continue to assert structured rejection while the suite stays green.