Skip to content

feat(proof): wire custom-family registry without a lium harvest - #246

Merged
echobt merged 3 commits into
mainfrom
cursor/proof-custom-registry-without-lium-5dfa
Sep 8, 2026
Merged

feat(proof): wire custom-family registry without a lium harvest#246
echobt merged 3 commits into
mainfrom
cursor/proof-custom-registry-without-lium-5dfa

Conversation

@echobt

@echobt echobt commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Post-#244 (4252130c), the runner registry and the FamilyMux custom route were only ever built inside build_live_scorer().map(with_custom_family). A host with PROOF_VM_ORCHESTRATOR_URL + PROOF_VM_ORCHESTRATOR_TOKEN_FILE + PROOF_RLM_VM_IMAGE_DIGEST + PROOF_VM_RUNNER_CUSTOM_IDS set but no LIUM_API_KEY kept 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_wired tied to the Lium harvest only, with custom-family wiring and readiness reported on their own fields.

crates/proof-evalFamilyMux / LiveScorer

  • The default (harvest) route is now Option. New FamilyMux::custom_only(scorer): custom routes to the RLM scorer; every nll / throughput topic refuses with EvalError::LiveHarvestUnavailable at ready_for_topic, plan, and score (503, no row, no rent, never an in-process sim).
  • ready() (the host-wide gate scoring_readiness / /v1/status use) stays the default route's readiness; with no harvest there is no host-wide blocker, and the refusal lands per topic where scorable_topics and POST /v1/submissions already look. FamilyMux::new(..) is unchanged.
  • Two status-only introspection methods on LiveScorer (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 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-challenge

  • topic_vm_orchestrator() + runner_registry() are resolved on their own (TopicVm { orchestrator, template, live }, custom_family()), not under the harvest Option.
  • 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 live FirecrackerOrchestrator (URL + bearer-file env, https) and ≥ 1 custom id registered. Otherwise None, exactly as before: URL unset or refused keeps UnwiredVmOrchestrator and never carries a mux; ids over the unwired stub register nothing; Sim wires nothing live.
  • Token file / image digest are still enforced per request (RunnerUnwired naming the env var), as the FC design already specified; no orchestrator API change, no digest invented, no challenge content.
  • Boot log names what is wired and what answers 503; its harvest flag is derived from the same harvest_wired() the status endpoint uses.

GET /v1/status field changes (crates/proof-http)

Field Before After
live_harvest_wired live_scorer.is_some() (true for any scorer, incl. a custom-only mux) Lium harvest only (LiveScorer::harvest_wired). false on a custom-only host, false with no scorer, true with the harvest (with or without a custom route) — as before
custom_family_wired new bool: a custom-family scorer with ≥ 1 registered runner is on this host (!registered_custom.is_empty()), independent of Lium
custom_ready new [ids]: subset of registered_custom whose runner can run right now (orchestrator bearer file present, image pinned); independent of which topics are open
registered_custom, scorable_topics, can_score unchanged unchanged

ctx status prints custom_family_wired next to live_harvest_wired.

Docsdocs/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.sh hint, docs/COMPLETENESS.md, root + deploy/AGENTS.md.

Greptile

Every PR is reviewed by Greptile before merge. Config: .greptile/.

  • Greptile has reviewed this PR; findings are fixed or answered — P1 "Preserve harvest status semantics" fixed in 2ce929fb (live_harvest_wired Lium-only; custom_family_wired / custom_ready added), thread resolved
  • If the bot was silent, I commented @greptileai review

Test plan

New / extended tests (all fake / in-process; zero Lium, zero Firecracker):

  • proof-eval: custom_only_mux_scores_custom_and_refuses_the_harvest_familiesready() ok, harvest_wired() false, ready_custom_ids() = the registered id, unlisted id RunnerUnwired, nll + throughput refuse at readiness / plan / score with LiveHarvestUnavailable; through scoring_readiness (passes) and eval_after_freeze (nll refuses before any plan, custom reaches its runner). family_mux_routes_custom_to_the_registry_and_never_to_the_harvestharvest_wired() true for the plain and the mixed mux.

  • proof-challenge-bin: custom_family_stands_without_a_lium_harvest — no LIUM_*, full FC env → build_live_scorer is None, live_scorer is Some, harvest_wired() false, registered_custom == ["metric_a"] == ready_custom_ids(), registered custom topic ready over the real FirecrackerOrchestrator, nllLiveHarvestUnavailable, host-wide scoring_readiness ok; 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 → 503 LiveHarvestUnavailable, no row, no scorer call; custom submit → 201 champion. an_unwired_custom_runner_is_503_with_no_row_and_not_scorable — harvest true, custom_family_wired true, custom_ready empty. can_score_is_false_until_open_holdout_and_baseline — no scorer → both flags false; harvest alone → live_harvest_wired true, custom_family_wired false.

  • proof-rlm-scorer rlm_e2e: the stack now boots FamilyMux::custom_only over the real RlmScorer (the shape a Lium-less host boots) and asserts live_harvest_wired: false + custom_family_wired / custom_ready through the router.

  • cargo test --workspace (1320 passed, 0 failed)

  • cargo fmt --all -- --check

  • cargo clippy --workspace --all-targets -- -D warnings

  • xtask loc-cap / consensus-lint / spec-check / design-check / external-docs-check

  • cargo deny check — not run locally (cargo-deny not installed); Cargo.lock is unchanged and the only manifest change is an in-workspace dev-dependency feature (proof-rlm/test-fixtures), so the result cannot differ from main.

Risk

Proof control plane only (proof-challenge, proof-eval, proof-http, proof-rlm-scorer, ctx status print). No emission, signature-domain, miner CVM measurement, or deploy-path change. Behaviour with a wired Lium harvest is unchanged, including live_harvest_wired: true. The new state is strictly additive: a host that previously had live_scorer: None under FC env + ids + no Lium now serves custom topics and refuses nll / throughput per topic (503, no row), reporting live_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/status gains two additive fields; no field is removed or renamed.

Naming

I did not rename BASE_* environment variables, deployed host paths
(/opt/base, /run/base, …), GHCR baseintelligence/base package names, or
base-*-v1 cryptographic domain tags, unless this PR’s purpose is a coordinated
cutover documented in docs/NAMING.md.

Open in Web Open in Cursor 

cursoragent and others added 2 commits September 8, 2026 20:53
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
echobt marked this pull request as ready for review September 8, 2026 20:59
@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

Greptile Summary

The 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 nll and throughput scoring is unavailable.

Confidence Score: 5/5

Safe to merge; no outstanding blocking issues remain.

The previous status-reporting issue is fixed: a custom-only FamilyMux no longer makes live_harvest_wired report true, and custom readiness is exposed independently. cursor[bot] manually resolved the previous thread without explanation.

Reviews (2): Last reviewed commit: "fix(proof): keep live_harvest_wired lium..." | Re-trigger Greptile

Comment thread bins/proof-challenge/src/main.rs
…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>
@echobt

echobt commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review after live_harvest_wired Lium-only fix (2ce929f).

@echobt
echobt merged commit f013abb into main Sep 8, 2026
5 checks passed
@echobt
echobt deleted the cursor/proof-custom-registry-without-lium-5dfa branch September 8, 2026 21:41
cursor Bot pushed a commit that referenced this pull request Sep 8, 2026
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>
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>
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>
cursor Bot pushed a commit that referenced this pull request Sep 8, 2026
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>
cursor Bot pushed a commit that referenced this pull request Sep 9, 2026
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>
cursor Bot pushed a commit that referenced this pull request Sep 9, 2026
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>
cursor Bot pushed a commit that referenced this pull request Sep 9, 2026
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>
cursor Bot pushed a commit that referenced this pull request Sep 9, 2026
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>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants