Compare commits
1 Commits
520bb60f5f
...
worktree-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2868fc0d56 |
@@ -8,4 +8,3 @@
|
||||
- **Node capability admission** — `.scratch/node-capability-admission/` (P0 plan; [ADR-0023](../../docs/adr/0023-model-agnostic-node-capability-admission.md), [ADR-0026](../../docs/adr/0026-node-assignment-ownership-and-managed-placement.md))
|
||||
- **Distributed relay performance** — relay `/rpc` requester sockets are persistent per Route Session and Activation Seam as of 2026-07-10; `request_id` remains unique per activation while `X-Meshnet-Session` remains stable for KV state. Next low-risk priorities: persistent direct/loopback HTTP, seam byte/latency telemetry, then trace-driven zstd tuning.
|
||||
- **Distributed GGUF direction** — benchmark-gated native runtime: compare controlled Transformers/safetensors and whole-model llama.cpp lanes before expensive work; ship only for measured speed or model-fit advantage. Public parallelism is contiguous Shards in an Inference Route; concurrency comes from per-node continuous batching across isolated Route Sessions, while tensor/expert collectives stay inside optional trusted composite providers. Native data plane uses versioned Protobuf over long-lived gRPC/HTTP2 seam streams, with existing relay carrying the same opaque frames when needed. llama.cpp/GGML remains the substrate behind a project-owned standalone worker and small pinned fork; vLLM is an optional complete managed provider and concept donor, not a fork. Nakshatra, `prima.cpp`, `llama-gguf`, LiGGUF and historical GPUStack are source/test donors only. Active plan: [README](../../.scratch/distributed-gguf-runtime/README.md), [architecture](../../.scratch/distributed-gguf-runtime/architecture.md), [PRD](../../.scratch/distributed-gguf-runtime/PRD.md), [Ralph backlog](../../.scratch/distributed-gguf-runtime/prd.json). ADR: [0024](../../docs/adr/0024-distributed-gguf-runtime.md). Research: [landscape](../../docs/research/distributed-gguf-landscape.md), [GitHub follow-up](../../docs/research/distributed-gguf-github-followup.md), [vLLM](../../docs/research/vllm-distributed-gguf-assessment.md).
|
||||
- **Multi-subscription orchestration policy** — keep one fixed worktree per provider/agent and one user-selected integration branch. Do not switch the integration branch or create per-task branches/worktrees without explicit user confirmation. Parallel mode is default; task assignments should be disjoint and integration/push is serialized after each independently verified task. Serial mode uses an explicit provider priority, consumes the preferred subscription until its authoritative limit, then falls back in order and returns to higher priority after its official reset. Because Git cannot check out one named branch in multiple worktrees, provider worktrees should normally remain detached at the integration HEAD; the controller cherry-picks each verified task into the unchanged integration branch, tests, and pushes, then resynchronizes every fixed worktree.
|
||||
|
||||
@@ -8,23 +8,6 @@ metadata:
|
||||
|
||||
# Project Status (2026-07-13)
|
||||
|
||||
## Distributed GGUF controller checkpoint (2026-07-21)
|
||||
|
||||
- All three fixed detached lanes from the 2026-07-18 checkpoint (Fable/DGR-025, Kimi/DGR-028, Terra/DGR-024) were reviewed, committed, and merged into `ralph/distributed-gguf-runtime`, now at `cd6b4d9`. The `.claude/worktrees/ralph-fable-loop`, `ralph-kimi-loop`, `ralph-terra-loop`, `ralph-cursor-loop`, and `ralph-next-task` worktrees were removed after merge (cursor-loop/next-task were idle with no work in progress). Only `.claude/worktrees/distributed-gguf-runtime` (the integration checkout) remains, plus the unrelated `fix-tracker-incomplete-snapshot` worktree (locked, not part of this arc).
|
||||
- DGR-025 and DGR-028 merged cleanly with no conflicts (105 + 7 tests passing, 112 together). DGR-024 required real completion work first: the worktree's `prd.json` note was stale (written for the old, policy-rejected in-memory fake-seam story). The actual code already present (`shard_runtime_server.py`, `test_shard_runtime_harness.py`) had correctly pivoted to a real subprocess/socket gRPC harness with direct-vs-opaque-relay byte-identity proof, but was missing the required fail-closed negative paths (stale epoch, expired deadline, malformed/checksum-corrupt fragments, exhausted flow-control credit, duplicate idempotency steps, in-band/out-of-band cancel). Implemented those (`SessionState` per `route_session_id`, `_validate_bundle`), added 9 new tests (11 total, all passing), and rewrote `evidence/DGR-024/README.md` to describe the actual implementation instead of the nonexistent `FakeShardSeam`.
|
||||
- `prd.json`'s `passes` field was left `false` for all three stories — that flag is only flipped by the project's own independent controller review process, not by whoever lands the merge. DGR-028's evidence README explicitly still awaits that P0/P1 review.
|
||||
- Post-merge full suite (before the DGR-024 merge): 3 failed / 1116 passed / 20 skipped — down from the prior 9-failure baseline, and the 3 remaining failures (billing default-db, dynamic-routing ADD_SHARD/LOAD_SHARD, preset dedup) are pre-existing and unrelated to native/runtime-identity code. Did not get a chance to rerun the full suite after the DGR-024 merge landed (interrupted); only the focused `tests/test_shard_runtime_harness.py` (11 passed) was reconfirmed post-merge — a fresh full-suite run is worth doing before treating the whole arc as done.
|
||||
- The unrelated dirty edits on the integration worktree (`model_catalog.py` / `tests/test_mining_cli.py`, adding a `Qwen2.5-Coder-1.5B-Instruct-Q2_K-GGUF` preset) were stashed during the merge sequence and popped back afterward — still uncommitted, as before.
|
||||
|
||||
**Why:** user directed "distributed-gguf-runtime is where we need to merge all ralph-* branches" and to prune worktrees once their task's work is merged, so completed lanes don't linger and new worktrees signal new tasks unambiguously.
|
||||
**How to apply:** next Ralph session picking up this project should start from `ralph/distributed-gguf-runtime` at `cd6b4d9`, rerun the full suite once to get a clean current baseline, and check whether independent review has flipped DGR-024/025/028's `passes` flags before selecting new work.
|
||||
|
||||
## Distributed GGUF controller checkpoint (2026-07-18)
|
||||
|
||||
- Integration branch `ralph/distributed-gguf-runtime` is at `377bc3475c41b762ebbcab038c05adf15d7749d0`, matching its remote; preserve the unrelated dirty integration edits in `model_catalog.py` and `test_mining_cli.py`.
|
||||
- Fixed detached lanes hold three claimed, uncommitted tasks: Fable DGR-025/Gitea #9 executing-artifact identity repair; Terra DGR-024/#8 fake gRPC seam repair; Kimi DGR-028/#12 numbered llama.cpp patch stack. No provider worker was running at the latest reconciliation, so continue these dirty trees before selecting new work.
|
||||
- DGR-028 controller repair added working apply/reverse/verify enforcement, exact assumptions, and a passing exact-pin native fixture; final independent P0/P1 review is still required before commit/integration. DGR-024 and DGR-025 focused gates pass but likewise remain provisional pending the current independent reviews. Controller reruns on 2026-07-18 passed DGR-025 (235 impacted tests), DGR-024 (78 shared/focused tests), and DGR-028 (7 Python tests plus exact-pin native CTest 1/1 and clean apply/reverse). Integrate DGR-028 before DGR-025, then replay DGR-025 on the new integration HEAD and regenerate/retest its runtime fingerprint vectors because DGR-028 changes the pinned patch-stack/tree identity. The integration full-suite baseline is 9 failures/1076 passes/22 skips: missing optional zstd/langchain dependencies plus pre-existing billing and dynamic-routing expectations; lane-only extra failures map to stale DGR-023 projection ancestry and a timing-sensitive cancel test, not the focused story paths.
|
||||
|
||||
## Selected-node model placement (2026-07-14)
|
||||
|
||||
- Admin Model placement now opens a node selector for load and release; the control-plane accepts optional `node_id` and targets only that registry assignment. Multi-model serving remains supported through `ADD_SHARD` and `max_loaded_shards`.
|
||||
|
||||
@@ -99,9 +99,18 @@ def select_safetensors_files_for_layers(
|
||||
if not isinstance(tensor_name, str) or not isinstance(rel_file, str):
|
||||
continue
|
||||
if _tensor_belongs_to_range(tensor_name, start_layer, end_layer, inferred_total_layers):
|
||||
selected.add(_normalise_relative_file(rel_file))
|
||||
rel = _normalise_relative_file(rel_file)
|
||||
if not (root / rel).is_file():
|
||||
# A required weight file is missing from this local snapshot: the
|
||||
# snapshot is incomplete for this layer range, so it must not be
|
||||
# advertised as a source at all. Silently dropping just this file
|
||||
# (as before) made a partial snapshot look "fully cached" to
|
||||
# downstream clients, which then skipped the real download and
|
||||
# only discovered the missing weights at model-load time.
|
||||
return []
|
||||
selected.add(rel)
|
||||
|
||||
return sorted(rel for rel in selected if (root / rel).is_file())
|
||||
return sorted(selected)
|
||||
|
||||
|
||||
def _tensor_belongs_to_range(
|
||||
|
||||
71
tests/test_tracker_model_files.py
Normal file
71
tests/test_tracker_model_files.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""Tests for tracker-side layer-aware SafeTensors file selection.
|
||||
|
||||
The tracker advertises its local snapshot as a downloadable "model source" for
|
||||
whatever layer range a node needs. If a required weight file for that range is
|
||||
missing from the tracker's own disk, the tracker must refuse to advertise
|
||||
itself as a source for that range — not quietly report the subset of files it
|
||||
does have as if that were the complete, correct set. A partial-but-"complete"
|
||||
answer makes the requesting node believe the download is already satisfied,
|
||||
so it never fetches the real weights and only discovers the gap much later
|
||||
at model-load time.
|
||||
"""
|
||||
|
||||
import json
|
||||
|
||||
from meshnet_tracker.model_files import select_safetensors_files_for_layers
|
||||
|
||||
|
||||
def _write_index(tmp_path, *, config=None):
|
||||
(tmp_path / "config.json").write_text(
|
||||
json.dumps(config or {"num_hidden_layers": 5}),
|
||||
encoding="utf-8",
|
||||
)
|
||||
(tmp_path / "model.safetensors.index.json").write_text(
|
||||
json.dumps({
|
||||
"weight_map": {
|
||||
"model.embed_tokens.weight": "model-00001-of-00004.safetensors",
|
||||
"model.layers.0.self_attn.q_proj.weight": "model-00001-of-00004.safetensors",
|
||||
"model.layers.4.self_attn.q_proj.weight": "model-00004-of-00004.safetensors",
|
||||
"model.norm.weight": "model-00004-of-00004.safetensors",
|
||||
"lm_head.weight": "model-00004-of-00004.safetensors",
|
||||
},
|
||||
}),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
|
||||
def _touch(path, size=1):
|
||||
path.write_bytes(b"0" * size)
|
||||
|
||||
|
||||
def test_selects_files_when_snapshot_is_complete(tmp_path):
|
||||
"Selects files when snapshot is complete\n\nTags: general"
|
||||
_write_index(tmp_path)
|
||||
_touch(tmp_path / "model-00001-of-00004.safetensors")
|
||||
|
||||
files = select_safetensors_files_for_layers(tmp_path, 0, 0)
|
||||
|
||||
assert files == ["config.json", "model-00001-of-00004.safetensors", "model.safetensors.index.json"]
|
||||
|
||||
|
||||
def test_returns_empty_when_a_required_weight_file_is_missing_on_disk(tmp_path):
|
||||
"Returns empty when a required weight file is missing on disk\n\nTags: general"
|
||||
_write_index(tmp_path)
|
||||
# model-00001-of-00004.safetensors is required for layer 0 but was never
|
||||
# downloaded onto this tracker host — the snapshot is incomplete.
|
||||
|
||||
files = select_safetensors_files_for_layers(tmp_path, 0, 0)
|
||||
|
||||
assert files == []
|
||||
|
||||
|
||||
def test_tail_range_returns_empty_when_only_head_shard_present(tmp_path):
|
||||
"Tail range returns empty when only head shard present\n\nTags: general"
|
||||
_write_index(tmp_path)
|
||||
_touch(tmp_path / "model-00001-of-00004.safetensors")
|
||||
# model-00004-of-00004.safetensors (norm/lm_head) is required for the tail
|
||||
# range but missing — must not be silently dropped from the result.
|
||||
|
||||
files = select_safetensors_files_for_layers(tmp_path, 4, 4)
|
||||
|
||||
assert files == []
|
||||
Reference in New Issue
Block a user