feat: an optional lane says it is optional, and what enabling it costs (4296)
Build images / sign-extension (push) Successful in 3s
CI / lint (push) Successful in 2s
Build images / build-agent (push) Successful in 5s
CI / extension-version (push) Successful in 2s
CI / frontend-build (push) Successful in 23s
CI / backend-lint-and-test (push) Successful in 31s
Build images / build-web (push) Successful in 1m21s
Build images / smoke-web (push) Skipped
Build images / build-ml (push) Successful in 2m12s
Build images / promote (push) Skipped
CI / integration (push) Successful in 2m39s
Build images / sign-extension (push) Successful in 3s
CI / lint (push) Successful in 2s
Build images / build-agent (push) Successful in 5s
CI / extension-version (push) Successful in 2s
CI / frontend-build (push) Successful in 23s
CI / backend-lint-and-test (push) Successful in 31s
Build images / build-web (push) Successful in 1m21s
Build images / smoke-web (push) Skipped
Build images / build-ml (push) Successful in 2m12s
Build images / promote (push) Skipped
CI / integration (push) Successful in 2m39s
Operator, 2026-09-22: "since the ml-worker is optional it should be shown as such in the UI and have a warning about what it does and that it pulls the models and what models and their projected size and ram requirements to run." The card previously said "a few GB, once" — a number sourced from nothing, which is exactly the hand-wave I had flagged in this step's own survey log as something that should be measured rather than asserted. ONE FACT CORRECTED WHILE WRITING THE COPY. I had named the lane "ML tagging". It downloads an EMBEDDER: google/siglip-so400m-patch14-384. WD14 tagging is the GPU agent's job — celery_app.py:5 still names both, but that has been stale since B3 (#1238), when the agent took over and this lane was left as the CPU embed fallback for stacks running no agent (see MLSettings.cpu_embed_enabled). Telling someone the lane "does tagging" would have been wrong in exactly the way this request exists to prevent. The facts are structured data on the lane, not prose in a component: ModelRequirement(repo, approx_download_bytes, approx_resident_bytes, measured). The API carries them; the card renders them. Numbers come from the system, wording from the UI. ML_BYTES_PER_SLOT IS NOW DERIVED from that requirement rather than stated separately. They have to be one number: the figure quoted to the operator before they enable the lane and the figure the cap enforces. Two copies could disagree, and the UI would promise a slot the cap then refuses. `measured=False` travels with the numbers and the card renders "about". They are estimates from the checkpoint's parameter count and dtype — ~877M params at fp32 is ~3.5GB of weights — not from a build. This decides whether someone's server survives, so it is labelled rather than rounded into something that reads like a fact. A test asserts the flag is false, to be flipped in the same commit that records a real measurement. The card now shows: an "optional" chip in the row itself (someone scanning the table should not have to enable a lane to learn it was never required), and before the switch, what the lane does, that you only need it if you are NOT running the GPU agent, the repo id, the download size, the per-slot RAM, and why the ceiling is what it is — including saying plainly when a box has too little memory to run it at all. Keyed on the lane's own `optional` flag, not on the name 'ml', so a second optional lane gets the same treatment without anyone remembering to add it. A test asserts no REQUIRED lane declares a model: if one ever needs a download, it stops being required. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
This commit is contained in:
@@ -266,3 +266,44 @@ def test_worker_lane_check_constraints(slots, cap, ok):
|
||||
# documents what is accepted rather than restating the SQL.
|
||||
satisfied = slots >= 0 and cap >= 0 and slots <= cap
|
||||
assert satisfied is ok
|
||||
|
||||
|
||||
# --- what an optional lane tells the operator before it is enabled -----------
|
||||
|
||||
|
||||
def test_the_ml_lane_is_marked_optional_and_declares_its_model():
|
||||
"""The operator's ask, 2026-09-22: an optional lane must SAY it is
|
||||
optional, and say what enabling it downloads — which model, how big, and
|
||||
what it costs to hold — before the switch is thrown rather than after a
|
||||
multi-GB fetch has begun."""
|
||||
ml = wl.LANES_BY_NAME["ml"]
|
||||
assert ml.optional is True
|
||||
assert len(ml.models) == 1
|
||||
assert ml.models[0].repo == "google/siglip-so400m-patch14-384"
|
||||
assert ml.models[0].approx_download_bytes > 0
|
||||
assert ml.models[0].approx_resident_bytes > 0
|
||||
|
||||
|
||||
def test_no_required_lane_claims_a_model():
|
||||
"""A lane the product cannot work without must not be gated behind a
|
||||
download. If one ever needs a model, it stops being required."""
|
||||
for lane in wl.LANES:
|
||||
if lane.models:
|
||||
assert lane.optional, f"{lane.name} needs a model but is not optional"
|
||||
|
||||
|
||||
def test_the_per_slot_ceiling_is_the_same_number_the_ui_shows():
|
||||
"""DERIVED, not restated. The figure quoted to the operator before they
|
||||
enable the lane and the figure the cap enforces have to be one number, or
|
||||
the UI promises a slot the cap will then refuse."""
|
||||
ml = wl.LANES_BY_NAME["ml"]
|
||||
assert wl.ML_BYTES_PER_SLOT == ml.models[0].approx_resident_bytes
|
||||
|
||||
|
||||
def test_estimated_numbers_are_flagged_as_estimates():
|
||||
"""`measured` travels with the figures so the card can say "about". An
|
||||
estimate presented as a measurement is what decides whether someone's
|
||||
server survives — it must not be rounded into something that reads like a
|
||||
fact. Flip this to True in the same commit that records a real
|
||||
measurement."""
|
||||
assert wl.SIGLIP_MODEL.measured is False
|
||||
|
||||
Reference in New Issue
Block a user