Files
neuron-tai/.scratch/distributed-gguf-runtime/evidence/DGR-017

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-...mdStatus: 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 documents 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.