13 KiB
DGR-031 evidence — the project-owned ShardEngine interface
Completed: 2026-07-23
Branch: ralph/distributed-gguf-runtime
Authority: .scratch/distributed-gguf-runtime/prd.json
Dependencies: DGR-021 (evidence/DGR-021/README.md — versioned activation
envelope, NamedTensor/ActivationEnvelope as the project-owned wire-envelope
layer), DGR-025 (evidence/DGR-025/README.md — exact artifact/runtime recipe
identity; both read before changing code).
Objective
Isolate worker/protocol code from llama.cpp internals behind a stable project-owned engine contract, so a fake fixture engine (DGR-032) and a real llama.cpp-backed engine (DGR-037) are interchangeable subclasses of one interface.
What was found live before changing code
Per RALPH-CONTEXT, legacy pass states were not trusted; the live surrounding contracts were read and exercised before designing this one:
packages/node/meshnet_node/shard_lifecycle.py(DGR-022) already defines a versioned RPC/session lifecycle contract —StructuredStatus,StatusCode,CacheExpectation,CacheResult,LifecycleState,SessionLifecycle— but it is explicitly the wire RPC contract "consumed by a future generated gRPC binding," not an execution-engine boundary.packages/node/meshnet_node/native_backend.py(DGR-025) is the identity boundary for the native GGUF artifact — it derives and attests aShardIdentity, but does not define an execution contract either.packages/node/meshnet_node/protocol.py(DGR-021) defines a project-ownedNamedTensor/ActivationEnvelopefor activation traffic between shard hops over the network, distinct from the generated-protobuf wire ABI innative_protocol.packages/node/meshnet_node/shard_runtime_server.py(DGR-024) is today a real gRPC servicer that proves wire fidelity by checksumming and echoing bytes — it has no execution engine behind it yet; that seam is exactly whereShardEngineplugs in for DGR-037.packages/node/meshnet_node/architecture_boundary.pyestablished the precedent this story follows for tail output:TailOutput.sampled_token()never exposes raw logits, only a sampled token id.- No
ShardEngine(orshard_engine) symbol existed anywhere in the repository prior to this story (confirmed bygrep -rn -i "shardengine\|shard_engine"across.py/.md, which returned only planning-document prose naming it as future work).
Live verification of the pre-existing dependency contracts before adding new
code: PYTHONPATH=packages/node:packages/tracker .venv/bin/python3 -m pytest -q tests/test_shard_lifecycle.py tests/test_activation_envelope.py tests/test_architecture_boundary.py tests/test_native_shard_protocol.py tests/test_shard_runtime_harness.py → 95 passed, 3 skipped.
What was added (this story's change)
packages/node/meshnet_node/shard_engine.py (new)
The ShardEngine boundary: an abc.ABC with eight abstract operations —
load, capabilities, prefill, decode, cancel, release, health,
metrics — matching the acceptance criterion's list exactly (prefill/
decode share one operation family; their shared result type is what the
criterion calls the "boundary/logits result"). Every request/result type is a
frozen dataclass built from plain str/int/bytes/Mapping values:
EngineTensor/BoundaryBundle— the project-owned named-tensor activation crossing a shard boundary (head/middle/tail-in). Deliberately a new, minimal type distinct from bothnative_protocol.pb.TensorBundle(generated-protobuf ABI) andprotocol.NamedTensor/ActivationEnvelope(wire-framing/fragmentation concerns irrelevant to model execution) — a fourth, execution-facing layer underneath the three that already existed.TokenOutput— a tail shard's sampled result: a token id (+ optional decoded text), never a raw logits tensor.MtpHook— reserved multi-token-prediction hook; its own__post_init__raises if constructed withenabled=True, so the type exists (fixing its field shape for DGR-051/DGR-066) without any code path being able to turn it on before DGR-066, matching RALPH-CONTEXT's "MTP is reserved and off for alpha."ArchitectureAuxStateHook— reserved per-shard architecture auxiliary state (V4 CSA/HCA/SWA/indexer/compressor and similar); has no wire encoding and is never embedded in aBoundaryBundle, matching RALPH-CONTEXT's "remain local ... never carried over the WAN seam."LoadRequest/LoadResult,EngineCapabilities,PrefillRequest/DecodeRequest(exactly one oftoken_ids/token_id(head) orinput(middle/tail) required — enforced in__post_init__),StepResult(a successful result must carry an output;cache_resultreusesshard_lifecycle.CacheResult),HealthResult,MetricsResult.- Status vocabulary is reused, not reinvented:
StructuredStatus/StatusCode/CacheExpectation/CacheResultare imported fromshard_lifecycle(already project-owned and version-stable) rather than a parallel enum living alongside it. - The module imports nothing from
native_protocol,grpc, orctypes— verified structurally, not just by convention (see tests below).
tests/shard_engine_contract.py (new)
A reusable, non-test_-prefixed helper: assert_shard_engine_contract(make_engine)
takes a zero-arg engine factory and runs nine lifecycle checks — health before
load, load→capabilities range/MTP-off, prefill→decode determinism (byte-identical
output replayed on a fresh session), middle-shard boundary-bundle-in/out vs.
head/tail token-output, deterministic cache-miss on an unopened session,
stale-route-epoch rejection, cancel-then-decode rejection (+ cancel
idempotency), release-then-decode rejection (+ release idempotency), and
metrics reporting cancelled sessions. DGR-032's fixture and DGR-037's
llama.cpp binding are both expected to import this and pass it against their
own engine, proving identical lifecycle semantics without duplicating the
checks.
tests/test_shard_engine.py (new)
_ReferenceEngine: a minimal in-memoryShardEngineused only to prove the shared contract is non-vacuous. It is explicitly not the DGR-032 deterministic fixture (no delay/memory-pressure/malformed/crash injection — that is DGR-032's own, larger scope); the docstring says so to prevent this story's evidence from being read as inherited completion credit for DGR-032.- Dataclass validation tests: abstract-class instantiation refusal, tensor/
bundle/token-output field validation, MTP-hook enable refusal, exactly-one-
input-kind enforcement on
PrefillRequest/DecodeRequest,LoadRequestshard-range-vs-total-layers validation,StepResultoutput-required-on-OK. test_shard_engine_module_imports_no_native_or_grpc_or_wire_abi_types: walksvars(shard_engine_module)and asserts no bound name's__name__isctypes,grpc, ormeshnet_node.native_protocol— a structural check (not a docstring-text grep, which produced a false positive on first draft because the module's own docstring namesggml_tensoras an example of what must never appear) that the ABI-isolation acceptance criterion holds.
.scratch/distributed-gguf-runtime/prd.json / issue markdown
Marked DGR-031.passes = true with completionNotes; regenerated
issues/031-introduce-the-project-owned-shardengine-interface.md via
scripts/ralph_prd_schema.py render so it matches prd.json byte-for-byte.
Acceptance criteria → evidence
- load/capabilities/prefill/decode/boundary-logits-result/cancel/release/
health/metrics —
ShardEngine's eight abstract methods plusStepResult.output: BoundaryBundle | TokenOutput | None. Verified bytest_reference_engine_obeys_the_shared_shard_engine_contractand the middle-shard-vs-tail-shard assertion insideassert_shard_engine_contract. - No
ggml_tensor/llama context/scheduler/ABI-owned structure — every type inshard_engine.pyis a plain dataclass overstr/int/bytes/Mapping; no import ofnative_protocol,grpc, orctypes. Verified bytest_shard_engine_module_imports_no_native_or_grpc_or_wire_abi_types. - Reserved typed MTP/architecture-aux-state hooks, not enabled —
MtpHook.__post_init__raises onenabled=True;ArchitectureAuxStateHookcarries opaque shard-local state with no wire path. Verified bytest_mtp_hook_is_reserved_and_refuses_to_enableandtest_architecture_aux_state_hook_carries_opaque_shard_local_state, plusassert_shard_engine_contract'scaps.supports_mtp is Falsecheck. - Contract tests proving fake and future llama implementations obey
identical lifecycle semantics —
tests/shard_engine_contract.pyis written to be imported by DGR-032 and DGR-037 against their own engines;test_shard_engine.pyproves it is real by running it against_ReferenceEngine. - Gates + this handoff — below.
Commands and results
PYTHONPATH=packages/node:packages/tracker .venv/bin/python3 -m pytest -q tests/test_shard_engine.py
12 passed in 0.13s
PYTHONPATH=packages/node:packages/tracker .venv/bin/python3 -m pytest -q \
tests/test_shard_engine.py tests/test_shard_lifecycle.py \
tests/test_architecture_boundary.py tests/test_activation_envelope.py \
tests/test_native_shard_protocol.py tests/test_shard_runtime_harness.py
95 passed, 3 skipped in 3.65s
.venv/bin/python3 -m compileall packages/node/meshnet_node/shard_engine.py tests/shard_engine_contract.py tests/test_shard_engine.py
Compiling 'packages/node/meshnet_node/shard_engine.py'...
Compiling 'tests/shard_engine_contract.py'...
Compiling 'tests/test_shard_engine.py'...
git diff --check
(no output — clean)
Limitations
tests/as a whole does not collect cleanly in this environment: 27 pre-existing test modules fail to import for missing optional dependencies (cryptography, etc.) unrelated to this story. Reproduced identically withgit stashbefore this session's change (27 errors during collection), so this is pre-existing environment state, not a regression introduced here. This story's own gates were run as the targeted, scoped test set above per the shared quality gates' own wording ("Targeted deterministic tests pass").- The contract in
shard_engine_contract.pyproves lifecycle semantics (gating, cache-miss/stale-epoch/cancel/release, boundary-vs-token output shape) are identical across implementations. It does not — and cannot yet — prove numerical parity between a fake and a real engine; that is DGR-036's explicit job once DGR-032 and DGR-037 both exist. _ReferenceEngineintest_shard_engine.pyis intentionally minimal (no delay/memory-pressure/malformed-output/crash injection). DGR-032's acceptance criteria require those independently; nothing here should be read as satisfying them.- No gRPC/CMake/native-build changes were needed or made — this story is
pure Python interface/type definition (
evidenceClass: model-free,hardware: none), so the native CMake/CTest and patch-stack gates in the shared quality-gate list do not apply here (consistent with DGR-021/DGR-025, which record the same non-applicability for non-native stories).
Dependency handoff
- DGR-032 (fake
ShardEngine): subclassShardEngine, add delay/memory- pressure/malformed-output/crash injection, and pass the sameassert_shard_engine_contractfromtests/shard_engine_contract.pyagainst it — no new contract vocabulary should be needed. - DGR-034/DGR-035 (range-aware GGUF ownership, boundary I/O):
LoadRequestalready carriesshard_start/shard_end/total_layers/recipe;capabilities()reports the authoritative range viaEngineCapabilities.is_head/is_tail.BoundaryBundle.token_id_sidebandis reserved for the first-three-hash- routed-layers V4 requirement RALPH-CONTEXT documents. - DGR-037 (bind llama.cpp to the worker): implement
ShardEngineas a thin wrapper around the native artifact fromnative_backend.py/runtime_recipe.py;shard_runtime_server.py'sSession/GetCapability/Health/Cancel/Releasehandlers become the translation layer betweenpb.*wire messages and this module's request/result types — this story intentionally does not touchshard_runtime_server.pyitself, since that wiring is DGR-037's scope. - DGR-051 (V4
ShardEngineadapter):MtpHook/ArchitectureAuxStateHookfix the field shape now so the V4 adapter does not need a breaking change to enable MTP after DGR-066 or to carry CSA/HCA/SWA/indexer/compressor state.