fix(cli): unify gitt issues list fill_pct math across Panel and table paths - #897
Conversation
… paths `gitt issues list` computed Fill % two different ways for the same field in the same function: - view.py:95 (Panel single-issue view): `bounty / target * 100` — raw float - view.py:146 (table all-issues view): `Decimal(bounty) / Decimal(target) * 100` For ratios that don't round identically under both formulas (e.g., 1/3, 5/12), the same on-chain issue rendered marginally different "Fill %" values depending on whether the operator passed --id or not. Extract a shared `_fill_percent(bounty, target)` helper using the Decimal path (correct, deterministic), and route both render paths through it.
anderdc
left a comment
There was a problem hiding this comment.
The bug premise doesn't hold — int / int * 100 and float(Decimal(int) / Decimal(int) * 100) collapse to the same float, so this isn't fixing a divergence. The extraction is a fine refactor on its own though, so I'll take it.
Scope down: keep the _fill_percent helper and the two call-site swaps in gittensor/cli/issue_commands/view.py. Drop tests/cli/test_issues_list_fill_pct.py entirely — the unit tests assert Python arithmetic, the "behavioral" tests pin format-string output, and the cross-mode test admits in its own docstring that both formulas yield the same float.
|
The implementation is small, but the regression test should use a value that actually fails before this change. For |
…case Reviewer flagged that the original fixture (bounty=1, target=3) didn't actually exercise the bug: 1/3 produces floats that differ at machine epsilon between the raw-float and Decimal paths, but render identically under both `:.0f` (table) and `:.1f` (Panel) format specs. The 33% vs 33.3% difference came from the format specs, not from the math path — so the test would have passed against the pre-fix code. Switch to bounty=23, target=80, which is a real rounding boundary: - 23/80*100 -> 28.749999999999996 (binary-float artifact) -> "28.7%" - Decimal helper -> 28.75 exactly -> "28.8%" The Panel-mode regression assertion now requires "28.8%" present and "28.7%" absent, which fails against the pre-fix `bounty / target * 100` formula and passes only under the unified Decimal helper. Verified locally by reverting the Panel call site and observing the expected failure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
anderdc
left a comment
There was a problem hiding this comment.
Drop tests/cli/test_issues_list_fill_pct.py; keep only the helper + two call-site swaps. The 23/80 rounding-boundary example is real, but the cosmetic impact doesn't warrant 176 lines of tests. Same scope-down as the prior review.
Cosmetic-only impact doesn't warrant 176 lines of tests; helper + two call-site swaps from df13b16 remain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
gitt issues listcomputedFill %two different ways for the same field in the same function:view.py:95— single-issue Panel view (--id <N>):view.py:146— table all-issues view:Same field, same on-chain data, two formulas. For ratios that don't round identically under both (e.g., 1/3, 5/12, 1/7), the same issue rendered marginally different
Fill %values depending on whether the operator used--idor not.Fix
Extract a shared
_fill_percent(bounty, target)helper using the Decimal path (correct, deterministic — no float-binary artifacts) and route both render paths through it.The agreement between the two render paths is now enforced by construction, not coincidence.
Type of Change
Reproduction (before this PR)
For an issue with
bounty=1, target=3:The two paths agreed for most ratios but diverged on values where binary float and Decimal disagree at the rounding boundary.
After
Both render paths call
_fill_percent. Format precision differs by mode ({:.0f}%for table,{:.1f}%for Panel), but both formats render the same underlying value.Why this isn't a duplicate
master_repositories.jsoningestion (rounding to 2 decimals) — different code path, different concern.Fill %formula or the Panel-vs-table inconsistency.Tests
tests/cli/test_issues_list_fill_pct.py— 13 new cases:_fill_percent(0, 0) == 0, negative target == 0,(100, 100) == 100, over-full > 100, parametric ratios (1/3, 5/12, 1/7, 2/11) match expected to 1e-1233%for 1/3, Panel mode shows33.3%for 1/3, both modes show33for the same data, JSON mode passesbounty_amount/target_bountythrough unchangedScope
view.py(+12 helper, 2 call-site swaps), one new test file.validate_issue_id/validate_ss58) and PR refactor: extract duplicate network/contract resolution to _resolve_contract_and_network helper #442 (extract_resolve_contract_and_network).Coordination
view.py:issues_listis currently being touched by #855 and #856 (both validate--idat parse time). This fix lives in the function body (the math, not the parse gate); whichever lands first, the other rebases trivially.Related
not_foundJSON; not regressed (existing test still passes).gitt i listto match sibling commands #855 / fix(cli): validate --id ongitt issues list(#854) #856 (OPEN) — adjacent in same function; no overlap.Labels
bugFixes #896