"""Box-type registry — the canonical uint -> box-class map for box-type routing
(operator 2026-06-15).

A WORKER advertises its type via the WORKER_BOX_TYPE env (pool_worker.py) at
/register and every heartbeat, AND — since 2026-06-22 — its total RAM
(mem_total_bytes, auto-read from /proc/meminfo). A TASK constrains where it may run
via the route_box_types column (task_spooler tasks: comma-separated uints; NULL = any
worker). The pool-service filters get_worker candidates to matching box_types.
The advancer size-routes big forward_pass docs to FWD_FAST_BOX_TYPES.

box_type is a resource-CLASS, NOT the box ordinal (operator 2026-06-22). The box
ORDINAL (thinkbox1, thinkbox2) is just the Hetzner provisioning order; box_type is the
capability tier, and they do NOT line up: thinkbox1 (the FIRST box) is the w2295/251G
machine = resource-class **2**. So "tbN" tells you nothing about box_type — read the
class. (Deployed stage-worker labels historically tracked the ORDINAL, tb1->1 / tb2->2,
INVERTED vs this registry; latent because stage tasks aren't box-routed — fixed in the
launch scripts.) Types are CLASSES (a future second high-end box is also type 2). UNSET
WORKER_BOX_TYPE => "untyped": the worker sends no box_type and is skipped only by
type-constrained tasks.

ROUTING IS NOW RAM-FIRST. box_type routing is a soft PERF preference; the HARD
OOM-safety lever is the memory-counting gate (spooler -> get_worker min_mem_bytes): a
forward_pass task lands only on a worker whose advertised RAM holds its working set
(reserve + bytes_per_token*token_count). Label-independent — it gates on the real
mem_total each box reports, so the box_type confusion can never cause an OOM (a
3M-token doc OOM-killed the 63G box precisely because box_type FP-routing was inert:
qwen/FP workers advertise no box_type). See wiki docs/forward-pass-oom-and-ram-routing.

KEEP IN SYNC with the per-box launch env (thinkbox/qwen-pool-*.sh + stage-pool-*.sh ->
WORKER_BOX_TYPE, step9 compose) and wiki facts/box-type-registry. This module is the
code-side SOT; nothing is forced to import it (the wire value is a plain int), but
logging/tools may.
"""

BOX_TYPES = {
    0: "generic",   # mainbox-class:  Ryzen 5 3600, AVX2,            64G  — default/fallback
    1: "midrange",  # i9v13-class (thinkbox2):  i9-13900,    AVX2+AVX-VNNI,  63G
    2: "high",      # w2295-class (thinkbox1):  Xeon W-2295, AVX-512,       251G  — fast, big-doc target
}


def name(box_type) -> str:
    """Human label for a box-type uint (for logs/tools). Unknown -> 'typeN'; unset -> 'untyped'."""
    if box_type is None or box_type == "":
        return "untyped"
    try:
        bt = int(box_type)
    except (TypeError, ValueError):
        return "untyped"
    return BOX_TYPES.get(bt, f"type{bt}")
