code-index-plugin-host cannot say which build it is — three of four shipped binaries answer --version, the fourth exits 21 with usage #262

Closed
opened 2026-09-10 22:11:20 +02:00 by buildagent · 1 comment
Member

Measured

Found while validating the new install.sh against the real published
v0.27.1 release
(not a fixture).

$ code-index              --version   ->  code-index 0.27.1 (f9ddfaf)              exit 0
$ code-index-daemon       --version   ->  code-index-daemon 0.27.1 (f9ddfaf)       exit 0
$ code-index-mcp          --version   ->  code-index-mcp 0.27.1 (f9ddfaf)          exit 0
$ code-index-plugin-host  --version   ->  usage: code-index-plugin-host --serve …  exit 21

Reproduced on the current tree's target/release build as well, so it is
not a property of that release.

Why this is not cosmetic

Every release archive ships all four of these binaries. The plugin host
is the one that is separately executed, by the daemon, against a
module it is handed — and it is the only one an operator cannot ask what
it is.

That runs against the discipline #181 established. answer_provenance.build
exists because an installed 0.26.1 (4555887) served pre-fix answers
about a tree sixty commits further on, and the crate version alone
compared equal throughout
— the build hash is the load-bearing half.
daemon_build extends the same comparison to the daemon that answers a
session. There is no equivalent for the plugin host, and no way to
construct one from outside, because the process cannot be asked.

Concretely, a mixed install — four binaries from two different releases,
which is exactly what a partial install or a hand-copied upgrade
produces — is invisible for this one binary. The new installer refuses to
create that state (it stages all four and renames), but it cannot
detect a pre-existing one for the host, and neither can doctor.

Not claimed

I did not establish whether the host already reports a version over its
own protocol. --self-report appears in its usage as a flag to
--serve, so a build identity may already cross the wire to the daemon;
if it does, this issue is narrower — a missing CLI surface rather than a
missing fact — and the fix is correspondingly smaller. That should be
checked before the shape below is chosen.

Shape of a fix

  1. --version prints code-index-plugin-host <version> (<hash>) and
    exits 0, in the spelling the other three already use — the installer,
    doctor and any operator all parse the same shape then.
  2. If the identity is not already in the host's self-report, add it, so
    the daemon can compare the host it just launched against its own
    build and disclose a skew the way daemon_build does.
  3. A gate that every binary the release archive ships answers
    --version — derived from the archive's contents, not a list. The
    packaging step already names the four binaries it copies; that is the
    population, and it is the same auto-detect-then-demand shape used by
    the required-asset audit and by installer_targets.rs.

Point 3 is the one that lasts: a fifth shipped binary would otherwise
repeat this silently.

Anti-vacuity

A test that runs --version on four binaries and checks exit 0 is
satisfied by a stub. It must assert the output contains the build
hash
, and that the hash matches the one the other binaries report from
the same build — two binaries from one build agreeing is the measurement;
"it printed something" is not.

#181 (which build answered), #182 (which tree), #245 (which generation),
#260 (an index behind the tree), #261 (pinning the installer).

## Measured Found while validating the new `install.sh` against the **real published v0.27.1 release** (not a fixture). ``` $ code-index --version -> code-index 0.27.1 (f9ddfaf) exit 0 $ code-index-daemon --version -> code-index-daemon 0.27.1 (f9ddfaf) exit 0 $ code-index-mcp --version -> code-index-mcp 0.27.1 (f9ddfaf) exit 0 $ code-index-plugin-host --version -> usage: code-index-plugin-host --serve … exit 21 ``` Reproduced on the current tree's `target/release` build as well, so it is not a property of that release. ## Why this is not cosmetic Every release archive ships all four of these binaries. The plugin host is the one that is **separately executed**, by the daemon, against a module it is handed — and it is the only one an operator cannot ask what it is. That runs against the discipline #181 established. `answer_provenance.build` exists because an installed `0.26.1 (4555887)` served pre-fix answers about a tree sixty commits further on, and the *crate version alone compared equal throughout* — the build hash is the load-bearing half. `daemon_build` extends the same comparison to the daemon that answers a session. There is no equivalent for the plugin host, and no way to construct one from outside, because the process cannot be asked. Concretely, a mixed install — four binaries from two different releases, which is exactly what a partial install or a hand-copied upgrade produces — is invisible for this one binary. The new installer refuses to create that state (it stages all four and renames), but it cannot *detect* a pre-existing one for the host, and neither can `doctor`. ## Not claimed I did not establish whether the host already reports a version over its own protocol. `--self-report` appears in its usage as a flag to `--serve`, so a build identity may already cross the wire to the daemon; if it does, this issue is narrower — a missing CLI surface rather than a missing fact — and the fix is correspondingly smaller. That should be checked before the shape below is chosen. ## Shape of a fix 1. `--version` prints `code-index-plugin-host <version> (<hash>)` and exits 0, in the spelling the other three already use — the installer, `doctor` and any operator all parse the same shape then. 2. If the identity is not already in the host's self-report, add it, so the daemon can compare the host it just launched against its own build and disclose a skew the way `daemon_build` does. 3. A gate that every binary the release archive ships answers `--version` — derived from the archive's contents, not a list. The packaging step already names the four binaries it copies; that is the population, and it is the same auto-detect-then-demand shape used by the required-asset audit and by `installer_targets.rs`. Point 3 is the one that lasts: a fifth shipped binary would otherwise repeat this silently. ## Anti-vacuity A test that runs `--version` on four binaries and checks exit 0 is satisfied by a stub. It must assert the output contains **the build hash**, and that the hash matches the one the other binaries report from the same build — two binaries from one build agreeing is the measurement; "it printed something" is not. ## Related #181 (which build answered), #182 (which tree), #245 (which generation), #260 (an index behind the tree), #261 (pinning the installer).
Author
Member

Released in v0.28.1, build 340a75a, via #264 and #265. Release CI passed, including the Windows archive round-trip smoke test. The downloaded archive defines the executable population: all four installed binaries, including code-index-plugin-host, report 0.28.1 and the common build 340a75a. The host ABI report carries the same identity. The exact-tag release smoke harness passed all 8 checks against the published Linux archive, including plugin execution and timeout/trap recovery; native Windows archive smoke also passed. Closing after public artifact verification.

Released in [v0.28.1](https://git.h-dv.de/h-dv/code-index/releases/tag/v0.28.1), build `340a75a`, via #264 and #265. [Release CI](https://git.h-dv.de/h-dv/code-index/actions/runs/752) passed, including the Windows archive round-trip smoke test. The downloaded archive defines the executable population: all four installed binaries, including code-index-plugin-host, report 0.28.1 and the common build 340a75a. The host ABI report carries the same identity. The exact-tag release smoke harness passed all 8 checks against the published Linux archive, including plugin execution and timeout/trap recovery; native Windows archive smoke also passed. Closing after public artifact verification.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
h-dv/code-index#262
No description provided.