Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .agents/skills/fine-tuning/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ Train language models with SFT, KTO, and GRPO locally or on supported cloud prov
| Check SFT loss masking (tokenizer only) | `python tuner.py doctor sft-mask --dataset-path <jsonl> --model <tokenizer>` |
| Inspect native training host candidate | `python tuner.py doctor native-training --json` — read-only platform/Python/package metadata; see `reference/native-local-training.md` |
| Diagnose an offline SFT worker rejection | Read the exact retained `trainer.stderr.log`; closed phase/category/milestone labels locate a boundary, not a cause or retry authority; see `reference/sft-training.md` |
| Native MLX prepared SFT candidate | Internal exact-token batch/loss and runtime comparison only; no native launch CLI or API provider yet; see `reference/native-local-training.md` |
| Native MLX prepared SFT candidate | Gated `ProviderFamilyV1` through existing TrainingAPI/RunsAPI; isolated worker, signed host catalog and native artifacts; no hardware qualification or launch CLI yet; see `reference/native-local-training.md` |
| Capture reviewed native runtime bytes | `python -B scripts/capture_native_mlx_runtime.py --config <absolute-config> --dependency-lock <absolute-lock> --output <new-private-file>` — observation only; explicit roots, dependencies and original pins required; see `reference/native-local-training.md` |
| Plan a derived training image | `python scripts/qualify_derived_training_image.py plan --config Trainers/image_profiles/<profile>.yaml` |
| Warm Space scaffold | `python3 Trainers/cloud/scripts/manage_space.py render --template vllm_warm --output-dir /tmp/my-space --base-image ghcr.io/<org>/<image>:<tag>` |
| Warm Space deploy | `python3 Trainers/cloud/scripts/manage_space.py deploy --space-id <user>/<space> --template vllm_warm --base-image ghcr.io/<org>/<image>:<tag> --hardware a10g-small --sleep-time 3600 --var BASE_MODEL=<model>` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ model:
runtime:
provider: modal
lock_path: tuner/execution/providers/modal/modal-runtime-v1.lock.json
expected_lock_sha256: 4f3fa81c9aeb9130258dec23f2b841e6dbdf2d686d1cf6b50249e743c3d496ca
expected_lock_sha256: 1f7422b56bf4d1c7bd07dfc440da8263719d7e74dc4ceeeb94100f9680a48087
input:
jsonl_path: /replace/with/private/prepared-dataset.jsonl
mode: text
Expand Down
133 changes: 129 additions & 4 deletions .agents/skills/fine-tuning/reference/native-local-training.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ remain ignored. Training shuffles deterministically within its own split;
validation retains every row in declared order, including partial batches.

The custom hooks target pinned MLX-LM 0.32.2. One batch is one optimizer update;
gradient accumulation and checkpointing are deliberately unavailable in this
gradient accumulation and activation checkpointing are deliberately unavailable in this
increment. Upstream accumulation averages microbatch means, which needs a
separate objective review for unequal supervised-token counts. Model, LoRA,
optimizer and learning-rate policy must be prepared explicitly by the future
child composition; this worker does not infer or silently apply those controls.
optimizer and learning-rate policy are prepared explicitly by the isolated
child composition; this worker does not infer those controls.

`tuner/runtime/native_mlx_runtime.py` compares host-supplied exact interpreter
and complete distribution pins against the running candidate before worker ML
Expand All @@ -62,5 +62,130 @@ into the shared interpreter or treat a newly observed inventory as approved.

There is no native launch CLI yet. The internal worker may run only in an
independently admitted, host-owned bounded child. The desktop plan lists the
missing native runtime material, child lifecycle, artifact roles and API joins.
implemented runtime/family boundaries and remaining consumer/qualification work.
Do not call the worker as an ad hoc substitute for that composition.

## Execution-boundary continuation

The internal runtime modules now include a read-only native material capture,
retained-source/tokenizer join, explicit LoRA/constant-AdamW composition,
independent safetensors delta verifier, and owned subprocess guardian. These are
reviewable runtime boundaries. The gated family described below composes them
through the existing public coordinator; no global provider registration or
native launch CLI is supplied.

`scripts/capture_native_mlx_runtime.py` takes a JSON object with `capture` and
`expectation`. `expectation` uses the existing `MLXRuntimeExpectation` fields.
`capture` contains absolute `stdlib`/`packages` roots, sorted `sources` trees,
sorted explicit external `files`, sorted `system_libraries`, and sorted
`aliases` pairs of absolute alias path and exact symlink spelling. Every tree
file, including startup `.pth` and bytecode, is captured. Unlisted aliases reject.
Homebrew's framework aliases must resolve to explicit captured bytes. Its
stdlib `site-packages` alias is recorded but excluded: the isolated child uses
`-I -S -B` and explicitly binds only its captured package search path.

Run the selected interpreter with `-B`, from an independently reviewed source
checkout, to avoid creating bytecode while capturing. Output requires an
existing owner-private parent and is exclusive; no environment repair or
installation occurs. `--check <capture> --expected-digest <reviewed-sha256>`
revalidates the exact original configuration and capture. Unknown/ambiguous
Mach-O dependencies, uncaptured external files and extra declared OS libraries
reject. OS shared-cache dependencies are explicitly trusted through the recorded
OS/kernel build, not falsely described as hashed ordinary files.

This captures installed bytes and static native dependencies. It does **not**
prove selected wheel archive provenance, attest dynamic `dlopen` behavior,
freeze the filesystem against a malicious same-uid process, or independently
grant execution. Root review must reconcile the original hash-required install
evidence and selected archives; public capability remains gated.

`native_mlx_input.py` consumes the existing retained stream lease, verifies
identity/hash/size, and feeds the established JSONL publication rows to shared
`materialize_sft_example`. It retains row IDs and splits without filtering or
repair. The tokenizer loads only from a verified private local snapshot with
`trust_remote_code=False` and `local_files_only=True`. Model and tokenizer
snapshots, exact source, rendering arguments and worker controls are committed
in the bound input. The host still owns publication semantic/lineage validation
and binding to an actual compiled workload.

`native_mlx_composition.py` loads a configured local MLX snapshot, selects every
LoRA target/layer explicitly, checks the realized trainable names/shapes and uses
explicit AdamW parameters with constant schedule. Unsupported schedules reject.
It checks the optimizer's actual step count. The native adapter verifier checks
tensor headers, bounds, names/shapes/dtypes, finite values and a nonzero numeric
parameter delta. Final validation is a distinct pass **after reloading the saved
adapter**; upstream in-loop validation occurs before the last optimizer update.
It saves native `adapter_config.json`, `input_binding.json` and
`native_result.json` exclusively. These worker files become authenticated public
artifact roles only through the family verifier described below.

`native_process.py` records claim/spawn/outcome through the existing
`DurableRecordStorePort` in the effects partition. There is no engine database.
The stdlib guardian owns the worker group, drains bounded output without
exposing its contents, enforces time/file bounds, and terminates on owner-pipe
loss or cancellation. Darwin uses kqueue process notifications because the
qualification CPython does not expose `os.waitid`. Linux tests use waitid without
reaping. Persisted PIDs are diagnostic only; another process cannot acquire
signal authority by reading them. Interrupted submission/publication retains
uncertainty and never auto-replays. This is trusted-worker supervision, not an
OS sandbox; escaped hostile descendants and guardian failure remain outside the
current evidence. Real Darwin lifecycle tests remain required.

Before ML imports/training, independently review the isolated child bootstrap,
authenticated compiled workload/native material, public provider-family
composition and native artifact roles. The bounded next proposal is
`Trainers/mlx_sft_mac/runtime-candidate/sft-qualification-proposal.json`; its
status is review-required and it is not executable admission.

## Public coordinator continuation

`native_mlx_compilation.py` recompiles `TrainingInputV1` plus the retained
`PreparedTrainingInputIdentity` and explicit `NativeMLXProfile` into a normal
`CompiledWorkload`. Parsing re-derives the complete document. Model/tokenizer
pins, loss semantics, chat arguments, batch/sequence/update/seed/checkpoint
controls, LoRA and constant AdamW are explicit. Accumulation, epochs, DoRA,
RSLoRA, implicit splits, packing and unsupported checkpoint-pruning policies
reject. Profiles declare the alpha/rank scale conversion; no model switch is
embedded in a launcher.

`native_mlx_child.py` is an internal `-I -S -B` entrypoint. It restricts import
roots, checks imported source/extension origins against capture members and
compiles pinned Python source rather than ambient bytecode. It joins the exact
staged dataset, capture, lock and snapshots to the recompiled workload. It is
not a public invocation or an independent source/qualification authority.
`native_runtime_spec` represents the capture with the existing `RuntimeSpec`
`native_environment` discriminator; it invents no OCI image. Legacy OCI
canonical bytes are unchanged.

`native_mlx_planning.py` supplies immutable planning/preparation adapters.
`native_mlx_family.py` supplies the existing `ProviderFamilyV1`: stage, bounded
synchronous submit, authenticated known-run observation and artifact streaming.
Use it with `compose_reference_host`; Syntunia's existing loader/resolver,
grant, record, stream, secret and clock ports remain authoritative. The consumer
must authenticate actual source evidence and current hardware before signing
command material. `NativeCommandCatalogV1` retains create-only signed material
through the existing record port. Signed terminal evidence must also match the
retained process outcome on every read. It is not an engine database or replay grant.

No accepting hardware authority is shipped. Candidate descriptors have
observe/artifact capabilities disabled and preflight is not ready. A
`NativeQualificationV1` contains exact selected profile/source/runtime/hardware
and two distinct retained attempt-evidence references; its independent host
authority must authenticate the supporting real runs, selected wheel/install
provenance and final-adapter/public-readback evidence. Reference hashes alone
are not qualification. Public logs, cancellation and reconciliation remain
disabled even with this narrow qualification. The guardian's internal stop
path does not promote public cancellation.

`native_mlx_publication.py` independently checks the exact output inventory,
workload/input binding, optimizer count, finite saved tensor delta, retained
checkpoint tensors and final-adapter validation identity. It emits the five
existing roles. `final_model` is a deterministic POSIX tar containing the MLX
adapter/config/checkpoints and pinned base manifest; `tokenizer` is an explicit
configured member archive from the verified snapshot. Lineage/metrics retain
the exact worker bindings. Finite file/aggregate budgets and public 1 MiB
stream chunks apply. CPU verification does not rerun the final evaluation.

See `docs/plans/native-desktop-training-api-v1.md` for remaining host assembly,
review and real-Mac acceptance. The CPU facade tests substitute the ML child;
they are not a hardware result and must never unlock the candidate.
3 changes: 2 additions & 1 deletion .claude/skills/fine-tuning/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ Train language models with SFT, KTO, and GRPO locally or on supported cloud prov
| Check SFT loss masking (tokenizer only) | `python tuner.py doctor sft-mask --dataset-path <jsonl> --model <tokenizer>` |
| Inspect native training host candidate | `python tuner.py doctor native-training --json` — read-only platform/Python/package metadata; see `reference/native-local-training.md` |
| Diagnose an offline SFT worker rejection | Read the exact retained `trainer.stderr.log`; closed phase/category/milestone labels locate a boundary, not a cause or retry authority; see `reference/sft-training.md` |
| Native MLX prepared SFT candidate | Internal exact-token batch/loss and runtime comparison only; no native launch CLI or API provider yet; see `reference/native-local-training.md` |
| Native MLX prepared SFT candidate | Gated `ProviderFamilyV1` through existing TrainingAPI/RunsAPI; isolated worker, signed host catalog and native artifacts; no hardware qualification or launch CLI yet; see `reference/native-local-training.md` |
| Capture reviewed native runtime bytes | `python -B scripts/capture_native_mlx_runtime.py --config <absolute-config> --dependency-lock <absolute-lock> --output <new-private-file>` — observation only; explicit roots, dependencies and original pins required; see `reference/native-local-training.md` |
| Plan a derived training image | `python scripts/qualify_derived_training_image.py plan --config Trainers/image_profiles/<profile>.yaml` |
| Warm Space scaffold | `python3 Trainers/cloud/scripts/manage_space.py render --template vllm_warm --output-dir /tmp/my-space --base-image ghcr.io/<org>/<image>:<tag>` |
| Warm Space deploy | `python3 Trainers/cloud/scripts/manage_space.py deploy --space-id <user>/<space> --template vllm_warm --base-image ghcr.io/<org>/<image>:<tag> --hardware a10g-small --sleep-time 3600 --var BASE_MODEL=<model>` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ model:
runtime:
provider: modal
lock_path: tuner/execution/providers/modal/modal-runtime-v1.lock.json
expected_lock_sha256: 4f3fa81c9aeb9130258dec23f2b841e6dbdf2d686d1cf6b50249e743c3d496ca
expected_lock_sha256: 1f7422b56bf4d1c7bd07dfc440da8263719d7e74dc4ceeeb94100f9680a48087
input:
jsonl_path: /replace/with/private/prepared-dataset.jsonl
mode: text
Expand Down
Loading
Loading