Skip to content

Comments

feat: harden gitt CLI with input validation, precision fix, and UX polish#219

Closed
bittoby wants to merge 1 commit intoentrius:testfrom
bittoby:feat/harden-cli-validation-ux
Closed

feat: harden gitt CLI with input validation, precision fix, and UX polish#219
bittoby wants to merge 1 commit intoentrius:testfrom
bittoby:feat/harden-cli-validation-ux

Conversation

@bittoby
Copy link
Contributor

@bittoby bittoby commented Feb 20, 2026

Summary

Harden and beautify the gitt CLI to be production-grade. All changes within gittensor/cli/issue_commands/ — no new files or dependencies.

6 files changed: helpers.py, mutations.py, view.py, vote.py, admin.py, __init__.py (+767, -321 lines)


Task 1: Fix bounty precision loss & min bounty

Files: helpers.py, mutations.py

  • --bounty changed from type=float to type=str
  • Added parse_bounty_amount() using Decimal — the old int(bounty * 1_000_000_000) silently turned tiny values into 0
  • Validates max 9 decimal places, enforces minimum 10 ALPHA
  • Removed int(bounty * 1_000_000_000) conversion in mutations.py

Task 2: Validate repo format + GitHub verification

Files: helpers.py, mutations.py

  • Added validate_repo() — strict regex replacing the old '/' not in repo check that let "//btcli", "a/b/c" etc. through
  • Added verify_github_repo() — pings GitHub API, rejects on 404, fails open on network errors
  • Applied in issue_register before any on-chain call

Task 3: Validate issue IDs + GitHub issue check

Files: helpers.py, mutations.py, vote.py, admin.py

  • Added validate_issue_id() — range check 1 ≤ value < 1,000,000
  • Applied in: register, vote solution, vote cancel, admin cancel-issue, admin payout-issue
  • Added verify_github_issue() for register only — checks issue exists, is open, is not a PR

Task 4: Validate SS58 addresses

Files: helpers.py, vote.py, admin.py

  • Added validate_ss58_address() using scalecodec.utils.ss58.ss58_decode (already a transitive dep), falls back to length check
  • Applied in: vote solution (solver_hotkey, solver_coldkey), set-owner, set-treasury, add-vali, remove-vali

Task 5: Extract format_alpha() helper

Files: helpers.py, view.py, admin.py, mutations.py

  • Added ALPHA_DECIMALS = 9, ALPHA_RAW_UNIT = 10**9 constants
  • Added format_alpha(raw, decimals=2) — returns "123.45 ALPHA"
  • Replaced all / 1e9 and / 1_000_000_000 across 12+ call sites with consistent formatting (2 decimals in tables, 4 in detail views)

Task 6: Remove deprecated code

Files: helpers.py

  • Deleted get_ws_endpoint() (20 lines) — docstring said "Deprecated: prefer resolve_network()", confirmed zero callers

Task 7: Polish CLI output & UX

Files: all 5 command files

Standardized messaging — added print_success() (green ✓), print_error() (red ✗), print_warning() (yellow !) to helpers.py. Replaced all ad-hoc console.print('[green]...') / console.print('[red]Error:...') patterns across every command.

Network header — added print_network_header(). Replaced the repeated 2-line [dim]Network:... + [dim]Contract:... pattern in every command.

Spinners — wrapped all long-running operations with console.status():

  • view.py: contract reads (read_issues_from_contract, substrate connections)
  • mutations.py: SubstrateInterface connect, contract.exec, wallet load, harvest calls
  • vote.py: wallet + subtensor + client init + vote submission
  • admin.py: all 6 commands (cancel, payout, set-owner, set-treasury, add-vali, remove-vali)

Rich Panels — added transaction summary Panels before submission (matching existing register style):

  • vote solution: blue border — shows issue ID, solver keys, PR number
  • vote cancel: yellow border — shows issue ID, reason
  • admin cancel-issue: yellow border — shows issue info + bounty
  • admin payout-issue: green border — shows issue info + bounty
  • admin set-owner: yellow border — shows new owner
  • admin set-treasury: yellow border — shows new treasury
  • admin add-vali: blue border — shows hotkey
  • admin remove-vali: red border — shows hotkey

Color-coded status — added style_status() to helpers.py. Active=green, Registered=yellow, Completed/Cancelled=dim. Applied in issues list table and detail view.

--json flag — added output_json() helper and --json option to 5 read commands:

  • issues list — outputs array of issues with raw + ALPHA amounts
  • issues bounty-pool — outputs pool total + issue count
  • issues pending-harvest — outputs treasury stake, allocated, pending
  • admin info — outputs contract config
  • vote list — outputs validators + consensus threshold

Empty states — wrapped in dim Panels with next-action guidance:

  • issues list (no issues): "Register your first issue: gitt issues register ..."
  • vote list (no validators): "Add validators with: gitt admin add-vali <HOTKEY>"

Help text — updated argument descriptions (e.g., solver_hotkey → "Solver's hotkey (SS58 address)"), added examples to docstrings.

Related Issues

Closes #210

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Other (describe below)

Testing

  • Tests added/updated
  • Manually tested

Verification commands:

# Task 1
gitt issues register --repo opentensor/btcli --issue 1 --bounty 0.00000000000001  # rejects: precision loss
gitt issues register --repo opentensor/btcli --issue 1 --bounty 5                 # rejects: below 10 ALPHA min
image
# Task 2
gitt issues register --repo "//btcli" --issue 1 --bounty 100                      # rejects: bad format
gitt issues register --repo "opentensor/doesnotexist99999" --issue 1 --bounty 100 # rejects: 404 on GitHub
image
# Task 3
gitt issues register --repo opentensor/btcli --issue 0 --bounty 100               # rejects: out of range
gitt issues register --repo opentensor/btcli --issue -1 --bounty 100              # rejects: out of range
gitt issues register --repo opentensor/btcli --issue 766 --bounty 100             # rejects: closed issue
gitt issues register --repo opentensor/btcli --issue 829 --bounty 100             # rejects: pull request
image
# Task 4
gitt vote solution 1 not-an-address 5Hyyy... 123                                  # rejects: invalid SS58
gitt admin set-owner bad-address                                                  # rejects: invalid SS58
gitt admin add-vali bad-address                                                   # rejects: invalid SS58
image
# Task 5 + 7
gitt issues list                                                                   # format_alpha, color status, spinners
gitt issues list --id 1                                                            # detail view with 4 decimals
gitt issues list --json                                                            # JSON output
gitt vote list --json                                                              # JSON output
result.mp4
# Task 6
python -c "from gittensor.cli.issue_commands.helpers import get_ws_endpoint"       # ImportError (removed)

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Changes are documented (if applicable)

@bittoby bittoby force-pushed the feat/harden-cli-validation-ux branch from 804cf11 to 1032126 Compare February 20, 2026 02:02
@bittoby bittoby changed the title feat: harden gitt CLI with input validation, precision fix, and UX polish (#210) feat: harden gitt CLI with input validation, precision fix, and UX polish Feb 20, 2026
@bittoby
Copy link
Contributor Author

bittoby commented Feb 20, 2026

Hi @anderdc
Can you give me feedback on this PR?

@anderdc
Copy link
Collaborator

anderdc commented Feb 20, 2026

howdy, we decided on mkdev's PR, nothing particularly wrong with this one, it checks all boxes, I was more in line with his code and it's legibility/elegance, there will be more bounties

@anderdc anderdc closed this Feb 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gitt cli improvements

2 participants