Skip to content

feat(proof): one Firecracker experiment VM per paid job with a generic in-guest runner - #253

Merged
echobt merged 15 commits into
mainfrom
cursor/in-guest-experiment-vms-37ce
Sep 9, 2026
Merged

feat(proof): one Firecracker experiment VM per paid job with a generic in-guest runner#253
echobt merged 15 commits into
mainfrom
cursor/in-guest-experiment-vms-37ce

Conversation

@echobt

@echobt echobt commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Architecte RELOCK C, generalist form: topics whose signed constraints.params select an in-guest runner get one dedicated Firecracker microVM per Baseline / Evaluate job — created for the job, sized by the topic's ask under a hard operator lock, fed the topic-pinned experiment pack over vsock, run by an operator adaptor baked into the guest image, attested by the host as experiment_vm, destroyed afterwards — and scored only once the orchestrator confirms that VM destroyed. Parallel experiments are parallel VMs, never containers sharing one VM. Path B (vsock → host harness) is not implemented. Rootless podman inside the guest is the accepted C (not Docker-in-VM).

Nothing benchmark-, dataset-, harness-, adaptor-, or pack-specific is compiled in or committed. The words that select the path are generic knobs whose values are topic data:

constraints.params role
baseline_runner (synonym in_guest_benchmark_runner) operator adaptor id under /opt/proof/runners/<id>/ (e.g. operator_adaptor_v0) — the adaptor itself lives outside git
experiment_pack_digest (+ optional experiment_pack_path) sha256: of the pack tar the KVM host stages; required with a runner, never defaulted
experiment_vcpus / experiment_mem_mib / experiment_disk_mib the topic's ask, held under the caps (over = 503, never clamped)
model_pin, every other param reach the adaptor as PROOF_MODEL_PIN / PROOF_PARAM_<KEY> (two signed names that collide after upper-casing / -_ are refused before anything runs)

Resource caps (Mathis LOCK — hard):

  • per-experiment VM 16 vCPU / 32 GiB RAMDEFAULT_EXPERIMENT_VCPUS=16, DEFAULT_EXPERIMENT_MEM_MIB=32768 (what a silent topic gets), DEFAULT_MAX_EXPERIMENT_VCPUS=16, DEFAULT_MAX_EXPERIMENT_MEM_MIB=32768 (the most a topic may ask for), and LOCK_MAX_EXPERIMENT_VCPUS=16 / LOCK_MAX_EXPERIMENT_MEM_MIB=32768 as compiled-in maxima: ExperimentCeilings::validate refuses any CP (PROOF_EXPERIMENT_VM_MAX_*) or host (PROOF_VM_AGENT_EXPERIMENT_MAX_*) ceiling above them so the process does not boot, and shape() / admit() refuse any VM shape above them whatever the ceilings say. A smaller host may only lower a ceiling — and lowering only the MAX knob is enough: an unset default follows it (a default set above its ceiling is refused, never clamped);
  • writable disk 32 GiB default (PROOF_EXPERIMENT_VM_DISK_MIB), 16 GiB floor, max raised by the operator when the metal has more (the disk ceiling is not locked);
  • PROOF_VM_AGENT_MAX_EXPERIMENT_VMS (default 2) caps how many run at once; the topic VM keeps its locked 4 / 8192;
  • rootfs bake target 1.5–2.5 GiB (budget check in the bake).

What changed

  • crates/proof-experiment (new): the binding parser (ExperimentBinding::from_params, fail-closed on a half selection), ExperimentCeilings (defaults + maxima + hard lock + disk floor) / VmShape::locked / ExperimentPolicy::from_env (an unset default follows a lowered ceiling; a set default above its ceiling is refused), wire ExperimentSpec.
  • proof-vm-proto: HostToRlm::StagePack / RlmToHost::PackStaged (≤ 160 MiB), GuestMode { sister | experiment_vm } on the attestation (serde default = sister, wire-compatible), VmRecord.experiment, health experiment_vms / max_experiment_vms, ErrorCode::Capacity (503).
  • proof-rlm: TopicVmSpec.experiment, run_paid_job (create → run → destroy → return the outcome only on a confirmed destroy; Ok(false) or a teardown error is VmError::TeardownUnconfirmed — 503, no row, no baseline — even after a successful run, naming the VM), VmBackedRunner::with_experiments; TopicSetup::baseline routes through it (the baseline is the first experiment VM). Fake orchestrator keeps experiment VMs out of attach, records teardowns, and can inject unconfirmed / failed teardowns.
  • proof-vm-agent: experiment VMs bypass the one-per-topic rule, never answer attach, count against the host capacity, ids <topic>-x<n>; the fake hypervisor attests experiment_vm.
  • crates/proof-fc-experiment (new, host layer over FirecrackerHypervisor): ceilings (under the lock) → pack resolved under PROOF_VM_AGENT_EXPERIMENT_PACK_DIR and re-hashed with verify_artifact before any jail → boot with disk_mib scratch → StagePack over vsock (destroy on failure) → job bound to the VM's runner + pack → experiment_vm attestation for that VM and job. proof-fc-host changes are 3 lines (scratch size from the spec, attestation mode).
  • proof-vm-fc / bins/proof-challenge: policy from env, an experiment attestation must name the VM the job was dispatched to; orchestrator binary gains the --experiment-* / --max-experiment-vms flags (a vCPU / memory ceiling above the lock refuses to boot) and wraps the backend.
  • crates/proof-vm-guest + bins/proof-vm-guest-agent (new): the generic guest agent (vsock :5000 via tokio-vsock, or --stdio). Hello, tmpfs secrets (chowned to the run-as user), pack verify + unpack, artefact fetch streamed under a hard 64 MiB cap (cut mid-body, never buffered first), adaptor exec contract (run / inspect / propose_rules, documented PROOF_* env, report.json / checklist.json / rules.json), param-name collision refusal before exec, stdout / stderr drained concurrently into rolling bounded tails while the process runs, deadline kill of the process group, secret redaction in every tail and evidence string. No default value ever: no runner / adaptor / pack / verifying artefact / report / finite value → RlmToHost::Failed → 502 → 503, no row. ProposeRules without an adaptor entrypoint echoes the signed topic's own checklist.
  • deploy/guest/: bake-rootfs.sh (Debian minbase + rootless podman/crun/fuse-overlayfs/pasta + catatonit; the podman store on run-as-owned paths init.sh createsgraphroot = /var/lib/proof/containers/storage on the scratch drive, runroot = /run/user/<uid>/containers — never the root-owned /var/lib/containers / /run/containers; generic operator hooks --extra-pkgs / --overlay / --chroot-hook for harness tooling; --check-kernel-config; tree budget 2560 MiB / image 3072 MiB; image named after its own sha256sum; RE-LOCK steps printed; --dry-run without root), init.sh / agent-loop.sh (PID 1, scratch on /dev/vdb, cgroup v2, run-as user, both podman paths pre-created and chowned), runners/README.md (adaptor contract + a fail-closed skeleton + honest rootless-podman limits). No adaptor ships in git — the harness CLI, agent, task format, and trial → primary_value rule are operator artefacts baked outside the repo and selected by signed params; a test greps deploy/guest/ for harness names.
  • Docs: docs/runbooks/proof-experiment-vms.md (params, caps incl. the hard lock, flow incl. confirmed destroy, bake + size budget, RE-LOCK on metal, fail-closed rows incl. the new ones, limitations); pointers in the orchestrator runbook, PROOF.md, root / deploy / docs AGENTS.md, ARCHITECTURE.md, COMPLETENESS.md, miner guide; env examples; wire check fails a ceiling knob above the lock, validates integers, the 16 GiB disk floor, the image pin.

Greptile findings addressed (head 85e26c69)

Finding Fix
P1 Require confirmed VM destruction / P1 Propagate teardown failures (proof-rlm/src/vm.rs) run_paid_job returns the outcome only on teardown → Ok(true); Ok(false) / ErrVmError::TeardownUnconfirmed (503, no row, no baseline), naming the VM and any job failure too. Tests in proof-rlm (evaluate + baseline, injected Ok(false) and Err) and proof-rlm-scorer (setup with an unconfirmed destroy seals no baseline).
P1 Writable Podman paths (bake-rootfs.sh) runroot = /run/user/<uid>/containers, graphroot = rootless_storage_path = /var/lib/proof/containers/storage; init.sh creates and chowns both before the agent starts. Verified in a private mount namespace: uid 1000 can write both, cannot create the old paths. Test asserts the bake's paths are what init makes writable.
P1 Stream artifact size checks (fetch.rs) download_capped reads resp.chunk() incrementally and aborts the moment the cap would be exceeded; honest Content-Length over the cap refused before the body. Test: endless chunked body without Content-Length is cut promptly; bodies at / under the cap arrive whole.
P1 Enforce locked VM maxima (proof-experiment) LOCK_MAX_EXPERIMENT_* compiled in; validate rejects max_vcpus > 16 / max_mem_mib > 32768 (AboveLock), shape / admit reject any such shape; orchestrator refuses --experiment-max-vcpus 32 etc.; wire check fails such knobs. Tests on both sides.
P1 Remove the Harbor harness / P1 Do not substitute rewards (runners/harbor-podman/*) Both files deleted; --with-harbor / --harbor-version replaced by generic --extra-pkgs / --overlay / --chroot-hook; README ships the contract + a fail-closed skeleton only and states a trial without a measurement is never scored from another value. Test greps deploy/guest/ for harness names.
P1 Reject parameter-name collisions (runner.rs) param_env refuses two signed names mapping to one PROOF_PARAM_* (names both + the variable) before run / inspect / propose_rules exec. Test: control (foo-bar alone maps) + collision (adaptor never runs) on all three paths.
P1 Clamp unset experiment defaults (proof-experiment, second review) ExperimentPolicy::from_env reads the MAX knobs first; an unset default follows a lowered ceiling (host parity), a default set above its ceiling is still refused, the lock still holds. Pure from_lookup + test over the vCPU-only / memory-only / disk-only configurations.
P2 Bound output while draining (runner.rs) stdout / stderr drained concurrently into rolling Tails of STREAM_TAIL_BYTES each while the process runs (≤ MAX_TAIL_BYTES total, marker for what was cut). Test: 8 MiB floods on both streams complete under the deadline with a bounded, marked tail.

Honest limits (also in the runbook)

  • Rootless podman, not Docker-in-VM: Firecracker guests have no nested KVM; containers are namespaces run by an unprivileged user. Harness behaviour under podman's API socket / pasta must be smoked on the baked image before signing a topic on it.
  • The guest kernel needs CONFIG_USER_NS, overlayfs, fuse, veth, tun, cgroups, seccomp… — a stock microVM config lacks several (--check-kernel-config names them).
  • flops_used on this path is guest-agent-authored (from report.json, relayed by the host); an agentic harness has no FLOP counter, so the topic sets flops_budget: 0 or supplies an accounting param — never invented.
  • Inspection needs an adaptor inspect entrypoint (topic-RLM work); without one such a topic cannot reach Evaluate.
  • An unconfirmed destroy leaves the VM for the operator to reconcile on the KVM host; the CP withholds the result rather than retrying blindly.
  • Host sizing: one experiment VM at the lock (16 / 32 / 32 GiB disk) already exceeds a g-8vcpu-32gb beside the 4/8 topic VM — the dedicated production host must carry it; the colocated staging droplet lowers the caps on both sides (below the lock is allowed) or keeps the count at 1 with a smaller topic ask.
  • Nothing has been baked or booted from this change. Everything is tested against the fake hypervisor, a recording stager, shell-script adaptors, loopback HTTP, a mount-namespace probe of init.sh, and the bake's dry run. No digest is invented anywhere; the pack digest and runner id are topic data staged outside git.

Greptile

  • Greptile has reviewed this PR; findings are fixed or answered
  • If the bot was silent, I commented @greptileai review

Test plan

  • cargo test --workspace (all green; new: proof-rlm withheld-unless-destroyed, proof-rlm-scorer baseline withheld on unconfirmed destroy, proof-experiment hard lock + lowered-ceiling-only policy, proof-vm-orchestrator above-lock flags refused, proof-fc-experiment above-lock shape refused, proof-vm-guest param collision / output flood / streamed fetch cap / bake hooks / podman paths / no-harness grep)
  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings, cargo deny check, xtask loc-cap / consensus-lint / spec-check / design-check / external-docs-check, dcap clippy
  • Metal: bake, stage image + pack on the KVM host, RE-LOCK per the runbook, run § Verify (not possible from this change; recorded as unknown)

Risk

Additive wire changes (serde(default) everywhere; an old agent given an experiment spec boots a topic VM, stages no pack, attests nothing → the CP refuses the run, 503). No emission, signature-domain, or miner CVM measurement impact. New host env knobs default to the 16 / 32 lock and 2 concurrent experiment VMs and refuse to boot above the lock; size the KVM host for max_experiment_vms × 16 vCPU / 32 GiB / 32 GiB disk on top of the 4/8 topic VM. A host that fails to destroy an experiment VM now surfaces as 503s on that topic (with the VM named) instead of silently leaking capacity.

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.

Open in Web Open in Cursor 

cursoragent and others added 7 commits September 9, 2026 12:22
Generic in-guest experiment binding read from the signed topic's
constraints.params (runner id, pinned pack digest, optional size), held
under configurable per-VM ceilings (16 vCPU / 32 GiB RAM / 32 GiB disk),
created per Baseline/Evaluate job and destroyed after it. Host stages the
pack over vsock and attests the run as experiment_vm; agent caps how many
run at once. No benchmark, pack, or runner is named in git.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
…er adaptors

Transport-agnostic guest agent (vsock or stdio) for the RLM / experiment
microVM: hello, tmpfs secret staging, pack verify + unpack, and every job
routed to <runners_dir>/<runner id>/{run,inspect,propose_rules} under a
documented env contract. No runner, adaptor, pack, verifying artefact,
report, or finite value = RlmToHost::Failed; secrets are redacted from
every tail and evidence document. Nothing benchmark-specific in git.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
… adaptor, experiment env knobs

deploy/guest/bake-rootfs.sh builds the enlarged guest image (Debian minbase,
rootless podman + crun + fuse-overlayfs, optional pinned Harbor CLI, the
guest agent as PID-1 service, operator adaptors under /opt/proof/runners),
enforces a tree size budget, and names the image after the sha256 it
computed with RE-LOCK steps. Adaptor contract + honest rootless-podman
limits in deploy/guest/runners/README.md; the Harbor-over-podman adaptor is
an example operator capability driven entirely by topic params. Env
examples gain the experiment ceilings and pack dir.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
…ock steps

New runbook docs/runbooks/proof-experiment-vms.md (generic params, lock
ceilings 16 vCPU / 32 GiB / 32 GiB disk, pack staging, guest image bake and
size budget, RE-LOCK on metal, fail-closed rows, stated limitations);
pointers from the orchestrator runbook, PROOF.md bindings + isolation
boundary, root/deploy/docs AGENTS, ARCHITECTURE, COMPLETENESS, and the
miner guide. Wire check validates the experiment ceilings and image pin.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
Co-authored-by: Mathis <echobt@users.noreply.github.com>
Co-authored-by: Mathis <echobt@users.noreply.github.com>
Default per-experiment VM 4 vCPU / 8 GiB; a topic may override up to
8 vCPU / 16 GiB; writable disk >= 16 GiB (32 GiB default). Ceilings gain
operator defaults (PROOF_EXPERIMENT_VM_VCPUS / _MEM_MIB) beside the maxima;
the disk floor is enforced on both sides; docs, env examples, and the wire
check follow. baseline_runner=<operator adaptor id> is the canonical example.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@echobt
echobt marked this pull request as ready for review September 9, 2026 13:39
DEFAULT_EXPERIMENT_VCPUS=16, DEFAULT_EXPERIMENT_MEM_MIB=32768,
DEFAULT_MAX_EXPERIMENT_VCPUS=16, DEFAULT_MAX_EXPERIMENT_MEM_MIB=32768:
a silent topic gets the lock and no topic may ask for more (less is fine).
Disk stays 32 GiB default / 16 GiB floor. Docs, AGENTS, runbooks, env
examples, and the wire check say 16/32 everywhere; still generalist.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@echobt

echobt commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review after Mathis 16vCPU/32GiB caps bump (40bd4bb).

@greptile-apps

greptile-apps Bot commented Sep 9, 2026

Copy link
Copy Markdown

Greptile Summary

Summary

  • Unset experiment VM CPU, memory, and disk defaults now follow configured ceilings, allowing smaller hosts to start without redundant default settings.
  • Explicit defaults that exceed their configured ceilings remain rejected, while the hard CPU and memory limits remain enforced.

Merge Safety

Safe to merge. No blocking issues remain.

Confidence Score: 5/5

Safe to merge; no outstanding blocking issues remain.

No outstanding findings remain.

Reviews (4): Last reviewed commit: "fix(proof-experiment): an unset default ..." | Re-trigger Greptile

Comment thread crates/proof-rlm/src/vm.rs Outdated
Comment thread deploy/guest/bake-rootfs.sh Outdated
Comment thread crates/proof-vm-guest/src/fetch.rs Outdated
Comment thread crates/proof-vm-guest/src/runner.rs Outdated
Comment thread crates/proof-experiment/src/lib.rs
Comment thread deploy/guest/runners/harbor-podman/run Outdated
Comment thread crates/proof-vm-guest/src/runner.rs Outdated
Comment thread crates/proof-rlm/src/vm.rs Outdated
Comment thread deploy/guest/runners/harbor-podman/summarize.py Outdated
cursoragent and others added 6 commits September 9, 2026 15:10
… destroyed

run_paid_job returned the job outcome after a teardown that answered
Ok(false) or failed, logging a warning only — a result could be scored
while the dedicated experiment VM still held host capacity. The outcome is
now returned only when the orchestrator confirms the destroy; anything else
is VmError::TeardownUnconfirmed (503, no row, no baseline), naming the VM
and, when the job itself also failed, both causes. VmBackedRunner::evaluate
and TopicSetup::baseline both route through it. The fake orchestrator can
inject Ok(false) / Err teardowns and keeps the VM alive as a host would.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
ExperimentCeilings::validate accepted max_vcpus up to 64 and max_mem_mib up
to 131072, so an operator ceiling above the Mathis lock sized and admitted
64-vCPU / 128 GiB experiment VMs on both sides. LOCK_MAX_EXPERIMENT_VCPUS /
LOCK_MAX_EXPERIMENT_MEM_MIB (16 / 32768) are now compiled-in maxima:
validate refuses any ceiling above them (AboveLock — the CP and the KVM
agent refuse to boot), shape() and admit() refuse any VmShape above them
whatever the ceilings say, and a smaller host may only lower a ceiling.
DEFAULT_* and DEFAULT_MAX_* equal the lock. The disk ceiling stays an
operator knob. The wire check fails (not warns) on a knob above the lock;
env examples and orchestrator flags say so.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
download() buffered the whole body with resp.bytes() before comparing its
length to MAX_ARTIFACT_BYTES, so a server omitting Content-Length could
stream an arbitrarily large body into the experiment VM's memory before the
cap fired. The body is now read chunk by chunk and the fetch aborts (and
drops the connection) the moment it would exceed the cap; an honest
Content-Length over the cap is still refused before the first body byte.
Test: a chunked, endless loopback body is cut at the cap promptly; chunked
bodies at and under the cap arrive whole.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
…ut while draining

Two distinct signed constraints.params names that normalise to the same
PROOF_PARAM_* variable (foo-bar / foo_bar) silently overwrote each other in
the adaptor environment. param_env now refuses the collision, naming both
keys and the variable, before run / inspect / propose_rules exec anything.

stdout and stderr were read to completion into unbounded vectors, with the
64 KiB tail applied only after exit, and sequentially (a full stderr pipe
could stall a run until its deadline). Both streams are now drained
concurrently into rolling Tail buffers of STREAM_TAIL_BYTES each while the
process runs, so a flooding adaptor costs the guest at most MAX_TAIL_BYTES;
the run log carries a marker for what was cut.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
…rbor harness for generic hooks

storage.conf pointed runroot / graphroot at /run/containers/storage and
/var/lib/containers/storage — root-owned, the latter on the read-only
rootfs — while init.sh only made /run/user/<uid> and /var/lib/proof
writable for the runner, so rootless podman could not initialise its store.
The bake now writes runroot = /run/user/<uid>/containers and graphroot =
rootless_storage_path = /var/lib/proof/containers/storage, and init.sh
creates and chowns both before the agent starts.

deploy/guest/runners/harbor-podman (run + summarize.py) named and drove one
benchmark harness and scored its trial format — challenge content in git,
and its summariser substituted the first unrelated rewards value when
'reward' was missing. Both files are removed. runners/ now ships the
adaptor contract and a fail-closed skeleton only; the bake's --with-harbor
/ --harbor-version give way to generic --extra-pkgs / --overlay /
--chroot-hook so operators bake their own harness tooling outside git.
Tests: dry-run plans the hooks and refuses malformed ones, the storage
paths match what init makes writable, and nothing under deploy/guest names
a harness or a benchmark.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
…unbook and agents docs

Runbook, root / deploy AGENTS.md, PROOF.md, COMPLETENESS.md, the
orchestrator runbook, and the miner guide now state the lock as a hard
maximum (a ceiling above it does not boot), that a paid run scores only
once its experiment VM is confirmed destroyed, that param names must stay
distinct as PROOF_PARAM_* variables, that the artefact fetch is streamed
under the 64 MiB cap, and that deploy/guest/runners ships the adaptor
contract and a skeleton only — the harness, adaptor, and scoring rule are
operator artefacts baked with the generic hooks, never in git. Example
runner ids no longer name a harness.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@echobt

echobt commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review after Greptile P1 fixes (ec1defa).

Comment thread crates/proof-experiment/src/lib.rs Outdated
ExperimentPolicy::from_env kept the lock default (16 / 32768) when an
operator lowered only PROOF_EXPERIMENT_VM_MAX_VCPUS or _MAX_MEM_MIB, so
validate rejected default_vcpus / default_mem_mib and the control plane
could not start on a smaller host. Ceilings are now read first and an
unset default is clamped to its ceiling, as the KVM host config already
does; a default the operator set explicitly is still validated as written
and refused above its ceiling, never silently clamped. The reader is a pure
from_lookup over any name -> value source so the vCPU-only, memory-only,
disk-only, explicit-over-ceiling, above-lock, and image-pin cases are
tested without touching the process env.

Co-authored-by: Mathis <echobt@users.noreply.github.com>
@echobt

echobt commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@echobt
echobt merged commit a8b9018 into main Sep 9, 2026
5 checks passed
cursor Bot pushed a commit that referenced this pull request Sep 9, 2026
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>
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