fix(senior-unilp-manager): reject bare value-taking flags instead of silently coercing to 1/True - #1706
Closed
andrew1234-arch wants to merge 1 commit into
Closed
fix(senior-unilp-manager): reject bare value-taking flags instead of silently coercing to 1/True#1706andrew1234-arch wants to merge 1 commit into
andrew1234-arch wants to merge 1 commit into
Conversation
…silently coercing to 1/True Fixes use-agent-os#1705
1 task done
Contributor
|
Thanks for the PR and the thorough write-up on #1705. The issue has been fixed by #1860, which is now merged — it ports the same |
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.
Linked issue
Fixes #1705
Summary
unilp/fmt.py'sparse_args()turns a bare--flag(no value, orimmediately followed by another
--flag) into the booleanTrue— correctfor a real switch, wrong for anything else. Every optional value-taking flag
in
lp_write.py,lp_read.py, andratchet.pyread its value with eitherargs.get(name) or DEFAULTor a bareargs.get(name)passed straight into ahelper, with no guard against that sentinel.
True or DEFAULTevaluates toTrue(Pythonorreturns the first truthy operand), soint(True)silently becomes
1— never the real default, never an error.Traced and empirically reproduced 20 affected call sites across the three
scripts, not just the original 11 I found (
slippage-bps×5,max-tick-drift×2,
deadline-secs,expiration-days,gas-multiplier,max-attempts):1for the real default (--slippage-bps,--max-tick-drift,--deadline-secs,--expiration-days,--gas-multiplier,--max-attempts).--from,--signer-env×3,--max-fee-per-gas,--rpc×3) — e.g.TypeError: str expected, not boolinsideos.environ.get, orAttributeError: 'bool' object has no attribute 'strip'inside URLvalidation. Confirmed empirically for each, not assumed from reading.
"True"(--ownerinlp_read.py), deferring the failure ~30 lines downstream intochecksum_address's "not a 20-byte address" error.I traced every
slippage-bps/max-tick-driftuse to confirm direction: bothcompute protective bounds (max-in for mint/increase, min-out for
decrease/burn), so this bug always tightens the bound rather than loosening
it — it fails toward reverts and confusing errors, not toward fund loss.
Still a real, previously-undetected correctness bug affecting a script that
broadcasts real transactions.
This is not hypothetical or newly-invented: the sibling skill
poolsdotfun-token-launcher— which vendors this exactfmt.pyconventionverbatim (its own PR #299 description: "vendors the stdlib crypto/RPC layer
from senior-unilp-manager... Copied verbatim where possible to stay
diffable") — was already patched for precisely this bug class. Its
poolsfun/fmt.pyaddsopt_str/opt_int/opt_floatwith a comment statingthe exact hazard this PR fixes.
senior-unilp-manager's ownfmt.pyneverreceived the same fix.
lp_read.py'smain()even hand-rolls a narrower,one-off guard for its own
--rpccase(
args.get("rpc") if isinstance(args.get("rpc"), str) else None) — proofthe codebase already knows about this hazard but never applied a fix
consistently across the three scripts.
No competing PR exists for this issue.
Fix
Backported
opt_str/opt_int/opt_floatfrompoolsfun/fmt.pyintounilp/fmt.py, byte-for-byte identical to the already-acceptedimplementation — no new design surface. Rewired all 20 call sites across
lp_read.py,lp_write.py, andratchet.py. Range bounds on the newopt_int/opt_floatcalls (slippage-bps: 0–9999;deadline-secs: ≥60;gas-multiplier: ≥1.0) matchpoolsfun/pools_write.py's own precedent forthe identical parameters exactly, rather than inventing new limits.
max-tick-drift/max-attempts/expiration-daysget aminimum=1, matchingpoolsfun's
max-salt-attemptsconvention.lp_read.py's pre-existing, already-safe--rpcguard is left untouched —it fails safe today and changing it would be an unrequested behavior change
outside this bug's scope.
Tests
scripts/selftest.py(offline, no RPC, no network):_raises()helper mirroringpoolsfun/selftest.py's ownraises()— checks the exception message names the field, not just that something
raised, since a regression could swap in a different opaque exception that
happens to also be a
ValueError.opt_str/opt_int/opt_floatdirectly: absent fallsback to default, values parse correctly, whitespace trims, every bare-flag
case is rejected with a "needs a value" message (not coerced), non-numeric
values are rejected, and every bound (
slippage-bps0/9999,deadline-secs60) is enforced.lp_read.resolve_owner({"owner": True}))proving the fix is correctly wired in, not just correct in isolation.
(not skipped) by running against
upstream/mainbefore and after.Commands run:
uv run ruff check <5 touched files>
→ All checks passed!
uv run mypy src/agentos --show-error-codes
→ Success: no issues found in 625 source files
python3 scripts/selftest.py
→ 750 assertions pass
uv run pytest tests/test_skill_bundled_url_scheme.py tests/test_skill_rpc_error_non_dict_payload.py tests/test_skills_default_prompt_contract.py tests/test_skills_script_paths.py tests/test_skills_third_party_notices.py tests/test_tools/test_skill_view_budget.py -q
→ 67 passed
No
ruff format --check— every touched file is underskills/bundled/,exempt from the formatter per repo convention.
Third-party origin: none —
opt_str/opt_int/opt_floatare backportedfrom this same repository's own
poolsfun/fmt.py(PR #299, already merged).Fixes the underlying issue for good, per the acceptance criteria named above:
every one of the 20 confirmed call sites now raises a clear,
field-naming error on a bare flag instead of silently substituting a wrong
value or crashing opaquely — matching the standard the sibling skill already
set.