feat: the agent's machine carries its own Rust, built rather than bor… - #8
Merged
Merged
Conversation
…rowed
On 2026-08-30 a paid benchmark run watched Claude, inside the machine, choose
exactly the right primitive — ask what a symbol is, then rename it — and be
answered:
context: source: index, resolution: matched, analyzer_starts: 0
rename: ok: false, error: unresolved,
message: there is no `cargo` on this machine
Everything after that in the transcript is a consequence. The preflight had said
READY, and it was right about what it asked: the machine was alive and holding
the right tree. Neither is the capability a Rust task needs, and there was
nothing between the money and finding that out.
The first fix attempted was to copy the host's ~/.rustup onto the store. Cesar
stopped it and he was right: Filosofia-Fundacional.md says Thalyx is the whole
system, so a programming face that only works because Fedora has rustup
installed is a face that belongs to Fedora. Move the disk to another x86_64 box
and the semantic provider would vanish.
So the runtime is Thalyx's own artifact. dev/build-rust-runtime.sh builds it
from digest-checked upstream tarballs — Rust's official musl host tools, whose
sha256 come from Rust's own channel manifest — plus the two files Rust does not
publish: musl's loader, compiled here from musl's release tarball, and
libgcc_s.so.1, linked out of the libunwind.a that ships inside rust-std itself.
Nothing is copied from the machine that builds it. 644 MB, on the store, never
in the initramfs — `make count` still says the kernel and one program, and there
is now a test that arms the archive and counts it.
Why musl and not the ordinary toolchain was a measurement taken before anything
was written: the GNU one needs glibc's loader, libc, libm, libdl, librt,
libpthread, libgcc_s and libz from the host plus a separate 191 MB libLLVM; the
musl one needs exactly two files, and LLVM is inside librustc_driver. Two
missing files is a problem a person can close.
That the unwinder-only libgcc_s is enough is also a measurement: of the 883
undefined symbols across cargo, rustc, rust-analyzer, the proc-macro server and
librustc_driver, everything resolves against musl and librustc_driver except 29,
and the only ones of those that are not weak are the fifteen _Unwind_*, all of
which libunwind.a defines. Then it was run rather than argued.
What is checked, and how, because `ldd` is the wrong instrument: it starts the
real loader against the real /lib, so it says what *this* Fedora would resolve.
An artifact missing a library that happens to live in the builder's /usr/lib
looks perfect on the builder and is a directory of dead ELF files inside Thalyx,
whose /lib is empty — and the failure surfaces as ENOENT from execve, which
reads as "there is no cargo on this machine" about a cargo that is right there.
So `thalyx dev rust-runtime` reads PT_INTERP and every DT_NEEDED out of the
headers and asks whether they are inside the artifact.
Also here:
- discovery puts Thalyx's own runtime second, behind only a variable that
names a file. When Thalyx carries a compiler, that is the compiler;
- PID 1 makes /lib/ld-musl-x86_64.so.1 point at the artifact's loader after
mounting the store, which is what the kernel reads out of PT_INTERP;
- a read-only `toolchain` verb that runs cargo --version and
rust-analyzer --version *inside* the machine and reads the workspace's
manifests, and `thalyx-mcp --preflight --needs-rust`, which refuses to be
READY without it. The benchmark asks for it whenever the project has a
Cargo.toml — derived from the tree, because a flag somebody has to remember
is the flag that was missing on the run that needed it;
- `make -C image agent PROJECT=…` stages it automatically for a Cargo
workspace, prints where it came from and how much, and refuses — deleting
what it copied — if the artifact is not closed.
Proven physically in this container, not just in tests: inside a chroot holding
the artifact, /proc and three device nodes — no shell, no /usr, no /lib64 —
cargo, rustc and rust-analyzer start, cargo metadata describes a synthetic
workspace, and a full rust-analyzer session resolved a definition and returned
four real rename edits. What is *not* proven here is a booted Thalyx doing it;
that needs the hardware, and dev/verify-agent-rust.sh is the one command for it.
Two rules learned and written into Estrategia-de-Pruebas.md: a check that asks
the host answers about the host, and musl resolves $ORIGIN for the main program
by reading /proc/self/exe — the same binary starts with /proc mounted and dies
without it, complaining about a library that is right where it says.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CvoEad9oWgX1Y594uirzbn
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.
…rowed
On 2026-08-30 a paid benchmark run watched Claude, inside the machine, choose exactly the right primitive — ask what a symbol is, then rename it — and be answered:
Everything after that in the transcript is a consequence. The preflight had said READY, and it was right about what it asked: the machine was alive and holding the right tree. Neither is the capability a Rust task needs, and there was nothing between the money and finding that out.
The first fix attempted was to copy the host's ~/.rustup onto the store. Cesar stopped it and he was right: Filosofia-Fundacional.md says Thalyx is the whole system, so a programming face that only works because Fedora has rustup installed is a face that belongs to Fedora. Move the disk to another x86_64 box and the semantic provider would vanish.
So the runtime is Thalyx's own artifact. dev/build-rust-runtime.sh builds it from digest-checked upstream tarballs — Rust's official musl host tools, whose sha256 come from Rust's own channel manifest — plus the two files Rust does not publish: musl's loader, compiled here from musl's release tarball, and libgcc_s.so.1, linked out of the libunwind.a that ships inside rust-std itself. Nothing is copied from the machine that builds it. 644 MB, on the store, never in the initramfs —
make countstill says the kernel and one program, and there is now a test that arms the archive and counts it.Why musl and not the ordinary toolchain was a measurement taken before anything was written: the GNU one needs glibc's loader, libc, libm, libdl, librt, libpthread, libgcc_s and libz from the host plus a separate 191 MB libLLVM; the musl one needs exactly two files, and LLVM is inside librustc_driver. Two missing files is a problem a person can close.
That the unwinder-only libgcc_s is enough is also a measurement: of the 883 undefined symbols across cargo, rustc, rust-analyzer, the proc-macro server and librustc_driver, everything resolves against musl and librustc_driver except 29, and the only ones of those that are not weak are the fifteen Unwind*, all of which libunwind.a defines. Then it was run rather than argued.
What is checked, and how, because
lddis the wrong instrument: it starts the real loader against the real /lib, so it says what this Fedora would resolve. An artifact missing a library that happens to live in the builder's /usr/lib looks perfect on the builder and is a directory of dead ELF files inside Thalyx, whose /lib is empty — and the failure surfaces as ENOENT from execve, which reads as "there is no cargo on this machine" about a cargo that is right there. Sothalyx dev rust-runtimereads PT_INTERP and every DT_NEEDED out of the headers and asks whether they are inside the artifact.Also here:
toolchainverb that runs cargo --version and rust-analyzer --version inside the machine and reads the workspace's manifests, andthalyx-mcp --preflight --needs-rust, which refuses to be READY without it. The benchmark asks for it whenever the project has a Cargo.toml — derived from the tree, because a flag somebody has to remember is the flag that was missing on the run that needed it;make -C image agent PROJECT=…stages it automatically for a Cargo workspace, prints where it came from and how much, and refuses — deleting what it copied — if the artifact is not closed.Proven physically in this container, not just in tests: inside a chroot holding the artifact, /proc and three device nodes — no shell, no /usr, no /lib64 — cargo, rustc and rust-analyzer start, cargo metadata describes a synthetic workspace, and a full rust-analyzer session resolved a definition and returned four real rename edits. What is not proven here is a booted Thalyx doing it; that needs the hardware, and dev/verify-agent-rust.sh is the one command for it.
Two rules learned and written into Estrategia-de-Pruebas.md: a check that asks the host answers about the host, and musl resolves $ORIGIN for the main program by reading /proc/self/exe — the same binary starts with /proc mounted and dies without it, complaining about a library that is right where it says.
Claude-Session: https://claude.ai/code/session_01CvoEad9oWgX1Y594uirzbn