Skip to content

feat: let Reef own inference and training coordination - #432

Merged
BobbyZhouZijian merged 43 commits into
mainfrom
feat/inference-training-ownership
Sep 14, 2026
Merged

BobbyZhouZijian merged 43 commits into
mainfrom
feat/inference-training-ownership

Conversation

@BobbyZhouZijian

@BobbyZhouZijian BobbyZhouZijian commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

Slime's bootstrap and bridge owned inference lifecycle, weight publication and recovery. This coupled future training and inference backends to Slime's rollout management. Reef now coordinates independent backend implementations, including when a trained version may begin serving.

Implements RFC #425 in this draft PR. The RFC remains proposed; maintainer acceptance and GPU validation remain open. This does not implement the separate vLLM/MLX work in #381/#325.

Changes

  • Define independent TrainingRuntime / InferenceRuntime scheduling interfaces and native TrainingBackend / InferenceBackend ABCs in reef/runtime/interfaces.py. Concrete implementations inherit them; there is no aggregate ModelRuntime.
  • Restrict reef/runtime/ to five modules and executor/: interfaces.py for contracts/values, scheduler.py for scenario scheduling and serialized training/resource handoffs, deployment.py for plans/resources/factory discovery, publication.py for transfer/version/commit coordination and LoRA residency, and recovery.py for durable state and reconstruction. Directory, dependency and installed-wheel checks enforce the layout. Runtime is a PEP 420 namespace package without a package facade.
  • Keep RuntimeScheduler and worker-side TrainingCoordinator as distinct objects in scheduler.py. Actual weight transfer ordering, target allocation, receiver verification and adapter replay live in publication.BackendWeightPublisher; startup restoration lives in recovery.TrainingRecovery. Shared store ABCs avoid circular imports while preserving disk-first job transitions.
  • Move HTTP/generic inference runtimes to reef/inference/, generic training connections to reef/train/runtime.py, and coordinator RPC transports to runtime/executor/connection.py. Generic pair assembly lives in reef/service/runtime.py. Builtin factories resolve lazily without package-import registration side effects.
  • Put concrete SGLang engine/router launch, request capture, plugin, configuration, weight/LoRA receipt and memory operations in reef/inference/sglang/. SGLangInferenceRuntime owns its default request handler. SlimeTrainingRuntime connects training and uses the independently selected inference factory. Runtime imports neither integration; training and inference integrations do not import each other, including from local functions.
  • Let Reef assemble separate unallocated training/inference components, validate native transport compatibility, reserve resources, fence inference before colocated training initialization, attach a fresh weight-transfer session, and start the generic coordinator. Cleanup, current-worker monitoring and bounded reconstruction follow component ownership.
  • Preserve full-weight/LoRA publication and colocated resource handoffs. Reef persists each transfer target before sending, verifies the sender and every receiver, and keeps generation fenced until durable artifact commit acknowledgement. Sender preparation/export and trainer release precede receiver memory restoration. Native senders cannot independently pause, resume or restart inference.
  • Name recipe update contracts CandidateBackend / RuntimeCandidateBackend and request execution InferenceHandler. Replace remaining first-party Protocol contracts with explicit inheritance and add CI enforcement against Protocol, runtime_checkable and TYPE_CHECKING, including alias forms. Protocol violations cannot be baselined; existing Callable debt does not grow. Repository-local uv caches are excluded as third-party dependencies, with regression coverage that still rejects authored Protocol definitions.
  • Keep managed inference resources under inference.*, update maintained YAML/request-handler examples, backend-extension documentation, plugin registration and wheel checks. Fix base-wheel test collection when optional Ray is absent.

Tinker on this branch

  • Tinker's inference side moved to reef/inference/tinker.py (SDK sampler, TinkerInferenceRuntime, chat handler). The trainer in reef/train/tinker_backend/ keeps its incumbent on disk; the two share only each artifact's tinker-checkpoint.json manifest. TrainingRuntime.commit_candidate (no-op default) lets the scheduler tell a trainer with immutable incumbents which candidate Reef committed.
  • Local SGLang inference with Tinker training: training.backend: tinker plus inference.backend: sglang runs Reef's model driver with a GPU-less trainer (ModelGpuLayout accepts zero training GPUs), SGLang engines in LoRA serving mode, and TinkerTrainingBackend behind Reef's coordinator. Adapter delivery is a Reef-owned transfer (reef-adapter-files-v1): TrainingBackend.adapter_files returns the PEFT directory, InferenceBackend.load_adapter_files loads it at the receiver, the publisher drives both; inference services list the transfers they accept. The HTTP service connects through the generic coordinator_training runtime kind.
  • tinker-cookbook==0.5.7 is pinned in the tinker extra for the checkpoint-to-PEFT conversion.
  • recipes/tttd/examples/tttd/serve-tinker.yaml runs the Erdős example on Tinker; the harness reads its stack file from TTTD_STACK. Running it exposed two judge bugs (no cvxpy in the judge image although the instruction offers it; numpy results rejected by the runner's json.dumps), both fixed.

Compatibility and operational impact

  • Extensions import runtime/native contracts from reef.runtime.interfaces and factory APIs from reef.runtime.deployment. The previous runtime package facade and base, backends, adapters, control, weights, training_job module paths are removed. ModelRuntime, ExecutorModelRuntime and aggregate RayRuntime aliases are removed. Model processes must run the same revision.
  • Runtime factories and connection helpers return (training_runtime, inference_runtime). Generic executor_training / ray_training kinds remain. Automatic Slime assembly selects slime_training with an independent inference_runtime selector; SGLang is the currently supported native receiver. Coordinator transports use CoordinatorClient and Executor/Ray variants. connect_ray_runtime and connect_executor_runtimes live in reef.service.runtime.
  • Native components, optional capabilities and factories require explicit ABC inheritance. Recipe extensions use CandidateBackend and Trainer.candidate_backend; request adapters use InferenceHandler, inference_handler, and its from_config classmethod. Evaluation plugin factories implement .build(...); header providers implement .headers(...). Existing native harness entrypoints retain boundary adapters.
  • Request adapter configuration uses inference.handler-factory / inference.handler-config; former request backend-factory / backend-config keys are rejected. Native inference.backend / training.backend selection is separate. Complete dotted CLI flags override YAML; no public services section is added.
  • inference.num-gpus, inference.tensor-parallel-size and inference.options are authoritative for managed inference; equivalent training-native rollout resource flags are rejected. training.colocate (default false) decides whether training and inference share the same GPUs; Reef makes the reservation and passes the colocation flags to the Slime driver. Model drivers return create_training_plan plus an independently selected inference definition. Direct start_bridge / TrainBridgeActorImpl construction is replaced by Reef assembly; legacy argument-file/healthcheck inputs remain supported.
  • The existing slime-sglang-control-v2 native attachment and direct worker-to-worker weight transport remain. Runtime IDs retain <incarnation>:<sequence>; pending markers may contain target_runtime_load_id, and older markers remain readable. Artifact formats, provider bodies, scenario isolation and receipt linkage retain their contracts.
  • Managed recovery retains HTTP and external Ray, allowing three component replacements per five minutes with 1/2/4-second delays. In-flight mutation/inference calls are not automatically replayed. Unconfirmed cleanup or ambiguous RUNNING state stops recovery; Slime rejected candidates require restoring committed trainer state before cold reconstruction.
  • Borrowed engines, PRM and user-simulation services retain external ownership. Reef reserves the model GPUs itself (reef.runtime.executor.placement: one placement group sized from inference.num-gpus, the trainer's GPU count and training.colocate, with bundles sorted by node and device) and hands the training and inference portions to the backends; Slime no longer creates its own placement groups. training.colocate is the only colocation switch: training.options.colocate / offload-rollout are rejected, and the driver receives the matching native flags from Reef. This adds no cluster autoscaling, dynamic parallelism resizing or arbitrary backend transport interoperability. Initial colocated training releases all inference memory; keeping the LoRA base resident applies only to later steps.

Verification

Validation on macOS ARM64 without CUDA for the merged source in 8607194d, plus the subsequent CI cache-scan correction:

  • Full source suite: python -m pytest tests -n 4 --dist loadfile --cov=reef --cov-report=term -q --tb=short --durations=15 — 3,800 passed, 60 skipped; 88.50% coverage. Repository environment, Node.js 22/uv on PATH, proxy bypass and isolated Git configuration.
  • Installed base wheel, outside the repository with no Ray/Torch/Slime: package-CI service suite — 3,043 passed, 62 skipped. Used CI's training-dependent test exclusions.
  • Real Ray CPU workers: REEF_TEST_RAY=1 over test_inference_control.py, test_training_restart.py and test_model_supervision_ray.py — 12 passed. Covers moved coordinator/control paths, named discovery, publication, commit barriers, reconstruction and cleanup across processes. Run on 56bfbf87; the merge and cache-scan fix leave these runtime/inference modules unchanged.
  • pre-commit run --all-files passed. python -m mypy passed for 275 source files. The design baseline retains 25 existing Callable entries; only moved-file paths changed. Directory/import boundary suite: 35 passed. Protocol policy suite: 45 passed, including reproduction of CI uv-cache false positives while still rejecting Protocol in owned source.
  • Node.js 22: npm ci, npm run check:docs, npm run lint, npm run build passed.
  • Built sdist/wheel, twine check and uv lock --check passed. An installed-wheel smoke check blocked Ray, SGLang, Slime, Torch, Megatron and Transformers imports while validating exact namespace contents, independent contracts, lazy native runtime factory discovery, generic connections, HTTP/model override construction and the SGLang plugin entry point.

Remote CI passed for cb51707a: lint and the test/package matrices on Python 3.10, 3.11 and 3.12 are all green. CI run.

Actual GPU checkpoint loading, LoRA IPC/NCCL transfer, colocated memory capacity and performance remain unverified. CPU contracts and process tests do not satisfy those acceptance gates.

Real Tinker runs on this branch (Qwen3-8B, CPU host, both in-process topology):

  • tutorials/tinker smoke: four sampled rollouts, one remote optimizer step, one committed release.
  • recipes/tttd/examples/tttd/serve-tinker.yaml on the Erdős task through harbor, thinking on, 26,000-token budget, 2 x 2 grid: two of four programs valid (C₅ ≈ 0.4995 / 0.5000), one training step committed, incumbent advanced. The 2 x 2 grid degenerates TTTD's leave-one-out advantages (±1e12), so that step checks the mechanism, not the method; a meaningful step needs more rollouts per group.
  • Restart and rollback on real Tinker (in-process topology): the restarted stack rebound the serving version to its new incarnation and trained step 2 from the committed adapter (best reward 2.612, C₅ ≈ 0.383); a rollback to the step-1 release minted a new served version and moved the trainer's incumbent back to that checkpoint.
  • A non-degenerate step, 2 groups x 8 rollouts with the paper's settings: advantages in [-0.90, 3.46], adaptive betas ≈ 1.2–1.6, loss:sum ≈ -5.5e4, four valid programs, best C₅ ≈ 0.386, one committed step.
  • The local-engine topology end to end on CPU (tests/reef_service/test_tinker_local_engine_ray.py): a Ray cluster with pretend GPUs, the real model driver, coordinator and HTTP-side connection, a stub engine accepting the adapter-file transfer in place of SGLang. Passes with the fake SDK in CI and, run locally with REEF_TEST_TINKER_REAL=1, with the real SDK: real training step, archive download and cookbook conversion (110 s). The converted adapter has 506 tensors with Hugging Face parameter names and shapes matching Qwen3-8B at rank 32.
  • Not run on GPU: an actual SGLang engine loading the adapter and serving it. Open risk found by the adapter check: Tinker also adapts lm_head, which SGLang's LoRA loader may not accept.

AI assistance

OpenAI Codex assisted with implementation, review, tests, documentation and this description at the contributor's direction. The human contributor remains responsible for reviewing and understanding the submitted changes and validation claims.

Checklist

  • The change is focused and contains no unrelated cleanup.
  • Tests cover behavior changes, or this pull request does not change behavior.
  • Public interface changes include contract tests, or no public interface changes are present.
  • Affected user and developer documentation is updated, or no documentation update is required.
  • Root README changes update both languages and README.i18n.yaml, or do not affect README content.
  • An accepted RFC is linked, or this change does not require an RFC.
  • Relevant pre-commit and test checks pass.
  • Non-trivial AI assistance is disclosed above, or none was used.

Review and merge

RFC #425 acceptance and GPU validation remain open. Follow the repository's maintenance model for review and merge requirements.

@github-actions

Copy link
Copy Markdown

Merge Oncall: @BobbyZhouZijian

The merge oncall will route reviews and keep this pull request moving toward a clear decision.

@github-actions github-actions Bot added area: docs User and developer documentation area: examples Examples, recipes, and reference deployments area: harness Harness integration, recipes, and evolution surfaces area: packaging Packages, containers, deployment, and vendored integrations area: service Service APIs, deployment, and command-line interfaces area: training Training execution, runtimes, algorithms, and pipeline reliability dependencies Dependency and toolchain updates labels Sep 12, 2026
@github-actions github-actions Bot added the area: ci Repository automation, continuous integration, and developer tooling label Sep 12, 2026
@github-actions github-actions Bot added the area: core Core contracts and scenario lifecycle label Sep 13, 2026
BobbyZhouZijian and others added 2 commits September 13, 2026 22:51
The test polls for the pid file and could read it before the write
finished, failing with an empty JSON document on busy CI runners.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Resolves the overlap with the ATIF training-data refactor (#446) and the
reported-feedback simplification (#445): main's TrainingBatch/TrajectoryItem
model is kept everywhere, this branch's names stay (CandidateBackend,
CandidatePluginFactory, SupportsReceipt, the runtime module split), main's
edit to the removed reef/runtime/adapters/executor_runtime.py is carried
into reef/train/runtime.py, and the Terminal-Bench example imports the
proxy runtime from reef.inference.http.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hanfeiyu

Copy link
Copy Markdown
Collaborator

Overall this looks great. Thanks for taking on this substantial refactor!

BobbyZhouZijian and others added 9 commits September 14, 2026 09:06
Brings in the Tinker backend (#448, #464) and splits it along this
branch's runtime ownership: TinkerCheckpointStore holds the local manifests
and remote snapshots, TinkerTrainingRuntime (reef.runtime.interfaces
TrainingRuntime) branches candidates from the store's active checkpoint,
and TinkerInferenceRuntime (InferenceRuntime) owns the chat handler,
serving version, candidate activation, publication acknowledgement and
head binding. The launch factory returns the pair; the scheduler owns
admission. activate_checkpoint moves onto WeightRuntime with the same
default, and WeightLoader is an ArtifactActivator so the committer and
startup recovery bind remote snapshots. The removed reef/runtime/base.py
and __init__.py stay removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…Lang serving

Selecting inference.backend: sglang with training.backend: tinker runs
Reef's model driver: the placement reserves inference GPUs only (a layout
with zero training GPUs is now a hosted trainer), the SGLang engines start
with LoRA serving, and Reef's coordinator drives TinkerTrainingBackend, a
native TrainingBackend. Each job trains one optimizer step on Tinker from
the scenario's published checkpoint, downloads the result and converts it
with tinker-cookbook into a PEFT adapter under the job checkpoint, and
publication loads that directory into every engine through a new
load_adapter_from_disk control operation; the incumbent per scenario is
remembered on disk so rejection leaves it and restarts branch from it.
The HTTP service connects through the new coordinator_training runtime
kind, the generic form of the Slime connection. The managed-inference
capacity and driver-process helpers move from the Slime launcher into
reef.train.deployment so both trainers share them. The in-process Tinker
topology is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tore

reef.inference.tinker owns Tinker's sampling side: the SDK sampler, the
inference runtime and its chat handler, resolving each artifact's
tinker-checkpoint.json manifest to the immutable remote sampler it names.
reef.train.tinker_backend keeps the trainer, which branches every candidate
from the incumbent it remembers on disk. The two share only that manifest.
TrainingRuntime gains commit_candidate, a no-op by default, which the
scheduler calls after Reef's durable commit and once at startup for the
head's job, so a trainer with immutable incumbents learns the head without
holding the inference runtime. The in-process pair is built through the
registered "tinker" inference kind.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A trainer that produces adapters as PEFT directories no longer needs the
engines' native control handle. TrainingBackend.adapter_files returns the
directory to serve as a version; InferenceBackend.load_adapter_files loads
it at the receiver; BackendWeightPublisher takes that path for publication
and for residency re-activation, verifying the served version as before.
Trainers declare the reef-adapter-files-v1 transfer and inference services
list the transfers they accept, so the plan pairs Tinker with SGLang without
Tinker knowing SGLang's control protocol. SGLang's receiver loads files
through its control actor; the Tinker backend sheds its engine handle and
its send methods refuse.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…in the scenario test

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The converter that turns Tinker checkpoints into PEFT adapters for a local
engine is a released package; pin it instead of asking operators to install
it by hand.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… running it

serve-tinker.yaml runs the TTT-Discover example on Tinker's hosted LoRA
training and sampling with the paper's method settings and the reduced
2 x 2 grid; the harness reads the stack file from TTTD_STACK and the
thinking flag from training.config, so both sides still agree.

A real run showed two judge bugs that scored every program zero: the judge
container lacked cvxpy although the task instruction offers it, and its
runner serialized program results with json.dumps, which fails on the numpy
arrays the verifier itself accepts. Both fixed and verified against the
sampled programs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A Ray cluster with pretend GPUs, the real model driver, a stub engine that
accepts Reef's adapter-file transfer in place of SGLang, and the Tinker SDK
faked on the driver's path (or real with REEF_TEST_TINKER_REAL=1) drive one
TTTD step through the coordinator from a Dispatcher connected like the HTTP
service. Running it found three things the doubles had hidden: the trainer
must open its SDK session inside the coordinator's process rather than be
pickled with one, the coordinator's process needs the recipe's Tinker loss
reference to import the recipe and its step preparer, and capacity
resolution overwrote a selected dotted inference factory with "sglang".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The Tinker SDK client refuses older interpreters, as the tinker extra does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@BobbyZhouZijian
BobbyZhouZijian marked this pull request as ready for review September 14, 2026 14:32
@BobbyZhouZijian
BobbyZhouZijian merged commit 58765b7 into main Sep 14, 2026
17 checks passed
BobbyZhouZijian added a commit that referenced this pull request Sep 14, 2026
main reworked the ground this branch stands on: #432 gave Reef ownership of
inference/training coordination, #446 unified training data as ATIF items, and
#412 moved the scenario and runtime modules. The MLX backend is re-integrated
rather than merely merged.

Conflicts and how they resolved:

- `reef/runtime/adapters/` and `reef/service/deploy/settings.py` are gone on
  main; the deletions are accepted. The MLX kind registers from
  `reef/train/__init__.py`, which is the direction the boundary allows.
- `reef/surface/base.py` and `reef/inference/sglang/chat.py` take main's
  restructured versions; `RecoveryRestorer` is re-added in main's ABC idiom.
- `reef/service/assembly.py` takes main's version: the function this branch had
  changed built a runtime from `ServiceSettings`, which no longer exists.

Re-integration:

- The batch path reads ATIF items. The captured tensors move from a
  `PolicySample`'s attributes to the item's `extra.reef.training`, where the
  openclawrl processor already writes them; the tests use main's own
  `policy_trajectory` helper so both sides agree on that layout.
- `MLXServingRuntime` (new) owns the parameters, the admission gate and the
  served version; `MLXRuntime` keeps candidates, the objective and checkpoints,
  and reaches the engine through it. The factory returns the pair #432's
  contract names. The seam follows the state: three methods needed both halves,
  and all three have the same shape — hold serving, touch the engine, release —
  so serving exposes an explicit `hold`/`release` rather than a context manager,
  because activation deliberately stays held until Reef's commit.
- `MLXInferenceBackend` implements both `InferenceHandler` and
  `InferenceBackend`; a receiver that runs as a separate service splits those,
  an in-process engine does not. The receiver operations that would mean moving
  memory Reef does not own (`offload`, `onload_*`, `unload_adapter`) raise
  instead of pretending, which is what the base class does for
  `load_adapter_files`.
- `assistant_message.py` moves under the MLX backend: main's boundary test
  counts it as an unowned module in `reef/runtime/`, and the MLX backend is its
  only consumer.

One judgement worth flagging: the shipped-config layout test now skips
`results/` directories. A results directory records the deployment a past run
used; migrating it to the current schema would make it a config that was never
executed, which is worse than an old one, because the record's whole value is
that it is what ran.

Verified: 3528 passed, 88 skipped (slime/ray/inference modules excluded — those
dependencies are absent here). mypy clean, ruff 0.14.7, isort 5.13.2,
black 24.3.0, and the Python design and statement policies pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SuEa3FyrkW1xc3sjmAJSEB
BobbyZhouZijian added a commit that referenced this pull request Sep 14, 2026
… activates

A live run on the merged tree found what 3528 passing tests did not.

**Nothing could start.** #432 replaced the public layout, so the MLX runtime's
config keys were no longer consumed: the deployment selects a runtime through
`training.backend` now, and its options arrive as `training.options`. This adds
`MLXDeployment(InProcessTrainingDeployment)` and registers `mlx` as a built-in
backend; the base class already refuses the Ray, executor and inference-engine
settings an in-process integration has no use for.

**Candidate evaluation is a factory class.** `CandidateEvaluationPluginFactory`
replaced the plain `build` function, and it receives both runtimes. That
correction matters here: the probe applies a candidate's weights and generates
from them, so it belongs to the *training* half — the serving half deliberately
never sees a candidate before Reef selects it.

**Activation belongs to the half that serves.** `activate_candidate` is
declared on `InferenceRuntime`, so Reef calls it there, and the split had left
it on the training runtime holding the staged snapshots. Every test passed,
because they called it directly on the training object rather than through the
caller Reef uses; the first live training step failed with "MLXServingRuntime
does not support candidate activation". The serving half now owns the staged
snapshots — it is the one that adopts them — and training stages and discards
through it. Two regression tests assert the seam as Reef holds it.

Verified by running it: four optimizer steps on Qwen3.5-9B, `rows=8` each,
`adapter_tensors_changed=304` (every LoRA tensor moving, so the gradient path
is intact), `adapter_delta_l2` 0.84-1.02 (the pre-merge run's first step was
0.837), the gate deciding as `regression-gate`, the probe's `answered_rate` at
1.0, and the served version advancing on every activation.

Suite: 3530 passed, 88 skipped. mypy, ruff, isort, black and the design and
statement policies pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SuEa3FyrkW1xc3sjmAJSEB
BobbyZhouZijian added a commit that referenced this pull request Sep 15, 2026
…struction

The repository had no MLX deployment anyone could run. The reference
`serve.yaml` is the seven-GPU stack, and the two configs beside the run records
are archives in the pre-#432 schema, deliberately left as what those runs used.
So the current shape had to be rediscovered from startup errors, one field at a
time.

`serve-mlx.yaml` is that shape, and it is the file the verification run used:
`training.backend: mlx` with the runtime's options under `training.options`,
the model named in `inference.model-path`, and the candidate gate in
`evaluation`. The comments carry the reasons that are expensive to rediscover —
why `in_proj_qkv` is adapted, why a cached prefill is ruled out, why the judge
needs a large token budget, and that relative storage paths make two runs from
one checkout collide on the artifact repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SuEa3FyrkW1xc3sjmAJSEB
BobbyZhouZijian added a commit that referenced this pull request Sep 19, 2026
Main moved inference ownership into reef.inference.sglang and publication
into reef.runtime (#432), deleting the rollout manager and the preflight and
bridge code this branch changed. Port the branch's behavior onto the new
owners instead of keeping the deleted paths:

- SGLangConfig decides prefix sharing: it defaults disable_radix_cache to
  off only when publication retracts (and, under LoRA, when SGLang keys
  radix entries by adapter), rejects overrides that re-enable sharing
  otherwise, and rejects PD groups with a retracting pause.
- The Slime translation selects the retract pause for colocated engines or
  --disjoint-prefix-sharing and no longer forces the radix flag on.
- The SGLang worker's retract pause flushes the cache after pausing.
- TrainingPublication marks a CHECKPOINT UPDATING_WEIGHTS when a failed
  pause barrier (publication or startup) has retired the engines.
- The adapter-scoped radix-key check moves beside the LoRA schema checks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci Repository automation, continuous integration, and developer tooling area: core Core contracts and scenario lifecycle area: docs User and developer documentation area: examples Examples, recipes, and reference deployments area: harness Harness integration, recipes, and evolution surfaces area: packaging Packages, containers, deployment, and vendored integrations area: service Service APIs, deployment, and command-line interfaces area: training Training execution, runtimes, algorithms, and pipeline reliability dependencies Dependency and toolchain updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants