Semantic versioning for the launcher CLI (sm121). The add-on image has its
own version and its own sm121/CHANGELOG.md; do not mix them.
format 2) packages are blob stores: blobs/<sha> holds the data once and
models/<version>/{model.safetensors,weights/,deployments/} are hardlinks
into it. The mirror copied dirname(package) with rsync -a, so it expanded
every link — a 488 GB package produced a second full copy instead of a
mirror. It now mirrors the store root with rsync -aH and only prunes a flat
package's dedicated directory (--delete on a store root would drop every
other prepared model). A $HOME-relative local_dir also stays expandable
(the shell quoting used to leave a literal $HOME).flare download carries no mirror marker, so every serve repeated
the 500 GB verification pass; the package is now resolved from
flare models list --json, and only when exactly one prepared version matches
<revision>-tp<N> (two candidates mean download — never guess, a wrong pick
serves the wrong model silently).weights/ at the mirror root).serve/stop honour the pinned FLARE controller. [flare.clusters.<c>]
.controller_node (or the flat [flare].controller_node) now decides which
node runs flare download / orbit run, instead of always our cluster rank 0.
The two diverge as soon as the orbit is re-paired or reordered — dgx4 became
the orbit's rank 0 for prod4 because its 2 TB disk is the only one that
holds the 488 GB package store plus the 488 GB agent cache, and the old
behaviour reached the wrong machine, failing with
"… is not an authorized controller of this node".orbit_nodes lists
the orbit's ranks in the orbit's order (gx10-dgx4 first when dgx4 is the
orbit's rank 0), so indexing it with our rank named the wrong node
(gx10-dgx3 for a dgx4 controller). A list that does not name our nodes
keeps the positional fallback.specs/tech-architecture/flare-bringup.md
("Package distribution: CLI store vs agent cache").io.containerd.snapshotter.v1), whose docker load
returns before the rootfs snapshot is materialized — a docker run issued
seconds after the sync can die with "unable to start container process …
stat …: no such file" (dgx3 lost exactly that race on the first Mistral
Large 4 serve: rank 2 died silently, --rm removed the evidence, and the
rendezvous hung until its 30-min timeout). The sync now probes exec
readiness on each peer (a trivial /bin/sh container start, retried up to
2 min) before declaring the sync done; a serve refuses to launch against a
half-materialized image.docker run no longer races the
image sync's last hop — sync-image OK now means exec-ready, not just
digest-present.health
and the dashboard only need to know whether the switch is reachable; the
RouterOS login was unnecessary API load. power off still logs in and sends
/system/shutdown.GET /api/bench/log follows the
recipe's newest bench job and only accepts a log written at/after its start;
a previous campaign is labelled previous, and a fresh launch shows
waiting instead of a stale log.j<hex> ids, and finish_job updates the still-running job with that id,
not an older finished one.run_tool always appends; bench::run truncates
the log once and writes launcher progress notes, so the dashboard window sees
readiness/notes and the depth suite shares one report log.ssh -tt avoids the "Pseudo-terminal will not
be allocated" path when the launcher has no terminal.flare orbit status
rows carry the orbit node and rank; the probe/health fold one pseudo-container
onto each rank node, not just the controller. A 4-rank FLARE serve now
shows 4 busy nodes and free 0, not one busy node and three idle.all8/pair12 too because those
paired clusters share nodes; the lane is owned by the cluster whose node count
and the recipe's required_nodes match the group's rank rows. Duplicate
pseudo-containers on a shared node are collapsed by (node, group).engine = "flare" and stream
flare orbit attach <group> --cluster <orbit> on the controller (not Docker
logs). The CLI does the same and prints both SSH stdout/stderr; run_ssh's
5 s inactivity timeout had killed the attach stream.GET /api/logs history and attach keys work for FLARE; the recipe-row ▤ logs
opens the controller's orbit session.⚡ bench button now opens a
bench window instead of firing the standard run blindly: choose recipe,
cluster, target node (node), run host (ssh_host, e.g. pluto.lan),
label, seed, concurrency, parallel, timeout, tokenizer, perf-only, depth and
no-think. The choices persist in localStorage (sm121-bench-params).GET /api/bench/log?recipe=… tail-reads the newest
bench log for the recipe; the window polls it while the run starts so early
failures (readiness, tokenizer, harness) are visible before a long wait.POST /api/bench/cancel sets the job's cancellation flag;
run_tool polls it and kills the tool-eval-bench child (also the SSH child
for remote runs), so the job finishes failed and the log stops.bench…, and the last recipe/job is restored on reload.node, seed, concurrency, parallel, timeout,
tokenizer, no_think; the report row's bench button posts to the parent
dashboard and opens the window.[flare.clusters.<our-cluster>]). The flat
orbit_cluster is a fallback for serve, not for the dashboard/health: our
clusters share nodes (dgx1 is rank 0 of prod4, 6nodes-switch, 2nodes-dac,
qwen38 and 1node-1), so probing an unpaired cluster with sparks made the
sparks lane look like that cluster's lane. serve now refuses an unpaired
FLARE cluster instead of silently launching onto the flat default.◆ prod4 badge
(orbit + controller + live groups; dimmed when nothing runs), and the topology
frame/chip labels include the orbit. health folds only the selected cluster's
lane, not every lane that shares its controller..sm121-flare-package.json (repo, revision, TP, package version,
local model.safetensors). A serve with a matching marker — checked against
the CURRENT flare models list --json version, so a lab re-cut under the same
revision is detected — skips both flare download verification and the
500 GB copy.rsync. The local mirror uses
rsync -a --delete (marker excluded), so a changed/stale package copies only
the changed files; a partial mirror resumes instead of being wiped and
re-copied. Download/mirror/orbit launch all use long-running SSH (the 5 s
inactivity timeout used to kill a 500 GB copy or a detached launch).POST /api/settings/extra/check validates without
writing; parse errors report line/column for the textarea; Ctrl+Enter
saves. The private block stays in /data/config-extra.toml, edited in the
dashboard's settings window.flare download now resolves the prepared package through
flare models list --json instead of failing on the metadata-only
"Resolved package" line.flare download gets --tensor-parallel from the recipe's launch
size; a TP4 package is no longer rejected as "TP size 1".weights/ and deployments/ companions; it clears the destination first
and runs over a long-lived SSH session (read-only package files and a 500 GB
copy must not be killed by the 5 s inactivity timeout).flare download and flare orbit run also use long-running SSH, so
a cached-package verification or a detached launch is not cut short.serve records the recipe directory name, not the display
name field — the old recipe.name lookup failed with
recipe dir not found for 'DeepSeek-V4.1-Flash-1017 (…) '.gb10: production recipe updated to the 2026-10-27 package
(c32, 1 GiB row cache, resident scales, --served-model-name).sm121 installed with cargo install --path . --force; version
now follows Cargo.toml, not a hard-coded 0.1.0.