Summary
When the vendored xlings (<home>/registry/bin/xlings) is older than the version mcpp pins, acquire_xlings_binary (src/fallback/xlings_binary.cppm) looks for a newer source and either replaces the binary (Updating vendored xlings A -> B) or keeps it and prints:
Note vendored xlings 2026.9.29.1 is older than the pinned 2026.9.30.1, but no newer source is available (keeping it; run `xlings self update`)
Two defects follow from how the check is made:
- The note can be false.
candidate_source_version returns the version of the first source that exists, in the order MCPP_VENDORED_XLINGS, the xlings released beside the running mcpp (<prefix>/registry/bin/xlings), then xlings on PATH. It does not take the newest of them. When the released copy is older than the pin and a newer xlings is on PATH, mcpp states that no newer source is available and keeps the older binary.
- The note is printed once per configuration load, not once per command. The check runs in
config::load_or_init(), which is not memoised and is called from about ten call sites (the pack pipeline, each member's prepare, the fetcher, and others). One mcpp pack --format release over a workspace printed the note three times per member.
Measurement
The cross-verification of #743 on the validation project (Sunrisepeak/GalTranslPP, run 36643197950, Windows) installs the released mcpp 2026.9.29.5 and replaces only its mcpp.exe with a build of the pull request branch, whose pin is xlings 2026.9.30.1. The xlings beside it is the 2026.9.29.1 that the 2026.9.29.5 release shipped. The same job installed xlings v2026.9.30.1 with quick_install.ps1 and put %USERPROFILE%\.xlings\bin on PATH. The build printed the note above, repeatedly, although a newer xlings was on PATH.
Scope
A release does not reach this state: its archive ships the pinned xlings beside mcpp. An mcpp installed with xlings install (home ~/.mcpp) whose vendored copy is older finds the released copy first, prints Updating once, and is quiet afterwards; a self-contained home's vendored copy is the released one. The state arises when the released copy is older than the pin, as in the cross-verification layout, a hand-replaced binary, or a development build placed in an older release directory.
| vendored |
released beside mcpp |
on PATH |
today |
expected |
| older |
pinned |
any |
one Updating |
unchanged |
| older |
older |
newer |
Note (false), repeated |
one Updating from PATH |
| older |
absent |
newer |
one Updating per load |
one Updating |
| older |
older |
older |
Note, repeated |
one Note |
Proposed change
- One function selects the source:
MCPP_VENDORED_XLINGS when it is set; otherwise the newer of the released copy and the PATH copy, the released copy on a tie. The check and the copy both use its answer, so the version stated is the version copied.
- The rule that a vendored binary is replaced only by a strictly newer one is kept, so an old system xlings still cannot downgrade it.
Updating and Note are each stated at most once per process.
Criteria
An e2e test with three stub xlings binaries that print a version:
- vendored older, released older,
PATH newer: one Updating line, and the vendored binary is then the PATH one;
- vendored older, released newer,
PATH older: the released copy is taken;
- all three older than the pin: one
Note line;
- a command that loads the configuration more than once prints the line once.
Found during the 2026.9.30.1 cycle (#743); it does not affect that release.
Summary
When the vendored xlings (
<home>/registry/bin/xlings) is older than the version mcpp pins,acquire_xlings_binary(src/fallback/xlings_binary.cppm) looks for a newer source and either replaces the binary (Updating vendored xlings A -> B) or keeps it and prints:Two defects follow from how the check is made:
candidate_source_versionreturns the version of the first source that exists, in the orderMCPP_VENDORED_XLINGS, the xlings released beside the running mcpp (<prefix>/registry/bin/xlings), thenxlingsonPATH. It does not take the newest of them. When the released copy is older than the pin and a newer xlings is onPATH, mcpp states that no newer source is available and keeps the older binary.config::load_or_init(), which is not memoised and is called from about ten call sites (the pack pipeline, each member's prepare, the fetcher, and others). Onemcpp pack --format releaseover a workspace printed the note three times per member.Measurement
The cross-verification of #743 on the validation project (Sunrisepeak/GalTranslPP, run 36643197950, Windows) installs the released mcpp 2026.9.29.5 and replaces only its
mcpp.exewith a build of the pull request branch, whose pin is xlings 2026.9.30.1. The xlings beside it is the 2026.9.29.1 that the 2026.9.29.5 release shipped. The same job installed xlingsv2026.9.30.1withquick_install.ps1and put%USERPROFILE%\.xlings\binonPATH. The build printed the note above, repeatedly, although a newer xlings was onPATH.Scope
A release does not reach this state: its archive ships the pinned xlings beside mcpp. An mcpp installed with
xlings install(home~/.mcpp) whose vendored copy is older finds the released copy first, printsUpdatingonce, and is quiet afterwards; a self-contained home's vendored copy is the released one. The state arises when the released copy is older than the pin, as in the cross-verification layout, a hand-replaced binary, or a development build placed in an older release directory.PATHUpdatingNote(false), repeatedUpdatingfromPATHUpdatingper loadUpdatingNote, repeatedNoteProposed change
MCPP_VENDORED_XLINGSwhen it is set; otherwise the newer of the released copy and thePATHcopy, the released copy on a tie. The check and the copy both use its answer, so the version stated is the version copied.UpdatingandNoteare each stated at most once per process.Criteria
An e2e test with three stub xlings binaries that print a version:
PATHnewer: oneUpdatingline, and the vendored binary is then thePATHone;PATHolder: the released copy is taken;Noteline;Found during the 2026.9.30.1 cycle (#743); it does not affect that release.