DGR-019 Lock alpha/beta performance contracts (evidence + contract framework) DGR-020 Run controlled whole-model GGUF baseline (benchmark results & contracts) DGR-024 Real generated-gRPC protocol harness (shard_runtime_server.py + tests) DGR-026 split-GGUF provisioning outside /home (provision script + manifest + tests) DGR-028 Numbered patch-stack apply & verify (llama_cpp_dependency.py + UPSTREAM_LOCK.json) DGR-029 Native CMake skeleton + deterministic CPU lane (UPSTREAM_LOCK.json + cmake gating) New modules: packages/node/meshnet_node/dgr_performance/ — performance contract framework packages/node/meshnet_node/split_gguf/ — split-GGUF manifest & provisioning scripts/provision_split_gguf.py — artifact provisioning CLI tests/test_dgr_performance_contract.py — contract validation tests tests/test_split_gguf_manifest.py — manifest tests tests/test_split_gguf_provision.py — provisioning tests tests/test_shard_runtime_harness.py — gRPC harness tests
14 KiB
DGR-026 evidence — provision exact split-GGUF artifacts outside /home
Status: implemented and verified this session; live re-review, not inherited credit.
Dependency: DGR-025 (evidence/DGR-025/README.md) — read before changing code.
Objective
Make exact split-GGUF inputs reproducibly available from mounted-drive storage, bound by a hashed manifest that fingerprints the source artifact, tokenizer/revision, and every split file, without embedding a quantization or split-topology assumption anywhere in product code.
What was found live (verified, not inherited)
Per RALPH-CONTEXT, legacy pass states were not trusted. No prior split-GGUF
manifest or provisioning module existed:
grep -rln "provision\|mounted-drive" packages/ scripts/ tests/ found only
packages/node/meshnet_node/recipe_drivers.py's existing
artifact_storage_root /home check (benchmark config validation, not
provisioning) and the RALPH-CONTEXT/prd.json prose itself. The pre-existing
packages/node/meshnet_node/downloader.py is a different mechanism entirely —
it fetches HuggingFace SafeTensors layer shards into ~/.cache/meshnet/shards
(i.e. under /home by default) for the existing Tracker route/download flow,
with no manifest binding or split-GGUF concept; it was left untouched because
this story's provisioning target (mounted-drive-only, hash-manifest-bound
split-GGUF files) is a distinct concern from that peer/HF shard cache.
Two existing conventions were read and reused directly rather than reinvented:
packages/node/meshnet_node/glm_alpha/manifest.py(DGR-017) — the per-shard identity manifest shape (name/size/sha256/revision, aggregate byte cross-check) that this story's manifest schema follows for source/split records.packages/node/meshnet_node/runtime_recipe.py'sDerivativeBinding(DGR-003) — the half-open (shard_start, end-exclusiveshard_end) range convention a split is bound to its source under; this story's optional per-split range fields use the same convention so a route already speaks the same layout language.packages/node/meshnet_node/recipe_drivers.py's_validate_config— the exact/homerejection shape (not root.is_absolute() or root == Path("/home") or Path("/home") in root.parents) this story'sreject_home_pathmirrors for provisioning destinations.
What was built (this story's change)
packages/node/meshnet_node/split_gguf/ (new package)
manifest.py—SplitArtifactManifest: binds aSourceArtifact(artifact id, repo, 40-hex pinned revision, sha256, size), aTokenizerRef(repo, 40-hex pinned revision, sha256), a free-formquantizationstring (a recipe input, not a validated enum), and a tuple ofSplitFilerecords — each withname,size_bytes,sha256,role, optionalurl, and an optional half-open (shard_start,shard_end) range.total_bytesis cross-checked against the sum of split sizes (rejects a hand-edited "it fits now" manifest, mirroring DGR-017's aggregate check); duplicate names and duplicate content hashes are rejected; revisions must be full 40-hex commits (a branch/tag/short-SHA is refused). Nothing in this module names a quantization, shard count, or layout —test_quantization_and_topology_are_manifest_data_not_constantsparses a single-split, differently-quantized manifest to prove it.provision.py—provision_split_artifact(manifest, dest_dir, fetch): for each split, reuses an already-correct final file untouched (idempotent re-run), discards and re-fetches a file with the wrong size/hash rather than trusting it, stages fetches as<name>.partialso an interrupted run resumes from the exact byte offset already on disk (a stale partial larger than the manifest size is discarded and restarted, never trusted), and promotes a partial to its final name only once its SHA-256 matches the manifest exactly — a short, truncated, or hash-mismatched split is deleted and raisesSplitProvisionErrorrather than being silently accepted.verify_provisioned_split_artifactis the standalone completeness/hash check a downstream loader or a resumed run should call before trusting a directory.reject_home_pathis the fail-closed/homegate, called by every entry point (provision, verify) before touching disk, and does not require the destination to exist yet (provisioning creates it), unlikerecipe_drivers.py'sstrict=Truebenchmark-root check. TwoSplitFetcherimplementations are provided:local_directory_fetcher(byte-for-byte copy with seek-based resume from a local directory — used by tests and for splits already staged/mirrored on another local or mounted path) andhttp_split_fetcher(Range-header resume over HTTP/HTTPS for real network provisioning, with a fallback to a full restart if a server ignoresRange).
scripts/provision_split_gguf.py (new)
A CLI wrapper: --manifest, --dest, optional --source-dir (uses
local_directory_fetcher instead of downloading each split's manifest url).
Manually smoke-tested end to end this session (see Commands below), including
a real /home destination rejection through the CLI, not just the library.
Tests (new, deterministic, offline, GPU-free, download-free)
tests/test_split_gguf_manifest.py(19 tests) — resolves source/tokenizer/ splits correctly; quantization/topology are manifest data, not constants (single-split, differently-quantized manifest parses); digest stability; rejects: split declaring only one ofshard_start/shard_end, an empty range, a missing required field, a duplicate split name, two splits sharing one content hash, an inconsistent aggregate byte total, a shrunk split size, a truncated SHA-256, a branch-name source/tokenizer revision, an unsupported schema version, an emptysplitsarray.tests/test_split_gguf_provision.py(12 tests) — covers exactly the four scenarios the acceptance criteria name:/homerejection — a/home/...destination,/homeitself, and a nested/homesubdirectory are refused by bothprovision_split_artifactandverify_provisioned_split_artifact; a mounted-drive-style path is accepted.- Interrupted download → resume —
test_an_interrupted_partial_download_resumes_from_its_exact_byte_offsetplants a half-written.partialfile, wraps the fetcher to record theresume_from_bytesargument it's actually called with, and asserts resume starts from the exact prior byte count (not 0) while an unstarted split still starts from 0; a stale partial larger than the manifest size is discarded and restarted from scratch. - Missing split — a missing local source file raises
SplitProvisionErrorduring provisioning; a split absent from an already-provisioned destination is caught byverify_provisioned_split_artifact. - Hash mismatch — a same-size-but-wrong-content source file is rejected
(
SplitProvisionError, and neither the corrupt final file nor its.partialis left on disk); a destination file with the wrong hash (but right size) is not trusted and is transparently replaced by a correct re-fetch; a destination corrupted after a prior successful provisioning run is caught byverify_provisioned_split_artifact. - Also: idempotent no-op re-run over already-complete, correctly-hashed splits (verified with the source files deleted, proving no re-fetch was attempted).
Acceptance criteria → evidence
- Exact manifest binding source artifact, tokenizer/revision, every split's
name/size/range-or-role/hash —
SplitArtifactManifest/SourceArtifact/TokenizerRef/SplitFileinmanifest.py; covered bytest_split_gguf_manifest.py. - Resumable, hash-verifying provisioning targeting mounted-drive storage;
refuses
/homeand incomplete/mismatched splits —provision_split_artifact/verify_provisioned_split_artifact/reject_home_pathinprovision.py; covered bytest_split_gguf_provision.pyand the CLI smoke test below. - Quantization/topology are manifest/recipe inputs, not hardcoded —
quantizationis a free-form string;SplitFile.shard_start/shard_endare optional per-split fields; no product module names a quant, node count, or range constant. Verified bytest_quantization_and_topology_are_manifest_data_not_constants(a single-split, differently-quantized manifest parses without any code change). - Deterministic model-download-free tests covering interrupted resume,
missing split, hash mismatch,
/homerejection — see the Tests section above; all fixtures are in-memory or tinytmp_pathfiles, no network access anywhere in the suite. - Gates + this handoff — below.
Commands and results
python3 -m pytest -q tests/test_split_gguf_manifest.py tests/test_split_gguf_provision.py
31 passed in 0.10s
python3 -m pytest -q tests/test_ralph_prd_schema.py
108 passed
python3 -m compileall -q packages/node/meshnet_node/split_gguf tests scripts/provision_split_gguf.py
git diff --check
python3 scripts/ralph_prd_schema.py validate .scratch/distributed-gguf-runtime/prd.json
(compileall exit 0; git diff --check exit 0)
OK: 55 stories validated.
CLI smoke test (manual, not part of the automated suite — exercises the real network-capable code path against tiny local files instead of a real model):
python3 scripts/provision_split_gguf.py \
--manifest /tmp/dgr026-smoke/manifest.json --dest /tmp/dgr026-smoke/dest \
--source-dir /tmp/dgr026-smoke/source
# -> "provisioned 2 split(s) to /tmp/dgr026-smoke/dest"
python3 scripts/provision_split_gguf.py \
--manifest /tmp/dgr026-smoke/manifest.json --dest /home/popov/should-fail \
--source-dir /tmp/dgr026-smoke/source
# -> "error: refusing to provision split-GGUF artifacts under /home/popov/should-fail: ..."
# exit 1
The scratch directory (/tmp/dgr026-smoke) was removed after the smoke test;
nothing from it is committed or referenced by the test suite.
Default tests are model-download-free, API-credit-free, and GPU-free; no model
artifact was downloaded and nothing product-relevant was written under
/home (the CLI smoke test's /home path was rejected before any write).
Changed files
packages/node/meshnet_node/split_gguf/__init__.py(new)packages/node/meshnet_node/split_gguf/manifest.py(new)packages/node/meshnet_node/split_gguf/provision.py(new)scripts/provision_split_gguf.py(new)tests/test_split_gguf_manifest.py(new)tests/test_split_gguf_provision.py(new).scratch/distributed-gguf-runtime/prd.json(DGR-026.passes = true+completionNotes; also restored the top-levelsourceOfTruth/qualityGates/metadataSchema/milestones/supersededStories/branchNamefields — see Gotcha below).scratch/distributed-gguf-runtime/issues/026-provision-exact-split-gguf-artifacts-outside-home.md(regenerated viascripts/ralph_prd_schema.py render).scratch/distributed-gguf-runtime/evidence/DGR-026/README.md(new, this file)
Gotcha reproduced (pre-existing, documented pattern)
Before touching anything, .scratch/distributed-gguf-runtime/prd.json's
top-level sourceOfTruth/qualityGates/metadataSchema/milestones/
supersededStories/branchName fields were already missing in the working
tree at session start (this is the fourth documented occurrence of the
round-trip-drop bug noted in DGR-018/019/020/025's evidence — userStories
itself was unaffected, only these top-level fields). Restored them from
git show HEAD:.scratch/distributed-gguf-runtime/prd.json before making any
DGR-026 edit; scripts/ralph_prd_schema.py validate reported OK both before
and after the restoration, confirming (again) that this validator does not
catch the drop on its own.
Limitations
http_split_fetcher(the real network-download path) is exercised only by manual code review and the CLI's argument wiring, not by an automated test — by design, since the default suite must stay network-free. Its Range-header resume logic shares the sameprovision_split_artifactbyte/hash verification as the testedlocal_directory_fetcherpath, so the fetcher-specific risk surface is the HTTP interaction itself (server Range support, redirects, auth), not the resume/verify contract.- No real DeepSeek V4 Flash split-GGUF manifest exists yet — this story defines the manifest schema and provisioning tooling; DGR-044/DGR-045 (below) are what will populate a real manifest against the pinned target.
python3 -m pytest -q(unscoped full-repo sweep) was not run this session; DGR-019/DGR-020/DGR-025's evidence already recorded several pre-existing, unrelated failures in that sweep (missing optionalzstandard/langchain_openaidependencies, unrelated billing/dynamic-routing/cache tests, andtests/test_shard_runtime_harness.py'sgrpcimport requirement). This story's own targeted suites,test_ralph_prd_schema.py,compileall, andgit diff --checkare all green as recorded above.- Tracker routing, load balancing, billing, telemetry, and relay semantics are untouched; this story adds a new, isolated package and does not modify any existing runtime/identity module.
Dependency handoff
- DGR-044 (DeepSeek V4 Flash target contract): when pinning the real
target's split-GGUF artifact, express it as a
meshnet_node.split_gguf.manifest.SplitArtifactManifest—source.sha256is the whole-model artifact digest DGR-003'sArtifactIdentity.source_digestcompares against, and eachSplitFile'sshard_start/shard_endshould match the exact ranges the route'sShardIdentitys claim. - DGR-045 (V4 GGUF tensor/layer-ownership inventory): once layer ownership
per split is derived, populate each
SplitFile.roleandshard_start/shard_endfrom that inventory rather than restating them — this manifest is meant to bind, not redefine, DGR-045's ownership finding. - Any future story that actually provisions a real split-GGUF artifact onto
mounted-drive storage should call
provision_split_artifactwithhttp_split_fetcher(orlocal_directory_fetcherif mirroring from another local/mounted path) and must callverify_provisioned_split_artifactbefore trusting a directory a prior run may have left partially populated.