feat: pin runtime identity to the exact llama.cpp patch stack (DGR-025)

Derive the recipe's runtime_version axis from the DGR-027 lock manifest
(exact upstream commit + ordered patch-stack byte digest) in new
meshnet_node.runtime_pin, failing closed on any lock/series/SHA256SUMS/
patch disagreement, and enforce pin discipline on runtime_version in both
the node and tracker identity implementations.

Also repair pre-existing backlog consistency: add missing DGR-022/DGR-027
completionNotes, regenerate the DGR-022/025/027 issue projections, and
relocate three pre-DGR legacy GLM issue files to issues/legacy/. Mark
DGR-025 passes=true with evidence at evidence/DGR-025/README.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dobromir Popov
2026-07-17 22:59:22 +03:00
parent f83cf331c3
commit ad66f7a4d8
12 changed files with 740 additions and 25 deletions

View File

@@ -0,0 +1,221 @@
"""Canonical runtime pin identity for the recipe fingerprint (DGR-025).
The recipe digest (:mod:`meshnet_node.runtime_recipe`) commits to a
``runtime_version`` axis, but a string the operator typed is a label, not a
pin: two workers could run different patch stacks under the same label and
still hash to the same recipe. The DGR-027 lock manifest
(``packages/node/native/llama``) already records the one exact upstream commit
and the ordered patch stack the native runtime is built from, so the axis
value is *derived* from that manifest, never asserted.
The derived value has three load-bearing parts, and each is separately fatal
to compatibility: the runtime name (from the upstream URL), the exact
40-character upstream commit, and a digest over the ordered patch-stack bytes.
A different upstream pin, a reordered stack, or a single changed patch byte
each produce a different axis value, which produces a different recipe digest,
which partitions the route — exactly the fail-closed behavior DGR-025 asks
for.
Every consistency check here fails closed. The manifest keeps three records of
the stack — ``UPSTREAM_LOCK.json``'s ``patch_series``, ``patches/series``, and
``patches/SHA256SUMS`` — plus the ``UPSTREAM_COMMIT`` convenience file, and a
disagreement between any two of them means the workspace's identity is
unknowable, not "probably fine". This module reads the committed manifest
only; fetching and patching the actual source tree stays with
``scripts/llama_cpp_dependency.py`` (DGR-027).
"""
from __future__ import annotations
import hashlib
import json
import re
from dataclasses import dataclass
from pathlib import Path
# Domain separation, matching the runtime_recipe digest convention: a patch
# stack digest can never be confused with an artifact or recipe digest.
PATCH_STACK_DIGEST_DOMAIN = "meshnet.runtime-patch-stack.v1"
# The UPSTREAM_LOCK.json layout this reader understands (DGR-027 schema).
RUNTIME_PIN_SCHEMA_VERSION = 1
# The committed DGR-027 manifest for the llama.cpp runtime.
DEFAULT_LOCK_DIR = Path(__file__).resolve().parent.parent / "native" / "llama"
_HEX40 = re.compile(r"^[0-9a-f]{40}$")
_HEX64 = re.compile(r"^[0-9a-f]{64}$")
class RuntimePinError(ValueError):
"""The lock workspace is missing, malformed, or internally inconsistent."""
def _canonical_sha256(value: object) -> str:
payload = json.dumps(
value, sort_keys=True, separators=(",", ":"), ensure_ascii=False
)
return hashlib.sha256(payload.encode("utf-8")).hexdigest()
@dataclass(frozen=True)
class RuntimePin:
"""One exact runtime: a name, an upstream commit, and an ordered patch stack."""
runtime_name: str
upstream_commit: str
patch_series: tuple[str, ...]
patch_digests: tuple[str, ...]
@property
def patch_stack_digest(self) -> str:
"""A digest over the ordered (name, bytes-digest) stack.
Order is digested deliberately: applying the same patches in a
different order can produce a different tree, so a reordered stack is
a different runtime.
"""
return _canonical_sha256(
{
"domain": PATCH_STACK_DIGEST_DOMAIN,
"body": {
"patches": [
[name, digest]
for name, digest in zip(self.patch_series, self.patch_digests)
]
},
}
)
@property
def runtime_version(self) -> str:
"""The exact ``runtime_version`` recipe axis value for this pin."""
return (
f"{self.runtime_name}@{self.upstream_commit}"
f"+patchstack.{self.patch_stack_digest}"
)
def _read_text(path: Path, what: str) -> str:
try:
return path.read_text(encoding="utf-8")
except FileNotFoundError:
raise RuntimePinError(f"{what} not found at {path}") from None
except OSError as exc:
raise RuntimePinError(f"{what} at {path} is unreadable: {exc}") from exc
def _read_series_file(path: Path) -> list[str]:
lines = _read_text(path, "patches/series").splitlines()
return [line.strip() for line in lines if line.strip() and not line.startswith("#")]
def _read_sums_file(path: Path) -> list[tuple[str, str]]:
entries: list[tuple[str, str]] = []
for line in _read_text(path, "patches/SHA256SUMS").splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
parts = line.split(None, 1)
if len(parts) != 2 or not _HEX64.match(parts[0]):
raise RuntimePinError(
"patches/SHA256SUMS contains a line that is not "
"'<sha256> <patch name>'"
)
entries.append((parts[0], parts[1].strip()))
return entries
def load_runtime_pin(lock_dir: Path = DEFAULT_LOCK_DIR) -> RuntimePin:
"""Derive the exact runtime pin from a DGR-027 lock workspace, or refuse.
Refuses — rather than guessing — on a missing or malformed lock, a moving
commit reference, a disagreement between the lock's ``patch_series``, the
``patches/series`` file, ``patches/SHA256SUMS``, or the actual patch
bytes, and on an ``UPSTREAM_COMMIT`` file that names a different commit.
"""
lock_path = lock_dir / "UPSTREAM_LOCK.json"
raw = _read_text(lock_path, "UPSTREAM_LOCK.json")
try:
lock = json.loads(raw)
except json.JSONDecodeError as exc:
raise RuntimePinError(f"UPSTREAM_LOCK.json is not valid JSON: {exc}") from exc
if not isinstance(lock, dict):
raise RuntimePinError("UPSTREAM_LOCK.json must be a JSON object")
schema = lock.get("schema_version")
if schema != RUNTIME_PIN_SCHEMA_VERSION:
raise RuntimePinError(
f"UPSTREAM_LOCK.json declares schema version {schema!r}; this reader "
f"understands version {RUNTIME_PIN_SCHEMA_VERSION}"
)
upstream = lock.get("upstream")
if not isinstance(upstream, str) or not upstream.strip():
raise RuntimePinError("UPSTREAM_LOCK.json is missing the upstream URL")
runtime_name = upstream.rstrip("/").rsplit("/", 1)[-1]
if runtime_name.endswith(".git"):
runtime_name = runtime_name[: -len(".git")]
if not runtime_name:
raise RuntimePinError("the upstream URL does not name a runtime")
commit = lock.get("commit")
if not isinstance(commit, str) or not _HEX40.match(commit):
raise RuntimePinError(
f"UPSTREAM_LOCK.json commit {commit!r} is not an exact 40-character "
"hexadecimal object id; a moving reference is not a pin"
)
commit_file = _read_text(lock_dir / "UPSTREAM_COMMIT", "UPSTREAM_COMMIT")
recorded = commit_file.strip().splitlines()[0].strip() if commit_file.strip() else ""
if recorded != commit:
raise RuntimePinError(
"UPSTREAM_COMMIT and UPSTREAM_LOCK.json disagree on the pinned commit"
)
lock_series = lock.get("patch_series")
if not isinstance(lock_series, list) or not all(
isinstance(name, str) and name.strip() for name in lock_series
):
raise RuntimePinError(
"UPSTREAM_LOCK.json patch_series must be a list of patch file names"
)
if len(set(lock_series)) != len(lock_series):
raise RuntimePinError("UPSTREAM_LOCK.json patch_series contains a duplicate")
series = _read_series_file(lock_dir / "patches" / "series")
if series != lock_series:
raise RuntimePinError(
"patches/series and UPSTREAM_LOCK.json patch_series disagree on the "
"ordered patch stack"
)
sums = _read_sums_file(lock_dir / "patches" / "SHA256SUMS")
if [name for _, name in sums] != lock_series:
raise RuntimePinError(
"patches/SHA256SUMS does not record exactly the ordered patch stack "
"named by UPSTREAM_LOCK.json"
)
digests: list[str] = []
for (expected_digest, name) in sums:
patch_path = lock_dir / "patches" / name
try:
body = patch_path.read_bytes()
except FileNotFoundError:
raise RuntimePinError(f"patch file {name} is named but missing") from None
except OSError as exc:
raise RuntimePinError(f"patch file {name} is unreadable: {exc}") from exc
actual = hashlib.sha256(body).hexdigest()
if actual != expected_digest:
raise RuntimePinError(
f"patch file {name} does not match its patches/SHA256SUMS digest"
)
digests.append(actual)
return RuntimePin(
runtime_name=runtime_name,
upstream_commit=commit,
patch_series=tuple(lock_series),
patch_digests=tuple(digests),
)