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@b4734de4facf877f85769a911abafc5283eab3d9andunsloth/GLM-5.2-GGUF@abc55e72527792c6e77069c99b4cb7de16fa9f23, quantizationUD-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-017passes: 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:
- the initial wheel omitted
glm_alpha/data/*.json, despite source-tree tests passing; - the self-sealed contract did not bind the manifest/snapshot digests, so coordinated shard-hash or architecture substitutions could be accepted;
--checkfollowed moving repository HEAD instead of validating immutable pins;- 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
Be precise about what the seal does. contract_sha256 is tamper-evidence, not
tamper-proofing. Nothing checked into a repo can stop an agent that rewrites the
threshold and re-seals the digest — test_resealing_a_mutated_contract_changes_its_digest
asserts that path openly. What the seal removes is the silent mutation: the digest
moves, and the change becomes a visible diff on a file whose entire purpose is to not
change, still claiming contract_id: glm-5.2-max-alpha/v1. Reviewers, not hashes, are
the enforcement; the hash makes sure there is something to review.
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_INDEXERexists. - #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.10is 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.jsonbefore DGR-004 picks a llama.cpp pin. The manifest script's--checkdeliberately 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_alphahas 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:
--writefollows current HEAD and leaves the existing contract binding invalid until a new contract is reviewed and sealed.--checkuses 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.