# DGR-017 — Lock the GLM-5.2 Max target and alpha contract Status: **done**. Every acceptance criterion is met with real command output. Evidence class: **real upstream metadata + deterministic arithmetic**. No weight payload was downloaded, no model was loaded, no GPU was used, and no benchmark was run — and none is claimed. This story makes the target *reviewable before* the 216.7 GB download, which is exactly its job. ## 1. Summary The alpha target is now pinned, planned, and sealed: - **Identity.** `zai-org/GLM-5.2` @ `b4734de4facf877f85769a911abafc5283eab3d9` and `unsloth/GLM-5.2-GGUF` @ `abc55e72527792c6e77069c99b4cb7de16fa9f23`, quantization `UD-IQ1_S`, six shards, 216,715,360,960 bytes, every shard's LFS SHA-256 resolved. - **Architecture.** The config/tokenizer/chat-template metadata the runtime cannot shard without, hashed at the pinned revision. - **Resources.** A deterministic planner that counts unified memory once, applies the `max(20% , 8 GiB)` reserve, and reports the arithmetic minimum and the recommended node count as two different numbers. - **Contract.** The roadmap's section-5 acceptance matrix as a machine-readable, digest-sealed document, locked before the target ever runs and cross-bound to the exact manifest and architecture-snapshot digests. - **Upstream.** A refreshed llama.cpp/donor status report. Three findings are worth a reader's attention. **Every number in the roadmap reproduced from primary sources.** The 216,715,360,960 byte total, the 201.832 GiB figure, the whole KV table (0.73 / 0.77 / 0.89 / 1.68 GiB at 16K, through 46.62 / 49.41 / 56.98 / 107.25 GiB at 1M), and the whole tier table (9 / 6 / 4 / 3 / 2 arithmetic minimum nodes) fall out of the exact config and the exact shard bytes. The roadmap was not approximating. The planner is written as a *reproduction* of those tables, so if the arithmetic ever stops matching, a test says which numbers moved. **The roadmap's "recommended" column is an imbalance factor of exactly 1.10.** Nodes = `ceil(total x 1.10 / budget)` yields 10 / 6 / 5 / 3 / 3 for the 32 / 48 / 64 / 96 / 128 GiB tiers — precisely the roadmap's recommendations. That constant is now named (`PLACEMENT_IMBALANCE_FACTOR`) and documented as a placeholder for measured per-tensor placement, not a fudge factor to be tuned once results are in. **224 GiB aggregate does not actually fit.** Two 112 GiB nodes hit the 224 GiB "hard-fit floor" exactly, and still come up **23.5 GiB short** once each node honours its reserve. That is what makes 224 GiB an *experimental floor* rather than an envelope, and it is now a test, not a caveat in prose. Relatedly, the 2×128 and 4×64 "fit probe" topologies fit with only **2.08 GiB of headroom across the entire route** — which is why they require measured placement evidence and are not the recommendation. ## 2. Files changed New — runtime-loadable package (single source of truth): | Path | What | |---|---| | `packages/node/meshnet_node/glm_alpha/__init__.py` | Public surface | | `packages/node/meshnet_node/glm_alpha/manifest.py` | Target manifest + architecture snapshot; fail-closed identity | | `packages/node/meshnet_node/glm_alpha/planner.py` | Memory / KV / seam planner; unified-memory de-duplication | | `packages/node/meshnet_node/glm_alpha/contract.py` | Immutable, digest-sealed alpha acceptance contract | | `packages/node/meshnet_node/glm_alpha/data/target-manifest.json` | The six pinned shards, sizes, SHA-256, URLs, licenses | | `packages/node/meshnet_node/glm_alpha/data/architecture-snapshot.json` | Pinned architecture + config/template hashes | | `packages/node/meshnet_node/glm_alpha/data/alpha-contract.json` | Sealed acceptance thresholds (`aab23220…`) | | `scripts/refresh_glm_target_manifest.py` | Re-resolve/verify pins from upstream metadata (`--check` / `--write`) | | `tests/test_glm_alpha_target.py` | 97 deterministic offline tests | New — evidence: - `.scratch/distributed-gguf-runtime/evidence/DGR-017/README.md` (this file) - `.../commands.txt` — exact commands and real results - `.../resource-plan.json` — generated tier/route/seam/KV plan - `.../upstream-status.json` — refreshed llama.cpp and donor status Modified: - `.scratch/distributed-gguf-runtime/issues/17-...md` — `Status: done` - `.scratch/distributed-gguf-runtime/prd.json` — DGR-017 `passes: true` (this story only) - `.ralph-tui/progress.md` — learnings The data files live **in the package**, not in evidence, because the runtime must load them (DGR-018 verifies downloads against these digests; DGR-003 folds the manifest digest into the recipe fingerprint). Duplicating them into evidence would create two sources of truth that could drift. ## 3. Acceptance criteria | Criterion | Where it is proven | |---|---| | Pin both repos by exact observed revision; `UD-IQ1_S` is the alpha quant | `target-manifest.json`; `test_manifest_pins_both_repositories_by_exact_revision` | | Six filenames, exact bytes, LFS SHA-256, aggregate GB/GiB, license, URLs, no payload download | HF `paths-info` API (LFS pointer metadata); `test_manifest_resolves_all_six_shards…`, `test_manifest_aggregate_bytes_are_exact_and_self_consistent` | | Snapshot + hash architecture-critical config/tokenizer/chat-template metadata | `architecture-snapshot.json`; `test_snapshot_captures_the_architecture_critical_metadata`, `test_snapshot_hashes_the_config_and_chat_template_bytes` | | Deterministic minimum-node calc from exact bytes, Q8_0 KV @16K/c1, imbalance, reserve | `planner.plan_topology`; `test_topology_planner_reproduces_the_published_tier_table` | | 224 GiB is a hard-fit floor, not an envelope; recommend 5×64 or 3×96/128 | `test_224_gib_aggregate_is_a_hard_fit_floor_not_an_operational_envelope`, `test_the_recommended_topologies_are_five_by_64_or_three_by_96_or_128` | | Unified memory counted once; additive RAM+VRAM rejected | `NodeMemory.from_host`; `test_adding_integrated_gpu_memory_to_system_ram_is_rejected`, `test_unified_memory_is_counted_once` | | 2.5 GbE minimum / 10 GbE recommended; serial latency modelled apart from bandwidth | `planner.plan_seams`; `test_2_5_gbe_is_the_alpha_minimum_and_10_gbe_is_recommended`, `test_serial_seam_latency_is_modelled_separately_from_bandwidth` | | Identity/semantic/target-run/performance/reliability/storage criteria locked before execution | `alpha-contract.json` (sealed, `locked_before_target_execution: true`); `test_the_contract_locks_every_roadmap_acceptance_section` | | Refresh upstream llama.cpp + donor status; no broad fork/scheduler | `upstream-status.json`; `adoption_state: none adopted` | | Tests reject changed revisions, missing shards, coordinated digest/config substitutions, inconsistent bytes, duplicate unified memory, malformed telemetry, and post-result threshold mutation | 97 tests; see §5 | | Targeted pytest passes | `97 passed` | | Installed wheel includes and loads all locked JSON resources | Real wheel build/install plus `load_locked_target()` outside the source tree | | `compileall packages tests` | exit 0 | | `git diff --check` | exit 0 | | Default tests deterministic, download-free, credit-free, GPU-free | Pure JSON + arithmetic; the only network code is an opt-in script excluded from the suite | | Full deterministic `pytest -q` | **852 passed, 13 skipped** on final rerun | ## 4. Real results ``` scripts/refresh_glm_target_manifest.py --check -> match upstream (exit 0) pytest -q tests/test_glm_alpha_target.py -> 97 passed build + install wheel; load_locked_target() -> INSTALLED_WHEEL_PASS compileall -q packages tests -> exit 0 git diff --check -> exit 0 pytest -q -> 852 passed, 13 skipped (253.30s) ``` Controller review found and fixed four gaps before the commit was accepted: 1. the initial wheel omitted `glm_alpha/data/*.json`, despite source-tree tests passing; 2. the self-sealed contract did not bind the manifest/snapshot digests, so coordinated shard-hash or architecture substitutions could be accepted; 3. `--check` followed moving repository HEAD instead of validating immutable pins; 4. non-finite resource telemetry could bypass ordinary range checks. Each failure now has either an adversarial regression test or a real installed-wheel / live-metadata gate. None of the provisional agent results were accepted on trust. The intermittent tracker cancellation race that DGR-001 and DGR-002 both recorded as flaky on a clean tree failed once in the final validation (`404` after the request completed), then passed **5/5** in isolation and passed in the integrated full-suite rerun above. This story touches no tracker code; the failed run is retained in `commands.txt` rather than hidden. Planner output (`resource-plan.json`): | Route | Fits | Headroom | |---|---|---:| | 5×64 GiB unified (recommended) | yes | +53.28 GiB | | 3×96 GiB unified (recommended) | yes | +27.68 GiB | | 3×128 GiB unified (recommended) | yes | +104.48 GiB | | 4×64 GiB (fit probe) | yes | **+2.08 GiB** | | 2×128 GiB (fit probe) | yes | **+2.08 GiB** | | 2×112 GiB (= 224 GiB floor) | **no** | −23.52 GiB | | 3×64 GiB | no | −49.12 GiB | ## 5. How the "no silent swap" claim is earned The story's whole purpose is to stop a later agent from changing the target after seeing a result. Each of those moves now has a test that names it: - swap the artifact → `test_a_changed_gguf_revision_is_rejected` - pin a branch instead of a commit → `test_a_branch_name_is_not_an_acceptable_revision_pin` - drop a shard → `test_a_missing_shard_is_rejected` - shrink a shard so it "fits" → `test_a_shard_size_edited_to_make_the_model_look_smaller_is_rejected` - change a valid-looking shard SHA without changing bytes → `test_coordinated_shard_hash_substitution_is_rejected_by_contract` - change internally consistent architecture metadata → `test_internally_consistent_architecture_substitution_is_rejected_by_contract` - take the bigger quant quietly → `test_swapping_in_a_different_quantization_is_rejected` - add iGPU "VRAM" to system RAM → `test_adding_integrated_gpu_memory_to_system_ram_is_rejected` - count one machine twice → `test_the_same_machine_counted_twice_in_a_route_is_rejected` - lower the speed floor → `test_lowering_the_speed_floor_after_seeing_a_result_is_rejected` - call a slow pass an alpha → `test_relabelling_a_speed_failure_as_a_pass_is_rejected` - admit the dense fallback → `test_admitting_the_dense_attention_fallback_after_the_fact_is_rejected` - shrink the reserve → `test_relaxing_the_per_node_reserve_after_the_fact_is_rejected` **Contract continuity is fail-closed.** The document’s `contract_sha256` detects accidental edits, and the approved v1 digest is pinned independently in code. A caller that changes a threshold and re-seals it under `glm-5.2-max-alpha/v1` is rejected by `test_resealing_a_mutated_v1_contract_is_rejected`; amendments require a new supported contract identity under human review. Parsed nested state is recursively immutable, so thresholds cannot change between validation and use; `to_dict()` returns an isolated copy rather than exposing the validated object. ## 6. Upstream status — the gating risk for DGR-004/DGR-018 Refreshed against live GitHub on 2026-07-13. One item **changed** since the roadmap: - **#24231 is now MERGED** (2026-07-11) — a generic `GGML_OP_LIGHTNING_INDEXER` exists. - #24770 MERGED (2026-06-20) — GLM-5.2 loads via a **dense-MLA compatibility path**. - **#25407 still OPEN** (updated today) — the real GLM DSA/IndexShare wiring. - #24730 still OPEN — the umbrella GLM-5.2 support request. **No released upstream llama.cpp performs native GLM-5.2 DSA + IndexShare today.** A stock pin taken now would load the artifact and emit text through the dense fallback — which the alpha contract explicitly refuses (`dense_attention_fallback_satisfies_alpha: false`). DGR-018 must therefore prove those paths are *active*, not that output appeared. Donor policy holds, and the evidence now supports it more strongly than before: PR #25407 is **12 files, +414/−7**. The semantics alpha needs are small enough to track and reproduce upstream. That is the argument against adopting Mesh-LLM's 261-patch fork — recorded as a donor (Apache-2.0, branch head `9bd18f15`, 2026-07-12), nothing adopted here. ## 7. Limitations and deferred work - **No artifact was downloaded or loaded.** Sizes and SHA-256 come from Hugging Face LFS pointer metadata. DGR-018 must verify the digests against the real files on mounted storage before route admission. A matching size with a wrong hash is exactly the failure this manifest exists to catch, and only a local verify can catch it. - **`PLACEMENT_IMBALANCE_FACTOR = 1.10` is a planning assumption, not a measurement.** It reproduces the roadmap's recommendations, but the real per-node share depends on exact tensor bytes (embeddings, output head, dense vs MoE layers, shared experts, indexer tensors, quant block alignment). DGR-019 must replace it with measured placement. Until then, arithmetic-minimum topologies (2×128, 4×64) stay fit probes. - **KV numbers are planning estimates, not admission truth.** The planner deliberately budgets the *conservative* indexer layout (keys across all 78 layers, not just the 21 Full ones) so a route admitted here cannot be surprised by the implementation it actually gets. The runtime must still report measured allocated/resident MLA and indexer cache per shard. - **Peak scratch is unmodelled.** The reserve exists precisely because backend workspaces and graph scratch are not predictable from the artifact; measured peak must land inside the reserve, and the contract requires that evidence. - **Upstream is moving fast.** #25407 was updated the same day it was observed. Refresh `upstream-status.json` before DGR-004 picks a llama.cpp pin. The manifest script's `--check` deliberately validates the immutable Hugging Face pins, not moving HEAD. ## 8. Compatibility and migration notes - Purely additive. No existing module, wire format, or test changed. Nothing in this story is on a live request path. - `meshnet_node.glm_alpha` has **no heavy imports** — no torch, no transformers, no network at import time — so a tracker or planner can read the target contract without paying for a model runtime. - Re-pinning is deliberately awkward: `--write` follows current HEAD and leaves the existing contract binding invalid until a new contract is reviewed and sealed. `--check` uses revision-specific APIs and exits non-zero rather than healing any integrity drift in the already locked target. ## 9. Handoff to dependent stories **DGR-003 (recipe identity):** fold `TargetManifest.digest` (`0b6aed04479d204902bb64c0203f1a46cab26a47b378ecccf85237b63f6c1962`) and `ArchitectureSnapshot.digest` (`253fbd94…`) into the runtime recipe fingerprint. The GLM fields the roadmap asks you to add (DSA/IndexShare metadata, context max, expert counts) are already resolved in `architecture-snapshot.json` — read them, do not re-derive them by hand. Populate the DGR-002 `Fingerprint` message; do not invent a second identity struct. **DGR-004 (llama.cpp pin):** read `upstream-status.json` first. Any pin taken before #25407 merges gives you the dense-MLA fallback, which cannot satisfy alpha. Track #25407 (12 files) as a numbered patch; do not adopt the Mesh-LLM fork. **DGR-018 (whole-model oracle):** the six digests in `target-manifest.json` are what you verify the download against. Your host needs ≥224 GiB runtime-accessible memory — and note that 224 GiB is the *floor*, not a comfortable target (see §1). Prove DSA, IndexShare, shared expert, and the Max template are **active**; the contract's `require_rendered_reasoning_effort_marker` is `<|system|>Reasoning Effort: Max`. Assert the rendered marker, not the request field: the template's only non-max level is `'high'`, so *every other value — including an absent one — renders Max*, and "the request said max" proves nothing. **DGR-019 (GLM semantics):** the IndexShare split is **21 Full producer layers and 57 Shared consumers**, in a `[full, full, full] + repeating [shared, shared, shared, full]` pattern. Prefer shard boundaries that keep an ownership group whole; the 8 KiB (2048 × int32) top-k sideband is the cost when you cannot. Replace `PLACEMENT_IMBALANCE_FACTOR` with measured per-tensor placement. **DGR-020 (alpha verdict):** load the target with `load_locked_target()`. It verifies the contract seal and cross-binds the manifest and architecture snapshot before returning them. Judge against `contract.threshold(section, key)` — an unlocked threshold raises rather than defaulting, so a criterion cannot be invented at read time. The verdict is `alpha` or `stop`; there is no third outcome, and a quality pass with a speed failure is `stop`. **Everyone:** unified system RAM and integrated-GPU memory are one pool. Build nodes with `NodeMemory.from_host(..., unified=True)` and it is impossible to write the double-count; pass a GPU size alongside `unified=True` and it raises rather than silently ignoring the argument.