# ADR-0011: Auto-shard from memory budget and tracker-managed network assignment ## Status: Accepted ## Context Early node startup required explicit `--shard-start` and `--shard-end` flags. This is fine for expert operators but a barrier to new participants who don't know how many layers their GPU can hold. Two improvements were needed: 1. **Auto-detect shard range**: fetch `num_hidden_layers` from the model's `config.json` and compute how many layers fit in available VRAM. 2. **Network-aware assignment**: instead of each node picking its own shard, the tracker knows the current coverage map and can tell the node which gap to fill. ## Decisions ### 1. Layer count from HuggingFace config `AutoConfig.from_pretrained(model_id)` downloads only `config.json` (~1 KB, no weights). `cfg.num_hidden_layers` gives the total layer count. The node uses this to set `shard_end = num_layers - 1` when no explicit range is given. A curated `MODEL_CATALOG` in `model_catalog.py` provides layer counts for common models without any network call — HuggingFace is only hit for uncatalogued repos. ### 2. VRAM-aware shard sizing `hardware.detect_hardware()` returns `vram_mb`. The node sends this to `/v1/network/assign?device=cuda&vram_mb=&hf_repo=`. The tracker responds with a `{shard_start, shard_end}` gap that fits within the reported VRAM budget using the `bytes_per_layer` table from the model preset. When the tracker has no registered nodes for the model yet, `gap_found: false` is returned and the node defaults to the full model. ### 3. --memory override `--memory MB` allows overriding the detected VRAM. Useful for CPU nodes (which report 0 VRAM) that want to serve a specific slice using system RAM. ### 4. Tracker network assignment endpoint `GET /v1/network/assign` replaces the old `GET /v1/nodes/assign`. It accepts `device`, `vram_mb`, and optionally `hf_repo`. It returns: ```json { "hf_repo": "Qwen/Qwen2.5-0.5B-Instruct", "shard_start": 12, "shard_end": 23, "num_layers": 24, "gap_found": true, "price_per_token": 0.0 } ``` `price_per_token` is reserved at 0.0 for future billing integration. ## Alternatives rejected **Fixed shard table per model**: would require updating the code for every new model. HuggingFace config fetch is more general. **Node computes its own gap**: requires the node to know the full coverage map. The tracker already has this; having the tracker compute the assignment is cleaner. ## Consequences - Nodes can join the network with a single command: `meshnet-node start --tracker ` - The tracker is now the authoritative source for shard assignment - VRAM budgets are advisory — nodes can still pin a range with explicit flags - `price_per_token: 0.0` is a stable protocol field; future billing sets it to a real value