asset-for may be a template, and a shim that could only be a copy is refused - #199
Merged
Merged
Conversation
…refused TWO CHANGES, both from the musl switch meeting reality. FIRST: `asset-for` values are now expanded like any other template. synth, ordeal and meld have switched to publishing musl, and the layer should ingest those assets for its gnu platform keys — which is what `asset-for` is for. But its values were used VERBATIM, and these upstreams put the release tag in the asset name: `synth-v0.74.0-x86_64-unknown-linux-musl.tar.gz`. A literal entry survives exactly until the realm's scanner bumps the version unattended, and then names a release that no longer exists. The deposit 404s at 3am. An upstream shipping musl under a versioned name was simply not expressible. `synth-%R-x86_64-unknown-linux-musl.tar.gz` now follows the bump. Backwards compatible by construction: every existing entry — `wac-cli-…`, `wsc-linux-x86_64`, `wrpc-wasmtime-…` — carries no placeholder and expands to itself, which has its own test so this cannot quietly break three realms. `%R` and not `%V`: these assets carry the release TAG, and `%V` is the bare version. The first draft of the test asserted the wrong one and was corrected against the real release listing rather than guessed a second time. SECOND: `shim install` refuses where a shim could only be a copy (DD-031). A shim IS the varve binary under another name — argv[0] dispatch, no parser, arguments as raw bytes, one process. On unix it is a symlink, so `self-update` replaces the binary and every shim follows; the code comment says exactly that. On Windows there is no symlink to rely on, so it was a copy, and the property inverts silently: the copy binds to the varve that existed at install time, `self-update` never touches shims, and every shim keeps running the old code forever. The pin still resolves the right LAYER, so the tool dispatched is correct. What goes stale is varve's own verification and refusal logic — the worst part to have quietly out of date in a tool whose job is refusing the wrong bytes. So it refuses, and says why, and names `varve run` as the alternative that is never stale. The mechanism that should replace the copy is deliberately open (DD-031 records the four candidates and what each costs): shipping the easy one now would entrench the weaker model before any Windows build exists. `cmd-shim.md` stops telling readers "on Windows a copy" — behaviour no build has ever produced, in a repository that gates exactly this class of claim. The refusal branch was type-checked by compiling it under `cfg(all())` once and reverting; the real target cannot be used here because ring's C build will not cross-compile to MSVC from macOS. `shim_platform.rs` keeps it honest afterwards, since nothing on unix would notice a `fs::copy` returning. Both new guards negative-controlled: restoring the copy fails, and re-adding the documentation promise fails. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu
`rivet validate` refused the decision as written: a design decision with no `satisfies` link is a decision floating beside the V rather than in it, and the release-plan gate is the thing that noticed. The two it protects are the ones a stale copy breaks. REQ-SHIM-002 says the shim IS varve under another name; a copy is a fossil of varve, correct the day it is written. REQ-SHIM-001 says a shim resolves the pin per invocation and never falls back; a shim that cannot be updated resolves with last month's logic, which for a tool whose job is refusal is the wrong month. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu
avrabe
enabled auto-merge (squash)
September 25, 2026 10:46
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.
Two changes, both from the musl switch meeting reality.
1.
asset-forvalues expand like any other templatesynth v0.74.0, ordeal v0.21.0 and meld v0.58.3 now publish musl, and the
layer should ingest those for its gnu platform keys — which is exactly what
asset-foris for. But its values were used verbatim, and these upstreamsput the release tag in the asset name:
A literal entry survives until the realm's scanner bumps the version
unattended — then the manifest names a release that no longer exists and the
deposit 404s at 3am. An upstream shipping musl under a versioned name was
not expressible at all.
synth-%R-x86_64-unknown-linux-musl.tar.gznow follows the bump.Backwards compatible by construction: every existing entry —
wac-cli-…,wsc-linux-x86_64,wrpc-wasmtime-…— carries no placeholder and expands toitself. That has its own test, so this cannot quietly break three realms.
(
%R, not%V: these assets carry the release tag;%Vis the bareversion. The first draft of the test asserted the wrong one and was corrected
against the real release listing rather than guessed twice.)
2.
shim installrefuses where the shim could only be a copy — DD-031A shim is the varve binary under another name: argv[0] dispatch, no
parser, arguments as raw bytes, one process. On unix it is a symlink, so
self-updatereplaces the binary and every shim follows — the code commentsays precisely that.
On Windows there is no symlink to rely on, so it was a copy, and the
property inverts silently: the copy binds to the varve that existed at install
time,
self-updatenever touches shims, and every shim keeps running the oldcode forever.
The subtle part: the pin still resolves the right layer, so the tool
dispatched is correct. What goes stale is varve's own verification and
refusal logic — the worst thing to have quietly out of date in a tool whose
job is refusing the wrong bytes.
So it refuses, explains why, and names
varve run(which resolves the pin perinvocation and is never stale). The replacement mechanism is deliberately
open — DD-031 records all four candidates and what each costs:
.cmdwrapper →varve runmakeand CI get the ambient binary, not the pinned oneShipping the easy one now would entrench the weaker model before any Windows
build exists (varve#197).
cmd-shim.mdalso stops telling readers "on Windows a copy" — behaviour nobuild has ever produced, in a repository that gates this class of claim
elsewhere.
Verification
The refusal branch was type-checked by compiling it under
cfg(all())once and reverting — the real target cannot be used here because
ring's Cbuild will not cross-compile to MSVC from macOS.
shim_platform.rskeeps ithonest afterwards, since nothing on unix would notice a
fs::copycomingback.
Both new guards negative-controlled: restoring the copy fails; re-adding the
documentation promise fails.
fmt · clippy -D warnings · 1044 tests, 0 failed · trace-gate OK.
🤖 Generated with Claude Code
https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu