blockmachine 0.8.0__tar.gz → 0.8.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {blockmachine-0.8.0 → blockmachine-0.8.2}/PKG-INFO +1 -1
  2. {blockmachine-0.8.0 → blockmachine-0.8.2}/blockmachine.egg-info/PKG-INFO +1 -1
  3. {blockmachine-0.8.0 → blockmachine-0.8.2}/commands/leaderboard.py +19 -11
  4. {blockmachine-0.8.0 → blockmachine-0.8.2}/commands/miner.py +3 -7
  5. {blockmachine-0.8.0 → blockmachine-0.8.2}/pyproject.toml +1 -1
  6. {blockmachine-0.8.0 → blockmachine-0.8.2}/tests/test_leaderboard_cli.py +29 -12
  7. {blockmachine-0.8.0 → blockmachine-0.8.2}/__init__.py +0 -0
  8. {blockmachine-0.8.0 → blockmachine-0.8.2}/auth_config.py +0 -0
  9. {blockmachine-0.8.0 → blockmachine-0.8.2}/blockmachine.egg-info/SOURCES.txt +0 -0
  10. {blockmachine-0.8.0 → blockmachine-0.8.2}/blockmachine.egg-info/dependency_links.txt +0 -0
  11. {blockmachine-0.8.0 → blockmachine-0.8.2}/blockmachine.egg-info/entry_points.txt +0 -0
  12. {blockmachine-0.8.0 → blockmachine-0.8.2}/blockmachine.egg-info/requires.txt +0 -0
  13. {blockmachine-0.8.0 → blockmachine-0.8.2}/blockmachine.egg-info/top_level.txt +0 -0
  14. {blockmachine-0.8.0 → blockmachine-0.8.2}/client.py +0 -0
  15. {blockmachine-0.8.0 → blockmachine-0.8.2}/commands/__init__.py +0 -0
  16. {blockmachine-0.8.0 → blockmachine-0.8.2}/commands/auth.py +0 -0
  17. {blockmachine-0.8.0 → blockmachine-0.8.2}/commands/validator.py +0 -0
  18. {blockmachine-0.8.0 → blockmachine-0.8.2}/config.py +0 -0
  19. {blockmachine-0.8.0 → blockmachine-0.8.2}/endpoints.py +0 -0
  20. {blockmachine-0.8.0 → blockmachine-0.8.2}/main.py +0 -0
  21. {blockmachine-0.8.0 → blockmachine-0.8.2}/settings.py +0 -0
  22. {blockmachine-0.8.0 → blockmachine-0.8.2}/setup.cfg +0 -0
  23. {blockmachine-0.8.0 → blockmachine-0.8.2}/testing.py +0 -0
  24. {blockmachine-0.8.0 → blockmachine-0.8.2}/tests/test_cli_config.py +0 -0
  25. {blockmachine-0.8.0 → blockmachine-0.8.2}/tests/test_cli_endpoints_and_testing.py +0 -0
  26. {blockmachine-0.8.0 → blockmachine-0.8.2}/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blockmachine
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: Blockmachine CLI - Miner and validator operator interface
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/taostat/blockmachine
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blockmachine
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: Blockmachine CLI - Miner and validator operator interface
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/taostat/blockmachine
@@ -90,8 +90,12 @@ def _node_score_field(node: dict, field: str, archive: bool) -> Optional[float]:
90
90
  return node.get(field)
91
91
 
92
92
 
93
- def _is_in_rehab(node: dict, archive: bool) -> bool:
94
- """True if the node has a zero routing score in the selected dimension."""
93
+ def _is_in_probation(node: dict, archive: bool) -> bool:
94
+ """True if the node is explicitly reported as probation."""
95
+ scoring_state = node.get("scoring_state")
96
+ if scoring_state is not None:
97
+ return scoring_state == "probation"
98
+
95
99
  score = _node_score_field(node, "routing_score", archive)
96
100
  return score == 0.0
97
101
 
@@ -160,9 +164,9 @@ def _render_default(data: dict, own_hotkey: Optional[str], archive: bool) -> Non
160
164
  node_score = _node_score_field(node, "routing_score", archive)
161
165
  node_pf = _node_score_field(node, "price_factor", archive)
162
166
  node_traffic = node.get("_share") or 0.0
163
- in_rehab = _is_in_rehab(node, archive)
167
+ in_probation = _is_in_probation(node, archive)
164
168
  node_name = prefix + _node_display_name(node)
165
- if in_rehab:
169
+ if in_probation:
166
170
  node_name += " \u21ba"
167
171
 
168
172
  table.add_row(
@@ -185,12 +189,14 @@ def _render_default(data: dict, own_hotkey: Optional[str], archive: bool) -> Non
185
189
  footer_parts.append("[yellow]*[/yellow] = your miner")
186
190
  footer_parts.append(f"{len(miners)} miners")
187
191
  footer_parts.append(f"{total_cus:,} total CUs")
188
- has_rehab = any(
189
- _is_in_rehab(n, archive) for m in miners_with_scores for n in m.get("nodes", [])
192
+ has_probation = any(
193
+ _is_in_probation(n, archive)
194
+ for m in miners_with_scores
195
+ for n in m.get("nodes", [])
190
196
  )
191
- if has_rehab:
197
+ if has_probation:
192
198
  footer_parts.append(
193
- "[dim]\u21ba = in rehab (zero score, receiving synthetic probes)[/dim]"
199
+ "[dim]\u21ba = in probation (building score via synthetic probes)[/dim]"
194
200
  )
195
201
  console.print(" " + " \u00b7 ".join(footer_parts))
196
202
 
@@ -288,10 +294,12 @@ def _render_detail(data: dict, own_hotkey: Optional[str], archive: bool) -> None
288
294
  )
289
295
 
290
296
  for node in miner.get("nodes", []):
291
- rehab_tag = (
292
- " [dim]\u21ba rehab[/dim]" if _is_in_rehab(node, archive) else ""
297
+ probation_tag = (
298
+ " [dim]\u21ba probation[/dim]"
299
+ if _is_in_probation(node, archive)
300
+ else ""
293
301
  )
294
- console.print(f" [dim]{_node_display_name(node)}[/dim]{rehab_tag}")
302
+ console.print(f" [dim]{_node_display_name(node)}[/dim]{probation_tag}")
295
303
 
296
304
  lat = node.get("latency_score") or 0.0
297
305
  rel = node.get("reliability") or 0.0
@@ -17,10 +17,6 @@ from cli.config import load_config, save_config
17
17
  from cli.endpoints import get_cert_fingerprint, is_ip_endpoint, test_tls
18
18
  from cli.testing import test_health, test_rpc, test_wss
19
19
  from cli.utils import format_timestamp, resolve_node_id
20
- from common.pricing_units import (
21
- usd_per_cu_to_usd_per_million_cu,
22
- usd_per_million_cu_to_usd_per_cu,
23
- )
24
20
 
25
21
  app = typer.Typer(help="Miner node management")
26
22
  secret_app = typer.Typer(help="Secret management")
@@ -971,7 +967,7 @@ def price_simulate(
971
967
  raise typer.Exit(1)
972
968
 
973
969
  mode = "archive" if archive else "lite"
974
- simulated_bid = usd_per_million_cu_to_usd_per_cu(price)
970
+ simulated_bid = price / 1_000_000
975
971
  score_key = "routing_score_archive" if archive else "routing_score"
976
972
  pf_key = "price_factor_archive" if archive else "price_factor"
977
973
  bid_key = "bid_archive" if archive else "bid"
@@ -1039,8 +1035,8 @@ def price_simulate(
1039
1035
  console.print(f" [bold]{nr['alias']}[/bold]")
1040
1036
  console.print(
1041
1037
  f" Price factor: {_fmt_delta(nr['current_pf'], nr['new_pf'])}"
1042
- f" (bid: ${usd_per_cu_to_usd_per_million_cu(nr['current_bid']):.4f}"
1043
- f" \u2192 ${price:.4f}, median: ${usd_per_cu_to_usd_per_million_cu(nr['median']):.4f})"
1038
+ f" (bid: ${nr['current_bid'] * 1_000_000:.4f}"
1039
+ f" \u2192 ${price:.4f}, median: ${nr['median'] * 1_000_000:.4f})"
1044
1040
  )
1045
1041
  console.print(
1046
1042
  f" Routing score: {_fmt_delta(nr['current_score'], nr['new_score'])}"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "blockmachine"
7
- version = "0.8.0"
7
+ version = "0.8.2"
8
8
  description = "Blockmachine CLI - Miner and validator operator interface"
9
9
  requires-python = ">=3.10"
10
10
  license = "MIT"
@@ -179,22 +179,38 @@ class TestArchiveOrdering:
179
179
  assert archive[0]["hotkey"] == "hk-archive"
180
180
 
181
181
 
182
- class TestRehabDisplay:
183
- def test_is_in_rehab_only_for_explicit_zero_score(self):
184
- from cli.commands.leaderboard import _is_in_rehab
182
+ class TestProbationDisplay:
183
+ def test_is_in_probation_prefers_explicit_scoring_state(self):
184
+ from cli.commands.leaderboard import _is_in_probation
185
+
186
+ assert (
187
+ _is_in_probation(
188
+ {"routing_score": 0.5, "scoring_state": "probation"}, archive=False
189
+ )
190
+ is True
191
+ )
192
+ assert (
193
+ _is_in_probation(
194
+ {"routing_score": 0.0, "scoring_state": "active"}, archive=False
195
+ )
196
+ is False
197
+ )
198
+
199
+ def test_is_in_probation_falls_back_to_zero_score_when_state_missing(self):
200
+ from cli.commands.leaderboard import _is_in_probation
185
201
 
186
- assert _is_in_rehab({"routing_score": 0.0}, archive=False) is True
187
- assert _is_in_rehab({"routing_score": None}, archive=False) is False
188
- assert _is_in_rehab({}, archive=False) is False
202
+ assert _is_in_probation({"routing_score": 0.0}, archive=False) is True
203
+ assert _is_in_probation({"routing_score": None}, archive=False) is False
204
+ assert _is_in_probation({}, archive=False) is False
189
205
 
190
- def test_is_in_rehab_uses_archive_score_in_archive_mode(self):
191
- from cli.commands.leaderboard import _is_in_rehab
206
+ def test_is_in_probation_uses_archive_score_in_archive_mode(self):
207
+ from cli.commands.leaderboard import _is_in_probation
192
208
 
193
209
  node = {"routing_score": 1.0, "routing_score_archive": 0.0}
194
- assert _is_in_rehab(node, archive=True) is True
195
- assert _is_in_rehab(node, archive=False) is False
210
+ assert _is_in_probation(node, archive=True) is True
211
+ assert _is_in_probation(node, archive=False) is False
196
212
 
197
- def test_render_default_shows_rehab_marker_without_literal_markup(
213
+ def test_render_default_shows_probation_marker_without_literal_markup(
198
214
  self, monkeypatch
199
215
  ):
200
216
  from cli.commands import leaderboard
@@ -216,7 +232,8 @@ class TestRehabDisplay:
216
232
  "nodes": [
217
233
  {
218
234
  "node_id": "node-12345678",
219
- "routing_score": 0.0,
235
+ "routing_score": 0.1,
236
+ "scoring_state": "probation",
220
237
  "latency_score": 1.0,
221
238
  "reliability": 1.0,
222
239
  "price_factor": 1.0,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes