Skip to content

asset-for may be a template, and a shim that could only be a copy is refused - #199

Merged
avrabe merged 3 commits into
mainfrom
feat/asset-for-templates
Sep 25, 2026
Merged

avrabe merged 3 commits into
mainfrom
feat/asset-for-templates

Conversation

@avrabe

@avrabe avrabe commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Two changes, both from the musl switch meeting reality.

1. asset-for values expand like any other template

synth 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-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 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.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. That has its own test, so this cannot quietly break three realms.

(%R, not %V: these assets carry the release tag; %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 twice.)

2. shim install refuses where the 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 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-update never touches shims, and every shim keeps running the old
code 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 per
invocation and is never stale). The replacement mechanism is deliberately
open — DD-031 records all four candidates and what each costs:

candidate cost
.cmd wrapper → varve run reintroduces a parser, two processes, batch quoting
hard link orphaned by self-update's atomic replace
Windows symlink (Dev Mode) freshness varies per machine
shell functions make and CI get the ambient binary, not the pinned one

Shipping the easy one now would entrench the weaker model before any Windows
build exists (varve#197).

cmd-shim.md also stops telling readers "on Windows a copy" — behaviour no
build 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 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 coming
back.

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

avrabe and others added 2 commits September 25, 2026 07:29
…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
avrabe enabled auto-merge (squash) September 25, 2026 10:46
@avrabe
avrabe merged commit 985b6eb into main Sep 25, 2026
26 checks passed
@avrabe
avrabe deleted the feat/asset-for-templates branch September 25, 2026 16:21
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.

1 participant