[P0 BUG] Enforce declared numeric bounds in rlm_tool schema validation #234
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#234
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Bug
rlm_toolcurrently accepts numeric schema keywords such asexclusiveMinimumin declarative tool schemas but does not enforce them during invocation validation.Exact source baseline:
main267697bef10a3fffff7c093e1435ece770e7444b.Current
validate_schema_definition/1acceptstype:numberproperty schemas carrying additional bound keys. At runtime, however,validate_type(number, _, Value, _)checks onlynumber(Value)and succeeds. The same gap applies to integer values becausevalidate_type(integer,...)likewise checks only the primitive type.This was exposed while adversarially reviewing #175/#221:
rlm_subagentadvertisestimeout_seconds:_{type:number,exclusiveMinimum:0}. #221 correctly has an independent host-owned timeout-policy rejection before child spawn, so this bug must be fixed generically rather than smuggled into that deadline transaction.No matching downstream implementation was found in
lost-rob0t/a0-symbolicsorlost-rob0t/agentProlog; this is a reusable core schema/runtime contract.RAGE / TDD contract
Falsifiable regression
Register a normal read-only fixture tool whose argument schema declares a numeric lower bound, then invoke it with a value that violates the bound. On the baseline runtime the handler is reachable because the bound is ignored. The fixed runtime must reject the value at the canonical schema boundary before capability/authority/handler execution, returning the existing structured
tool_error{phase:schema,kind:schema_validation_failed,...}family.Negative tests assert the expected structured rejection while the test suite stays green; do not use intentional-red CI, xfail, skips, swallowed errors, or weaker host-side validation as a substitute.
Analyze / design
Keep one schema validator in
rlm_tool; do not add domain-specific checks to callers.Before realization, inspect all numeric bound keywords already admitted/used by repository schemas and choose the smallest coherent supported set. At minimum, a declared
exclusiveMinimummust no longer be decorative. Ifminimum,maximum, andexclusiveMaximumare already part of the accepted schema dialect or used by current declarations, enforce them through the same helper rather than creating asymmetric one-off behavior.Schema-definition validation must also reject malformed bound declarations (non-numeric bound values and internally contradictory bounds) rather than preserving impossible/deceptive contracts.
The runtime must preserve:
numbervalues where the current dialect permits them;Adversarial cases
Cover at least:
exclusiveMinimum:0rejects0and a negative value;Decision gate
GO only if the fix remains a small extension of the existing
validate_schema_definition/1+validate_schema_value/3path. HOLD/re-design if supporting the declared keywords would require a second schema subsystem or change the public schema dialect broadly.Verification
Run focused tool-schema tests, canonical deterministic suite, benchmark/conformance, CLI/trace, Nix flake, clean pack install, Tree-sitter FFI, and configured REAL/Paid OpenRouter gates on the exact candidate head. Any changed head invalidates earlier evidence.
Non-goals
RAGE exact-head realization/verification record for PR #237.
Decision: GO on exact candidate head
bdc8bd25faacb7c6f056f88aa18c6c536ef700f8against unchanged canonicalmain267697bef10a3fffff7c093e1435ece770e7444b.The implementation remains inside the existing
rlm_toolschema-definition/value-validation path and supports the coherent numeric subsetminimum,maximum,exclusiveMinimum, andexclusiveMaximum. Bound metadata is validated at registration; contradictory/empty intervals fail there; argument and result values use the same semantics; nested paths and the existing structured schema-error envelope are preserved; invalid arguments never reach the handler.Adversarial review removed two risks before promotion: the initial constructed comparison goal was replaced with closed explicit predicates, and the unrelated
metadata_context/2no-op/singleton was removed in a one-hunk cleanup commit inspected before the branch ref moved. No model-controlled data becomes callable and no authority/capability/effect boundary is widened.Fresh verification ran on synthetic merge commit
b70bace37df7854178bddf076001301b840d5705(exact head into exact main): canonical deterministic PlUnit 78 suites / 895 passed / 0 failed / 0 timeout / 0 blocked / 0 fixme, benchmark/conformance 16/16, deep recursion 15/15, CLI/trace, graph/artifact restart, whitespace, REAL OpenRouter, Paid OpenRouter, Nix flake, clean SWI pack install, and Tree-sitter FFI all passed.PR #237 is now non-draft and mergeable. Issue remains open until the change is actually merged/reconciled.