Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .agents/roadmap_v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ issue is not yet placed. Keyed record: update in place, never append.
| [#465](https://github.com/mudler/vllm.cpp/issues/465) | `ENG-RELEASE-WINDOWS` | LogprobsTensors per-request slice parameter shadows its member under native MSVC `/WX` | bug |
| [#474](https://github.com/mudler/vllm.cpp/issues/474) | `ENG-RELEASE-WINDOWS` | MSVC stringizes a backslash-bearing raw literal inside CHECK and rejects the Windows argv expectation | bug |
| [#475](https://github.com/mudler/vllm.cpp/issues/475) | `ENG-RELEASE-WINDOWS` | PR #446 release benchmark projection exceeds its page budget after merging current main | bug |
| [#499](https://github.com/mudler/vllm.cpp/issues/499) | `ENG-RELEASE-WINDOWS` | Release binaries report project version instead of prerelease identity | bug |
| [#500](https://github.com/mudler/vllm.cpp/issues/500) | `ENG-RELEASE-WINDOWS` | MSVC release build lacks ostream definition for string_view doctest diagnostics | bug |
| [#170](https://github.com/mudler/vllm.cpp/issues/170) | `ENG-RELEASE-BINARIES` | Publish container images to GHCR (cuda, vulkan, cpu) | feature |
| [#322](https://github.com/mudler/vllm.cpp/issues/322) | `ENG-RELEASE-BINARIES` | Release handoff collides with tracked checkout `assets` directory | bug |
| [#406](https://github.com/mudler/vllm.cpp/issues/406) | `ENG-TRAILER-MERGE-ARTIFACTS` | The trailer gate fails on how commits LAND: GitHub's Co-authored-by displaces the trailer block | bug |
Expand Down
6 changes: 5 additions & 1 deletion .agents/specs/release-binary-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ request [#117](https://github.com/mudler/vllm.cpp/issues/117); hosted CI repair
per-commit documentation checkpoint repair is tracked by
[#448](https://github.com/mudler/vllm.cpp/issues/448); its archive-target
checkpoint repair is tracked by
[#450](https://github.com/mudler/vllm.cpp/issues/450).
[#450](https://github.com/mudler/vllm.cpp/issues/450). The merged-SHA dry-run
repairs for exact prerelease identity and the native MSVC test translation unit
are tracked by [#499](https://github.com/mudler/vllm.cpp/issues/499) and
[#500](https://github.com/mudler/vllm.cpp/issues/500), specified together in
[release-dry-run-gate-repairs.md](release-dry-run-gate-repairs.md).

## Delivery topology

Expand Down
262 changes: 262 additions & 0 deletions .agents/specs/release-dry-run-gate-repairs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# Merged-SHA release dry-run gate repairs

Identity: `ENG-RELEASE-WINDOWS`

Issues:
[#499](https://github.com/mudler/vllm.cpp/issues/499) and
[#500](https://github.com/mudler/vllm.cpp/issues/500)

Parent specifications:
[release-binary-matrix.md](release-binary-matrix.md) and
[windows-binary-release.md](windows-binary-release.md)

Related native compiler contract:
[windows-msvc-strict-build.md](windows-msvc-strict-build.md)

Status: `READY`. The developer approved this bounded design on 2026-08-12. It
starts from exact main commit `e1087a8812c9b7d96fca5a813981f378fcace638`
after PR #446 merged. Implementation, a fresh review, the operator gate, and a
new non-publishing ten-tuple dry run remain required.

## Scope

Repair the two independent failures exposed by the first exact-merged-SHA
release dry run after PR #446:

1. make the version compiled into every release `vllm-server` equal the exact
release identity supplied by the release plan, including `-pre.1`, while
preserving the existing backend suffix; and
2. make `tests/vt/test_cpu_isa_x86.cpp` own the standard stream definition its
doctest `std::string_view` diagnostics instantiate under MSVC.

Keep CMake's numeric `project(vllm_cpp VERSION 0.0.3)` identity, archive names,
manifests, `VERSION` records, C ABI version, backend suffix policy, release
matrix, `/W4 /WX`, and the strict extracted-archive version validator
unchanged. Do not change production ISA selection, suppress a warning, alter a
release tuple, publish a tag or release, or fold an independent dry-run failure
into these issues.

## Hosted baseline and root causes

Manual workflow run
[`31607273683`](https://github.com/mudler/vllm.cpp/actions/runs/31607273683)
executed against exact merged SHA
`03ed25a5745ccbbfba7ce9e0f5a1c4a5251b7c30` with release identity
`0.0.3-pre.1`.

Issue #499 affected six jobs after their Linux or macOS build and packaging
work had completed:

| Tuple/job | Job ID | Observed gate |
|---|---:|---|
| Linux arm64 CPU | `94152936141` | extracted version mismatch |
| macOS arm64 Metal | `94152936210` | extracted version mismatch |
| Linux x86_64 Vulkan | `94152936237` | extracted version mismatch |
| Linux x86_64 CPU | `94152936310` | extracted version mismatch |
| Linux x86_64 musl CPU | `94152936346` | extracted version mismatch |
| macOS arm64 MLX | `94152936489` | extracted version mismatch |

`CMakeLists.txt:12` declares only numeric project version `0.0.3` and
`CMakeLists.txt:689` configures `include/vllm/version.h.in`. That template
exports only the numeric `PROJECT_VERSION_{MAJOR,MINOR,PATCH}` components, and
`src/vllm/version.cpp:5-12` reconstructs `0.0.3` before applying the current
backend suffix. The release builders require `VERSION`, but their CMake
configure calls do not pass it: `scripts/build-cpu-release.sh:26-40`,
`scripts/build-linux-accelerator-release.sh:32-48`,
`scripts/build-macos-release.sh:29-43`, and
`scripts/build-windows-release.ps1:180-198`. They use `VERSION` later for the
archive and metadata, so the same archive contains manifest/`VERSION` identity
`0.0.3-pre.1` and a server that reports `0.0.3`.

This is not a validator defect. `scripts/validate-release-archive.py:662-671`,
`:740-749`, and `:782-790` correctly require the extracted executable's output
to contain the manifest's exact version and the `VERSION` record's exact C ABI.
That comparison remains fail-closed.

Issue #500 affected native Windows CPU job `94152936312` and Vulkan job
`94152936445`. Both failed while compiling
`tests/vt/test_cpu_isa_x86.cpp:112` through doctest's binary-expression
stringification. The operands are `std::string_view`; the translation unit
includes `<string>` but not `<ostream>`. Under this MSVC include closure,
`std::basic_ostream` is only forward-declared, so the library's
`operator<<(basic_ostream&, string_view)` instantiation produces incomplete
type, missing `iostate`, and cascading C2146/C2027/C2065 diagnostics. The
production x86 ISA code compiled far enough to reach this test-only boundary.

## Design

### Exact compiled build version

Add a CMake cache string named `VLLM_CPP_BUILD_VERSION`. Its default is the
complete numeric `${PROJECT_VERSION}`, so developer and non-release builds keep
reporting `0.0.3` without a new required argument. Generate that string into
`include/vllm/version.h` and make `vllm::Version()` begin with the generated
build version instead of reconstructing the three numeric components.

Preserve the existing backend suffix exactly after that identity. For example,
the default CPU build reports `0.0.3`, a prerelease CPU artifact reports
`0.0.3-pre.1`, and a prerelease CUDA artifact reports
`0.0.3-pre.1+cuda`. Do not derive the prerelease from the tag inside CMake and
do not change the numeric `PROJECT_VERSION`, shared-library `VERSION`/`SOVERSION`,
or C ABI version.

All four release builder families pass their already-required `VERSION` value
to CMake as `-DVLLM_CPP_BUILD_VERSION=...`. The workflow remains responsible
for deriving the single release identity from `release/release-version.json`
and supplying it to each builder. CMake must reject an empty explicit build
version rather than silently reverting to the project version.

The generated value is build metadata, not a second release authority. The
release plan, manifest, archive name, `VERSION` record, executable output, and
post-publication audit must still agree, and the extracted-archive validator
continues enforcing that agreement.

### Explicit stream ownership in the MSVC test

Add the standard `<ostream>` definition directly to
`tests/vt/test_cpu_isa_x86.cpp`. This is a test translation-unit header-hygiene
repair: it makes doctest's diagnostic formatting valid without relying on a
transitive include. Do not change the compared `std::string_view` values,
doctest expressions, production x86 ISA code, compile flags, warning policy, or
standard-library formatting behavior.

## RED-first tests and mutation evidence

Implementation starts by capturing failures against the pinned baseline:

1. Extend the version test contract so a default configuration requires exact
`0.0.3` plus the existing backend suffix, while a separate configure with
`-DVLLM_CPP_BUILD_VERSION=0.0.3-pre.1` requires exact `0.0.3-pre.1` plus that
same suffix. The prerelease arm must fail on the current numeric-only
`Version()` implementation.
2. Extend `tests/scripts/test_release_pipeline.py` over the real four builder
scripts. It must require each configure invocation to forward its existing
`VERSION` input through `VLLM_CPP_BUILD_VERSION`; deleting the argument,
substituting a literal, using `PROJECT_VERSION`, or omitting one builder
must fail.
3. Preserve or extend the archive-validation mutation proving that a server
output of `0.0.3` is rejected when manifest and `VERSION` declare
`0.0.3-pre.1`. No skip-version path may be introduced into a release job.
4. Extend the Windows portability suite over the real
`tests/vt/test_cpu_isa_x86.cpp` closure. It must require the explicit
standard stream definition used by the `std::string_view` doctest
expressions; removing it must fail the structural test and the native MSVC
compile. Comments, literals, or unrelated transitive includes are not valid
substitutes.

Every mutation runs in a scratch copy and restores the candidate tree
byte-for-byte. A structural Linux result does not substitute for executing the
native MSVC compiler.

## Gates

Focused local gates are:

1. the default and prerelease-configured `test_version` cases, including the
current backend-suffix arm;
2. `python3 -m unittest tests.scripts.test_release_pipeline -v` and the focused
release archive/metadata validator tests;
3. `python3 -m unittest tests.scripts.test_check_windows_portability -v` plus
the direct portability checker; and
4. clean CPU configure/build and `test_cpu_isa_x86` execution on the available
local host, followed by full unstaged, staged, and post-commit
`scripts/agent-preflight.sh`.

Hosted acceptance requires native `windows-2022` CPU and Vulkan Release builds
to compile `test_cpu_isa_x86` under unchanged `/W4 /WX`, then execute their
existing focused runtime/ISA and archive gates. The six affected Linux,
macOS, and musl jobs must extract the archive and accept the exact
`0.0.3-pre.1` server identity. CUDA jobs must preserve their existing
`+cuda` suffix after the same prerelease identity.

After merge, rerun the complete ten-tuple non-publishing workflow at the exact
merged SHA. Every required tuple, aggregate handoff, and verify job must be
green, and each archive/manifest/`VERSION`/executable identity must agree.
Manual dispatch must continue skipping attest and publish. Only that immutable
dry run can authorize the already-planned developer-controlled
`v0.0.3-pre.1` tag flow; the tag run must rebuild, attest, publish exactly 32
assets, and pass the existing authenticated post-publication audit before any
binary-release claim advances.

## Risks and stop conditions

- A build-version string can accidentally become an independent release
authority or be lost through one platform's quoting. The single declaration
and all four builder mutations must keep the release graph closed.
- Replacing numeric component macros outright could break an internal consumer.
Preserve them unless their removal is separately proved and reviewed; only
`Version()` needs the full generated identity.
- Backend suffixes can be dropped or duplicated when the base string changes.
Exact CPU and CUDA expectations are required.
- A transitive stream include may make a local compiler green while MSVC stays
red. The test TU must own `<ostream>`, and native compilation remains binding.
- Stop with `NEEDS_DECISION` if #500 requires any production ISA, behavior,
warning-level, or warning-suppression change.
- Stop with `NEEDS_CONTEXT` if a rerun exposes a direct diagnostic outside
these two root causes. File and specify an independent issue rather than
weakening a gate or silently expanding this repair.
- Do not tag or publish if any of the ten dry-run tuples, aggregate handoff,
verify job, exact version checks, or Windows native gates is not green on the
same merged SHA. A partial matrix is not release evidence.

## Written-spec self-review

- Scope is limited to exact compiled release identity and one test-TU stream
definition; release topology and production ISA behavior do not change.
- The CMake default, release override, backend suffix, four builder inputs,
strict validator, and native compiler boundary are explicit.
- RED tests and mutations fail for the two observed defects before code changes.
- Local, hosted, dry-run, tag-run, and post-publication evidence are separated;
none is inferred from another.

## Outcome

Implemented both bounded dry-run repairs without changing release topology,
production ISA behavior, warning policy, or validator strictness.

- `VLLM_CPP_BUILD_VERSION` is now a non-empty CMake cache string defaulting to
`PROJECT_VERSION`. The generated version header retains the numeric component
macros and also carries that exact identity; `Version()` appends the existing
`+cuda` qualifier to it unchanged.
- The CPU, Linux accelerator, macOS, and Windows release builders each forward
their already-required `VERSION` value to CMake exactly once.
- `tests/vt/test_cpu_isa_x86.cpp` now owns the standard `<ostream>` definition
required by its doctest diagnostics.

RED evidence on the pinned candidate preceded implementation. The builder
contract reported zero `VLLM_CPP_BUILD_VERSION` arguments for all four builder
families, the portability contract reported no active `<ostream>` include, and
a separately configured `0.0.3-pre.1` `test_version` failed because the binary
reported `0.0.3`. The retained strict-validator mutation rejects a numeric-only
server output when the manifest and `VERSION` declare `0.0.3-pre.1`.

Focused green evidence:

- release pipeline suite: 41 tests passed;
- Windows portability suite: 71 tests passed, followed by the direct checker;
- archive and platform metadata suites: 43 tests passed;
- an explicit empty build-version configure was rejected; and
- clean CPU builds passed the default and prerelease version tests. The clean
prerelease build also passed all 8,242 x86 ISA assertions. Server smoke output
was exactly `vllm.cpp 0.0.3 c-abi=17` by default and
`vllm.cpp 0.0.3-pre.1 c-abi=17` with the release override.

The two hosted CUDA failures from dry run `31607273683` provide additional
root-cause evidence: jobs `94152936151` and `94152936356` both completed their
build and package phases and failed only because the extracted binary reported
the numeric project version. They did not expose a third repair within this
row's scope.

Native Windows compilation, the complete ten-tuple non-publishing workflow,
and the tag-run publication/audit remain post-merge acceptance gates. No tag or
release is authorized by the local evidence alone.

Fresh review of immutable implementation `e0b17eb9` found that the compiled
version test derived its default expectation from the same cache value under
test. Mutating the cache default from `${PROJECT_VERSION}` to `9.9.9` therefore
changed both subject and oracle and left the focused suite green. The review
loop adds an independent release-contract assertion over the real CMake cache
declaration. With the `9.9.9` mutation applied, that assertion failed exactly
with `9.9.9 != ${PROJECT_VERSION}`; after restoration it and the complete
42-test release pipeline suite passed. Production CMake and runtime code remain
unchanged by this follow-up.
5 changes: 5 additions & 0 deletions .agents/specs/windows-binary-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ Release benchmark projection compaction:
[#475](https://github.com/mudler/vllm.cpp/issues/475), specified in
[release-benchmark-projection-compaction.md](release-benchmark-projection-compaction.md)

Merged-SHA release dry-run gate repairs:
[#499](https://github.com/mudler/vllm.cpp/issues/499) and
[#500](https://github.com/mudler/vllm.cpp/issues/500), specified in
[release-dry-run-gate-repairs.md](release-dry-run-gate-repairs.md)

Parent contract: [release-binary-matrix.md](release-binary-matrix.md)

Planned publication: GitHub prerelease tag `v0.0.3-pre.1`.
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ vllm_cpp_forbid_in_source_build("${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}")

project(vllm_cpp VERSION 0.0.3 LANGUAGES CXX)

set(VLLM_CPP_BUILD_VERSION "${PROJECT_VERSION}" CACHE STRING
"Exact version identity reported by this build")
if(VLLM_CPP_BUILD_VERSION STREQUAL "")
message(FATAL_ERROR "VLLM_CPP_BUILD_VERSION must not be empty")
endif()

# Native Windows release ABI: the core and every consumer use the static
# MSVC/UCRT runtime (/MT in Release, /MTd in Debug), so the installed server
# does not depend on a developer-machine CRT deployment.
Expand Down
16 changes: 16 additions & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ example targets are named after the directories they are built from, so an
in-source build makes the linker write each executable over its own source
directory (issue #85).

### Setting the compiled build identity

`vllm-server --version` reports the CMake project version by default. Release
packaging passes the complete release identity, including any prerelease
component, with `-DVLLM_CPP_BUILD_VERSION=<version>`:

```sh
cmake -S . -B build -DVLLM_CPP_BUILD_VERSION=0.0.3-pre.1
```

The value must not be empty. CUDA builds append their existing `+cuda`
qualifier to this identity. This option controls only the compiled binary
identity; release archives must still use the repository release workflow so
their manifest, `VERSION` record, archive name, and executable are validated as
one version.

### One ROCm-specific behaviour

ROCm builds register the full V1 sampler surface (temperature, top-k/top-p, min-p,
Expand Down
3 changes: 2 additions & 1 deletion include/vllm/version.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
#define VLLM_CPP_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define VLLM_CPP_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define VLLM_CPP_VERSION_PATCH @PROJECT_VERSION_PATCH@
#define VLLM_CPP_BUILD_VERSION "@VLLM_CPP_BUILD_VERSION@"

namespace vllm {
// Returns "MAJOR.MINOR.PATCH", plus "+cuda" when built with the CUDA backend.
// Returns the exact build identity, plus "+cuda" when built with that backend.
std::string Version();
} // namespace vllm
1 change: 1 addition & 0 deletions scripts/build-cpu-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ fi

cmake -S . -B "$build_dir" -G Ninja \
-DVLLM_CPP_BUILD_TESTS=ON \
-DVLLM_CPP_BUILD_VERSION="$VERSION" \
-DVLLM_CPP_BUILD_EXAMPLES=ON \
-DVLLM_CPP_SERVER=ON \
-DVLLM_CPP_CUDA=OFF \
Expand Down
1 change: 1 addition & 0 deletions scripts/build-linux-accelerator-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ cmake -S . -B "$build_dir" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DVLLM_CPP_BUILD_TESTS=ON \
-DVLLM_CPP_BUILD_VERSION="$VERSION" \
-DVLLM_CPP_BUILD_EXAMPLES=ON \
-DVLLM_CPP_SERVER=ON \
-DVLLM_CPP_CUDA="$cuda" \
Expand Down
1 change: 1 addition & 0 deletions scripts/build-macos-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ fi
cmake -S . -B "$build_dir" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DVLLM_CPP_BUILD_TESTS=ON \
-DVLLM_CPP_BUILD_VERSION="$VERSION" \
-DVLLM_CPP_BUILD_EXAMPLES=ON \
-DVLLM_CPP_SERVER=ON \
-DVLLM_CPP_CUDA=OFF \
Expand Down
1 change: 1 addition & 0 deletions scripts/build-windows-release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ Invoke-Checked cmake @(
"-G", "Visual Studio 17 2022",
"-A", "x64",
"-DVLLM_CPP_BUILD_TESTS=ON",
"-DVLLM_CPP_BUILD_VERSION=$env:VERSION",
"-DVLLM_CPP_BUILD_EXAMPLES=ON",
"-DVLLM_CPP_SERVER=ON",
"-DVLLM_CPP_CUDA=OFF",
Expand Down
4 changes: 1 addition & 3 deletions src/vllm/version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
namespace vllm {

std::string Version() {
std::string v = std::to_string(VLLM_CPP_VERSION_MAJOR) + "." +
std::to_string(VLLM_CPP_VERSION_MINOR) + "." +
std::to_string(VLLM_CPP_VERSION_PATCH);
std::string v = VLLM_CPP_BUILD_VERSION;
#ifdef VLLM_CPP_CUDA
v += "+cuda";
#endif
Expand Down
Loading
Loading