feat(proof): wire custom-family registry without a lium harvest - #246
Merged
Conversation
The runner registry and the FamilyMux custom route were only built inside build_live_scorer().map(with_custom_family), so a host with the topic-VM orchestrator and PROOF_VM_RUNNER_CUSTOM_IDS set but no LIUM_API_KEY kept every custom topic unwired and needed a placeholder Lium harvest to open them. - FamilyMux: the default (harvest) route is optional. FamilyMux::custom_only routes custom to the RLM scorer and refuses every nll / throughput topic at readiness, plan, and score with LiveHarvestUnavailable (503, no row, no rent). ready() stays the default route's readiness; with no harvest there is no host-wide blocker and the refusal lands per topic. - proof-challenge: the topic-VM orchestrator + registry are resolved on their own; with a harvest the mux routes both families (unchanged); with none, a live FirecrackerOrchestrator selected by env plus >= 1 registered id installs the custom-only mux. Env unset or refused (UnwiredVmOrchestrator), no id, or Sim keeps live_scorer None, so the host stays fail-closed exactly as before. - Tests: no Lium + full FC env -> registry non-empty, host-wide gate passes, registered custom topic ready, nll/unlisted ids refuse; env unset / ids over the unwired stub / refused URL / no id -> None -> LiveHarvestUnavailable; HTTP: custom-only host scores the custom topic, a throughput submit is 503 with no row and no scorer call. Co-authored-by: Mathis <echobt@users.noreply.github.com>
State in the operator spec, miner status table, KVM-host runbook, env example, completeness sheet, and both AGENTS contracts that the custom runner registry stands without a Lium harvest (custom scores, nll / throughput 503), what live_harvest_wired now means, and that a placeholder Lium key must not be staged to open custom topics. Co-authored-by: Mathis <echobt@users.noreply.github.com>
echobt
marked this pull request as ready for review
September 8, 2026 20:59
Greptile SummaryThe custom-family wiring fix keeps Lium harvest availability separate from custom topic-VM availability. A custom-only host can serve registered custom topics while accurately reporting that Lium-backed Confidence Score: 5/5Safe to merge; no outstanding blocking issues remain. The previous status-reporting issue is fixed: a custom-only Reviews (2): Last reviewed commit: "fix(proof): keep live_harvest_wired lium..." | Re-trigger Greptile |
…part Greptile P1 on #246: on a custom-only host the status endpoint treated any live_scorer as a wired Lium harvest and reported live_harvest_wired: true while nll / throughput submissions were refused with 503. - LiveScorer gains two status-only introspection methods (never gates): harvest_wired() — default true (the handle is the harvest), RlmScorer false, FamilyMux answers for its default route only, so a custom_only mux is never harvest-wired; ready_custom_ids() — registered custom ids whose runner reports ready (RlmScorer: local orchestrator bearer file + image pin checks, no request leaves the host). - /v1/status: live_harvest_wired = Lium harvest only. New custom_family_wired (a custom-family scorer with >= 1 registered runner) and custom_ready (subset of registered_custom that can run now). registered_custom / scorable_topics unchanged. The proof-challenge boot log derives its harvest flag from the same method. - ctx status prints custom_family_wired next to live_harvest_wired. - Tests: custom-only host -> live_harvest_wired false, custom_family_wired true, custom_ready = the id (proof-http stub, proof-challenge bin with the real FirecrackerOrchestrator + RlmScorer, rlm_e2e stack now boots FamilyMux::custom_only like a Lium-less host); Lium harvest present -> true as before, with and without a custom route; no scorer -> both false; registered-but-unwired runner -> wired true, custom_ready empty; emptied bearer file drops the id from ready but not from registered. - Docs: PROOF.md, external-miner status table, KVM-host runbook, env example, operator script hint, COMPLETENESS, both AGENTS contracts. Co-authored-by: Mathis <echobt@users.noreply.github.com>
Contributor
Author
|
@greptileai please re-review after live_harvest_wired Lium-only fix (2ce929f). |
8 tasks
cursor Bot
pushed a commit
that referenced
this pull request
Sep 8, 2026
…ready, not lium After #246 the custom family is wired from the topic-VM env alone and `live_harvest_wired` is the Lium harvest only (nll / throughput), so a custom-only host reads false by design. The harness `cp` step no longer FAILs on it: the flag is logged as informational, and the custom family is gated on `custom_family_wired` (FAIL when ids are set but the family is not routed), `registered_custom` ⊇ ids, and `custom_ready` ⊇ ids (registered but not ready = bearer file / image pin on this host). The admin probe log line shows the same three fields. `VmOrchestratorReport` carries `custom_family_wired` next to `registered_custom`, and its `live_harvest_wired` is the host's Lium-only answer. Runbook (§ Wire the control plane, admin-probe field table, § 0 preconditions, § 3 cp row), the CP staging overlay, docs/PROOF.md, and docs/COMPLETENESS.md say the same. Verified against a custom-only loopback proof-challenge wired to a loopback agent: custom gates PASS with live_harvest_wired=false logged, not failed. Co-authored-by: Mathis <echobt@users.noreply.github.com>
9 tasks
echobt
added a commit
that referenced
this pull request
Sep 8, 2026
* feat(proof): admin probe for the topic-vm orchestrator wire
GET /v1/admin/proof/vm-orchestrator (operator bearer, read-only, no VM,
no spend) reports what proof-challenge resolved for the topic-VM
orchestrator and whether the KVM-host agent answers, through the very
client the runner drives: `ready()` (bearer file present, RLM image
pinned — re-read now), the locked template, one agent health call, and
the host's own gates (live_harvest_wired, registered_custom). A broken
wire is data, not an error: bearer refused, agent unreachable, digest
unpinned, and URL unset each show up by name so a staging operator can
prove the wire without cargo on the droplet. Never the bearer value.
proof-challenge resolves the orchestrator once per process and shares
the Arc between the runner registry and the probe; the registry is
still built only over a wired harvest, so log lines are unchanged.
Tests: route is 401 / 503 auth_unconfigured / 200; unwired hosts name
the env vars; against the in-process fake agent the report shows ready
+ fake hypervisor, then a bearer rotated on one side, a stopped agent,
and an emptied bearer file, each as data.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* feat(deploy): proof-vm-wire-check.sh staging harness + fake-agent test
Operator harness for the Proof topic-VM wire on the staging master
droplet: bash + curl + python3, no cargo, bearer only ever in a 0600
curl config, production hosts refused.
env CP env file: https URL (loopback http = WARN), bearer
file non-empty via --path-map (compose bind mount), RLM
image pin is sha256:<64 hex> (empty = FAIL, never
invented), optional CA is PEM, custom ids well-formed,
locked 4/8192 shape, PROOF_FORCE_SIM off
agent GET /v1/health with the bearer (ready / reason /
hypervisor / vms); no bearer and wrong bearer → 401
cp /v1/status gates (lium, live_harvest_wired,
registered_custom ⊇ ids), no URL / token / path leak,
/v1/proof/topics holdout leak, executor readiness, and
the admin vm-orchestrator probe (the CP's own rustls
client: ready, agent health, agent_error)
boot-probe create → attach → 409 → 409 topic_mismatch → destroy →
404 for ONE RLM VM (no job, no spend); Ctrl-C tears
the VM down
submit-probe POST /v1/submissions on a custom topic asserting the
fail-closed code + reason; 2xx refused without
--allow-live-run; a scored row must carry the
sister-measured flops_used
matrix the fail-closed flips with the expected 503 reasons
Integration test (proof-vm-fc, fake agent on loopback, skipped without
bash/curl/python3): env / agent / boot-probe speak the router's JSON,
the bearer never appears in the output, one boot + one Destroy, a dead
agent fails the check; unpinned digest and an emptied bearer file fail
closed.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* fix(proof-vm-fc): keep the agent url out of the unreachable error
`orchestrator unreachable (...)` travels into the miner-facing 503 body
when the KVM-host agent is down; reqwest's Display would print the
agent's URL with it. Keep the method + route, strip the URL
(`Error::without_url`). Test asserts the route stays and the address
does not.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* docs(deploy): staging env overlays for the proof topic-vm wire
deploy/env/proof-challenge.staging-vm.example: the client-side keys to
append to proof-challenge.env on the staging master (https agent URL
on the VPC, bearer file, private CA, RLM image pin, locked 4/8192
shape, custom ids, admin tokens file).
deploy/env/proof-vm-orchestrator.staging.example: /etc/proof-vm/
orchestrator.env for the dedicated KVM host serving staging (private
bind + TLS, bearer file, kernel + sister pins, sizes, egress allowlist
for the judge origin / artefact hosts / resolver).
Placeholders only, and every REPLACE_WITH_* value fails closed as
written: the wire check flags each one, proof-challenge stays unwired
or answers 503, the agent refuses to boot. No digest is real.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* feat(deploy): wire-check submit-probe --no-artifact-uri for the 400 row
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* docs(runbook): proof topic-vm orchestrator — digitalocean staging wire + probes
New § DigitalOcean staging: the CP stays on the existing staging master
droplet; the agent needs a KVM host with /dev/kvm — a DO Droplet is not
one (no nested virtualisation; the unit's ConditionPathExists refuses by
design; no nested-FC workaround), so use DO bare-metal / dedicated
hardware or any bare-metal KVM host on the staging VPC / private
network, private bind, TLS + bearer. Host pre-checks, per-topic budget,
CP preconditions (lium, live_harvest_wired, judge, executor, a signed
custom topic with a sealed baseline), KVM-host and CP steps with the
staging env overlays, the wire check (env / agent / cp / boot-probe),
the fail-closed matrix (flip → restart? → expected 503 reason → what
the admin probe shows), the happy path with the exact log lines and
row / artefact evidence (sister sandboxed + flops_used, evidence bind,
destroy teardown), a sign-off checklist that records unknown / not run
rather than a green box, and rollback.
§ Wire the control plane documents GET /v1/admin/proof/vm-orchestrator
(field → root cause table; loopback only — staging's public API is
cleartext). Operate table gains "Is the wire up?".
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* docs: point operators at the proof topic-vm staging harness
AGENTS.md verification item 7, deploy/AGENTS.md (staging wire section),
docs/AGENTS.md runbook index, docs/PROOF.md HTTP surface (the admin
vm-orchestrator probe), deploy/secrets/README.md (admin_tokens now also
gates the probe), docs/COMPLETENESS.md (probe + harness + overlays;
still not on any host, sign-off unfilled).
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* test(proof-rlm-scorer): rlm_e2e app state carries vm_probe
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* docs(runbook): staging may colocate the fc agent on the cp when /dev/kvm works
Architecte nit on #247: `cortex-staging` (nested DigitalOcean
virtualisation) did boot Firecracker and the § 4 fail-closed matrix came
back green, so the runbook must not claim a Droplet can never be the KVM
host. Corrected wording everywhere the PR (and the #244 lines next to
it) said so:
- staging may colocate the agent on the control-plane droplet when
/dev/kvm works — validated on cortex-staging;
- production prefers a dedicated DO bare-metal / KVM host;
- nested KVM remains fragile — if the boot fails or /dev/kvm goes away,
provision metal, do not patch around it (fragility signs listed);
- never Lium, never an emulator, never without /dev/kvm.
Runbook § DigitalOcean staging gains the colocated specifics: the CP
container reaches the agent on the droplet's VPC address (loopback in
the container is the container; FcConfig accepts plain http on loopback
only), agent bound on that address with TLS + SAN, :8200 firewalled to
the compose network, sizing on top of the compose stack, a local
`install` of the bearer copy; sign-off records the placement. The
fail-closed probes, the matrix, and the harness are unchanged.
Same correction in AGENTS.md item 7, deploy/AGENTS.md, both staging
overlays, the generic env examples, the systemd unit comment,
docs/PROOF.md, docs/ARCHITECTURE.md, docs/COMPLETENESS.md (staging
boot + § 4 green recorded; § 5 / § 6 still to be recorded), and the
agent / binary module docs.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* docs(proof-vm): staging colo = allowed proven exception; prod = dedicated do metal
Architecte GO conditionnel on #247: one wording across every placement
statement (runbook, AGENTS.md item 7, deploy/AGENTS.md, both staging
overlays, the generic env examples, the systemd unit comment,
docs/PROOF.md, docs/ARCHITECTURE.md, docs/COMPLETENESS.md, agent and
binary module docs):
- staging: colocating the agent on the CP droplet with nested /dev/kvm
is an allowed exception, proven on cortex-staging (§ 4 green); nested
stays fragile — if the boot fails, provision metal;
- production: dedicated DO metal preferred — never colocated on the CP.
No "a Droplet is not one / no nested" claim remains. Fail-closed probes,
matrix, and harness unchanged.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* fix(deploy): wire-check — case-insensitive prod guard, strand-proof boot-probe, budget flops
Greptile on #247:
P1 production guard bypass: refuse_prod parsed nothing and matched the
URL case-sensitively, so https://NETWORK.CORTEX.FOUNDATION reached
authenticated create / submit requests. The guard now parses the host
(scheme, userinfo, port, path, query, trailing dot stripped; IPv6 kept
bracketed), lower-cases it, and refuses a protected host or any
subdomain of one, plus a case-insensitive whole-URL match as belt and
braces. It runs at env load, before any other check, on every probe.
P2 lost response strands VM: PROBE_TOPIC_LIVE is set before the create
goes out; a create whose answer is 000 / 5xx / unparseable is reconciled
through GET /v1/vms/by-topic and any VM the agent reports is destroyed
in line (probe_reconcile_destroy), and the EXIT trap does the same for
anything still in flight (Ctrl-C, unconfirmed teardown). Topic state is
cleared only after a confirmed destroy followed by a 404, so a retry on
the probe topic is never blocked. PROOF_VM_WIRE_CHECK_FAULT=
lose-create-answer is a test-only hook that drops the create's answer.
P1 live probe under-declares FLOPs: submit-probe declared 1, so a live
run measuring more was a flops_under_declared reject. Fail-closed probes
still send 1 (nothing runs); --expect 2xx declares the topic's
flops_budget read from GET /v1/proof/topics/<id> (--declared-flops N
overrides; unreadable budget = FAIL naming the flag).
Tests (fake agent): uppercase / userinfo / trailing-dot / subdomain
production origins exit 2 before any request, for submit-probe and for
the agent URL at env load; the lost-answer create boots one VM that is
found by topic and destroyed, the topic is free, a retry passes.
Runbook § 3 / § 5 updated.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* style(proof-vm-fc): rustfmt the wire-check script test
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* test(proof-vm-fc): split the lost-create reconcile probe into its own test
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* fix(deploy): wire-check gates custom on custom_family_wired / custom_ready, not lium
After #246 the custom family is wired from the topic-VM env alone and
`live_harvest_wired` is the Lium harvest only (nll / throughput), so a
custom-only host reads false by design. The harness `cp` step no longer
FAILs on it: the flag is logged as informational, and the custom family
is gated on `custom_family_wired` (FAIL when ids are set but the family
is not routed), `registered_custom` ⊇ ids, and `custom_ready` ⊇ ids
(registered but not ready = bearer file / image pin on this host). The
admin probe log line shows the same three fields.
`VmOrchestratorReport` carries `custom_family_wired` next to
`registered_custom`, and its `live_harvest_wired` is the host's Lium-only
answer. Runbook (§ Wire the control plane, admin-probe field table, § 0
preconditions, § 3 cp row), the CP staging overlay, docs/PROOF.md, and
docs/COMPLETENESS.md say the same. Verified against a custom-only
loopback proof-challenge wired to a loopback agent: custom gates PASS
with live_harvest_wired=false logged, not failed.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
* fix(deploy): wire-check refuses a zero declared_flops override
Greptile P2 on #247: `--declared-flops 0` passed the override check and
reached the control plane for a live probe, where any measured usage is
a flops_under_declared reject instead of the documented awaiting_admin
path. Explicit overrides must now be positive integers; zero, negative,
and non-numeric values exit 1 with an actionable message before any
request. Test covers 0 / abc / -1 on a live-run invocation.
Co-authored-by: Mathis <echobt@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Mathis <echobt@users.noreply.github.com>
echobt
added a commit
that referenced
this pull request
Sep 9, 2026
* deploy: staging pins for 4252130 images.yml built GHCR digests on main then could not push the pin commit (GH013: PRs required + Greptile). Land the same promote via PR. Co-authored-by: Mathis <echobt@users.noreply.github.com> * fix(deploy): keep full prior staging release in previous Sequential promote.sh calls were snapshotting previous per service, so rollback of 4252130 would restore a mixed pin set. Capture the 1dd07f7 release once and write it back after the promote loop. Co-authored-by: Mathis <echobt@users.noreply.github.com> * deploy: staging pins for f013abb Retarget #245: main moved to #246. Digests from images run 34281980177. previous stays the full 1dd07f7 staging release. Co-authored-by: Mathis <echobt@users.noreply.github.com> * deploy: staging pins for 890ce5b Retarget #245: main moved to #247. Digests from images run 34286333214. previous stays the full 1dd07f7 staging release. Co-authored-by: Mathis <echobt@users.noreply.github.com> * deploy: staging pins for c0ce094 Retarget #245: main moved through #248/#252. Digests from images run 34297422117. previous stays the full 1dd07f7 staging release. Co-authored-by: Mathis <echobt@users.noreply.github.com> * deploy: staging pins for 85ab2b7 Retarget #245: main moved to #251. Digests from images run 34299348722. previous stays the full 1dd07f7 staging release. Co-authored-by: Mathis <echobt@users.noreply.github.com> * deploy: staging pins for e30d51d Retarget #245: main moved to #250. Digests from images run 34302039784. previous stays the full 1dd07f7 staging release. Co-authored-by: Mathis <echobt@users.noreply.github.com> * deploy: staging pins for a8b9018 Retarget #245: main moved to #253. Digests from images run 34373475123. previous stays the full 1dd07f7 staging release. Co-authored-by: Mathis <echobt@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mathis <echobt@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Post-#244 (
4252130c), the runner registry and theFamilyMuxcustom route were only ever built insidebuild_live_scorer().map(with_custom_family). A host withPROOF_VM_ORCHESTRATOR_URL+PROOF_VM_ORCHESTRATOR_TOKEN_FILE+PROOF_RLM_VM_IMAGE_DIGEST+PROOF_VM_RUNNER_CUSTOM_IDSset but noLIUM_API_KEYkept every custom topic unwired (registered_custom: [], open custom topics could not even load), so the staging colo-VM path needed a placeholder Lium harvest just to open custom topics.This decouples the custom / FC registry from Lium harvest construction, and (per the Greptile P1 / architect lock) keeps
live_harvest_wiredtied to the Lium harvest only, with custom-family wiring and readiness reported on their own fields.crates/proof-eval—FamilyMux/LiveScorerOption. NewFamilyMux::custom_only(scorer):customroutes to the RLM scorer; everynll/throughputtopic refuses withEvalError::LiveHarvestUnavailableatready_for_topic,plan, andscore(503, no row, no rent, never an in-process sim).ready()(the host-wide gatescoring_readiness//v1/statususe) stays the default route's readiness; with no harvest there is no host-wide blocker, and the refusal lands per topic wherescorable_topicsandPOST /v1/submissionsalready look.FamilyMux::new(..)is unchanged.LiveScorer(never gates):harvest_wired()— defaulttrue(the handle is the harvest),RlmScorerfalse,FamilyMuxanswers for its default route only, so a custom-only mux never reads as harvest-wired;ready_custom_ids()— registered custom ids whose runner reports ready right now (RlmScorer: local bearer-file + image-pin checks, no request leaves the host).bins/proof-challengetopic_vm_orchestrator()+runner_registry()are resolved on their own (TopicVm { orchestrator, template, live },custom_family()), not under the harvestOption.live_scorer(): with a Lium harvest →FamilyMux::new(harvest).with_custom_family(rlm)(unchanged behaviour). With none →FamilyMux::custom_only(rlm)only when the env selected the liveFirecrackerOrchestrator(URL + bearer-file env, https) and ≥ 1 custom id registered. OtherwiseNone, exactly as before: URL unset or refused keepsUnwiredVmOrchestratorand never carries a mux; ids over the unwired stub register nothing; Sim wires nothing live.RunnerUnwirednaming the env var), as the FC design already specified; no orchestrator API change, no digest invented, no challenge content.harvest_wired()the status endpoint uses.GET /v1/statusfield changes (crates/proof-http)live_harvest_wiredlive_scorer.is_some()(true for any scorer, incl. a custom-only mux)LiveScorer::harvest_wired).falseon a custom-only host,falsewith no scorer,truewith the harvest (with or without a custom route) — as beforecustom_family_wiredbool: a custom-family scorer with ≥ 1 registered runner is on this host (!registered_custom.is_empty()), independent of Liumcustom_ready[ids]: subset ofregistered_customwhose runner can run right now (orchestrator bearer file present, image pinned); independent of which topics are openregistered_custom,scorable_topics,can_scorectx statusprintscustom_family_wirednext tolive_harvest_wired.Docs —
docs/PROOF.md(runner registry,/v1/status, submit 503 list),docs/external-miner/proof.md(status table + field lists),docs/runbooks/proof-vm-orchestrator.md(CP wiring: Lium is not a prerequisite; what status reads),deploy/env/proof-challenge.env.example,deploy/scripts/proof-operator-path.shhint,docs/COMPLETENESS.md, root +deploy/AGENTS.md.Greptile
Every PR is reviewed by Greptile before merge. Config:
.greptile/.2ce929fb(live_harvest_wiredLium-only;custom_family_wired/custom_readyadded), thread resolved@greptileai reviewTest plan
New / extended tests (all fake / in-process; zero Lium, zero Firecracker):
proof-eval:custom_only_mux_scores_custom_and_refuses_the_harvest_families—ready()ok,harvest_wired()false,ready_custom_ids()= the registered id, unlisted idRunnerUnwired,nll+throughputrefuse at readiness / plan / score withLiveHarvestUnavailable; throughscoring_readiness(passes) andeval_after_freeze(nllrefuses before any plan, custom reaches its runner).family_mux_routes_custom_to_the_registry_and_never_to_the_harvest—harvest_wired()true for the plain and the mixed mux.proof-challenge-bin:custom_family_stands_without_a_lium_harvest— noLIUM_*, full FC env →build_live_scorerisNone,live_scorerisSome,harvest_wired()false,registered_custom == ["metric_a"] == ready_custom_ids(), registered custom topic ready over the realFirecrackerOrchestrator,nll→LiveHarvestUnavailable, host-widescoring_readinessok; emptied bearer file keeps the id registered but not ready; Sim →None.without_lium_the_custom_family_needs_the_live_orchestrator_and_an_id— env unset / ids over the unwired stub / refused URL / no id →None→ 503. Lium-wired mux →harvest_wired()true.proof-http:a_custom_only_host_scores_custom_and_refuses_the_harvest_families— status:live_harvest_wired: false,custom_family_wired: true,custom_ready: ["topic_minted_metric"], only the custom topic scorable,can_score: true; throughput submit → 503LiveHarvestUnavailable, no row, no scorer call; custom submit → 201champion.an_unwired_custom_runner_is_503_with_no_row_and_not_scorable— harvest true,custom_family_wiredtrue,custom_readyempty.can_score_is_false_until_open_holdout_and_baseline— no scorer → both flags false; harvest alone →live_harvest_wiredtrue,custom_family_wiredfalse.proof-rlm-scorerrlm_e2e: the stack now bootsFamilyMux::custom_onlyover the realRlmScorer(the shape a Lium-less host boots) and assertslive_harvest_wired: false+custom_family_wired/custom_readythrough the router.cargo test --workspace(1320 passed, 0 failed)cargo fmt --all -- --checkcargo clippy --workspace --all-targets -- -D warningsxtask loc-cap/consensus-lint/spec-check/design-check/external-docs-checkcargo deny check— not run locally (cargo-deny not installed);Cargo.lockis unchanged and the only manifest change is an in-workspace dev-dependency feature (proof-rlm/test-fixtures), so the result cannot differ frommain.Risk
Proof control plane only (
proof-challenge,proof-eval,proof-http,proof-rlm-scorer,ctxstatus print). No emission, signature-domain, miner CVM measurement, or deploy-path change. Behaviour with a wired Lium harvest is unchanged, includinglive_harvest_wired: true. The new state is strictly additive: a host that previously hadlive_scorer: Noneunder FC env + ids + no Lium now serves custom topics and refusesnll/throughputper topic (503, no row), reportinglive_harvest_wired: false/custom_family_wired: true; every previously fail-closed case (env unset, refused URL, no id, unpinned digest, empty token file, Sim) still fails closed./v1/statusgains two additive fields; no field is removed or renamed.Naming
I did not rename
BASE_*environment variables, deployed host paths(
/opt/base,/run/base, …), GHCRbaseintelligence/basepackage names, orbase-*-v1cryptographic domain tags, unless this PR’s purpose is a coordinatedcutover documented in
docs/NAMING.md.