From 8fcd6938cb6ec2b6a67168b74e23becfadc22681 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Tue, 11 Aug 2026 20:05:23 +0000 Subject: [PATCH] record(ENG-TRAILER-MERGE-ARTIFACTS): close the row DONE at 157080c8 Closing the row BEFORE deleting its branch, which is the ordering that matters: audit-live-rows calls an ACTIVE row with no branch ABANDONED, and doing the cleanup first is exactly how main went red after dbd0d51c landed. The branch is still on the remote as this lands. State ACTIVE -> DONE with closing commit 157080c8 and a parity-ledger closure anchor, matching how ENG-NOW-DERIVED was closed. The claim file is deleted, which is what closing a claim means under the one-file-per-claim shape, and RUNNABLE_BASELINE shrinks by the row because a DONE row leaves the gated population entirely rather than taking a weaker verdict. The pre-existing `departed` set in test_check_gate_commands.py grows from three runnable DONE rows to four. That literal is updated rather than loosened, and my own near-duplicate guard is dropped: the canonical mutation test already covers re-adding a departed row, and two tests asserting the same thing is how a set like this drifts. The spec's `## Outcome` records what this row did NOT do. It fixed one of five observed shapes; f64f2b71 (bot co-author) is a real violation the broken parse had been hiding and now correctly fails, which looks like a regression and is the opposite; and the remaining three are merge-method artifacts whose fix is a process decision, not a checker change. That is why the row does not claim to have made main green. Gates: preflight rc=0; check-agent-record OK; check-doc-checkpoint OK; test_check_gate_commands 31. Issue: https://github.com/mudler/vllm.cpp/issues/406 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:claude-opus-5 [Claude Code] --- .../CLAIM-ENG-TRAILER-MERGE-ARTIFACTS.md | 5 --- .agents/engine-matrix.md | 6 ++-- .agents/parity-ledger.md | 1 + .agents/specs/trailer-merge-artifacts.md | 32 +++++++++++++++-- scripts/check-gate-commands.py | 11 +++--- tests/scripts/test_check_gate_commands.py | 35 ++++++++----------- 6 files changed, 51 insertions(+), 39 deletions(-) delete mode 100644 .agents/claims/CLAIM-ENG-TRAILER-MERGE-ARTIFACTS.md diff --git a/.agents/claims/CLAIM-ENG-TRAILER-MERGE-ARTIFACTS.md b/.agents/claims/CLAIM-ENG-TRAILER-MERGE-ARTIFACTS.md deleted file mode 100644 index 92e08accc..000000000 --- a/.agents/claims/CLAIM-ENG-TRAILER-MERGE-ARTIFACTS.md +++ /dev/null @@ -1,5 +0,0 @@ -# CLAIM-ENG-TRAILER-MERGE-ARTIFACTS - -| Claim | Row IDs | Agent | Worktree / remote dir | Branch | Owned scope | State | Last update | -|---|---|---|---|---|---|---|---| -| `CLAIM-ENG-TRAILER-MERGE-ARTIFACTS` | `ENG-TRAILER-MERGE-ARTIFACTS` (`ACTIVE`) | Claude Code (opus-5), helper role | isolated worktree `/home/mudler/_git/vllm.cpp-trailers`; no GPU, no registry, no publication | `row/ENG-TRAILER-MERGE-ARTIFACTS`, issue [#406](https://github.com/mudler/vllm.cpp/issues/406) | Owns ONLY: NEW `.agents/specs/trailer-merge-artifacts.md`; the paragraph-fusion helpers in `scripts/check-commit-trailers.py`; and the five cases in `tests/scripts/test_check_commit_trailers.py`. EXCLUDES every other rule in that checker, the merge-method process change the spec names as follow-up, and all product source | `ACTIVE` | 2026-08-11 — fix implemented; 21/21 green; the five real `main` commits re-verified and the verdict table reproduces | diff --git a/.agents/engine-matrix.md b/.agents/engine-matrix.md index b401a5b98..5031aa774 100644 --- a/.agents/engine-matrix.md +++ b/.agents/engine-matrix.md @@ -42,11 +42,11 @@ forensics: roadmap_v1.md and the parity ledger. | Sampling and generation | 15 | 4 | 2 | 0 | 0 | 4 | 0 | 1 | 4 | | Structured output and tools | 7 | 0 | 3 | 0 | 0 | 2 | 0 | 0 | 2 | | Speculative decoding | 21 | 0 | 0 | 1 | 0 | 5 | 0 | 4 | 10 | -| Serving, API, CLI, library | 30 | 10 | 2 | 0 | 2 | 8 | 2 | 2 | 4 | +| Serving, API, CLI, library | 30 | 10 | 2 | 0 | 2 | 7 | 2 | 3 | 4 | | LoRA and adapters | 2 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | | Long context and attention | 10 | 5 | 0 | 0 | 1 | 0 | 1 | 0 | 3 | | Loading, tokenizer, config | 10 | 3 | 3 | 0 | 0 | 1 | 1 | 1 | 1 | -| **Total** | **150** | **35** | **16** | **4** | **9** | **28** | **8** | **10** | **39** | +| **Total** | **150** | **35** | **16** | **4** | **9** | **27** | **8** | **11** | **39** | ## Engine core and scheduling @@ -212,7 +212,7 @@ claims it. | `ENG-RELEASE-CONTAINERS` | Published OCI container images on GHCR, built by GitHub Actions: the same staged server bundle as `ENG-RELEASE-BINARIES`, shipped from one package `ghcr.io/mudler/vllm.cpp` with the lane in the tag — `:-cuda` / `-vulkan` / `-cpu`, the moving `:latest-cuda` / `:latest-vulkan` / `:latest-cpu`, and a bare `:latest` aliasing the cpu lane, with `ENTRYPOINT vllm-server`. Lanes `cuda` (one fat image covering every supported SM), `vulkan`, `cpu` (adaptive baseline); `rocm` blocked-preview, tracking its binary channel. Version tags are immutable; every `latest-` moves. Each lane is a `linux/amd64` + `linux/arm64` multi-arch manifest built on native runners — aarch64 is first-class here because GB10 (sm_121a), Thor (sm_110) and Orin (sm_87) are all arm64. The image contains the bundle and nothing else: no weights, no Python, no PyTorch, no compiler, no build tree. BOUNDARY: the GPU driver and container runtime stay on the host and are never bundled; Metal and MLX are NOT-CONTAINERIZABLE (no macOS container runtime and no Metal passthrough exists) and remain static-binary-only lanes, recorded as a permanent boundary rather than pending work. No image, workflow, registry package or pull is claimed to exist. | T0 | release image lanes `.buildkite/release-pipeline.yaml:34-170` and the published-image dependency boundary `docker/Dockerfile.cpu:262-290` @ `555967922` | `docker/Dockerfile` (cpu/vulkan/cuda targets calling the release scripts); `docker/healthcheck.sh`; `release/container-matrix.json`; `scripts/check-container-matrix.py`; `scripts/check-container-workflow.py`; `scripts/validate-container-image.py`; `scripts/container_tags.py`; `.github/workflows/containers.yml`; SIGTERM handler `src/vllm/entrypoints/openai/server_main.cpp` (`SignalShutdown`, all three `listen()` sites); the pre-existing `docker/Dockerfile.arm64` is an unrelated CPU bench cross-check | issues `#170`, `#312`, `#394`; `tests/scripts/test_check_container_matrix.py` 31/31; `test_check_container_workflow.py` 29/29; `test_check_cuda_fat_gencode.py` 7+4 subtests. **GB10 2026-08-11 (`promaxgb10-4ad8`, `sm_121a`, CUDA 13.3): arm64 cuda image 1.71 GB, 673/673 objects, ten-SM gencode audit PASS, and a REAL GPU boot -- `/health` 200, `/version` 200, in-container healthcheck, clean SIGTERM, `--gpus all`, host driver 580.159.03 injected.** cpu amd64 783 MB gated locally; cpu+vulkan amd64 green on hosted CI **arm64 cuda lane RUNTIME-VERIFIED on GB10 2026-08-11** -- the first accelerator-hardware evidence for any lane. Four defects were removed to get there, each found by building rather than reading: the CUDA 12.9 base could not compile `sm_110`, the BuildKit cache mount outlived its toolchain (both #366), Marlin gencode had drifted from the feature table and failed the audit on 14 correctly-compiled TUs (#394, blocking BOTH cuda tuples project-wide), and the validator could only ever produce build evidence because its boot smoke never passed `--gpus`. **NOT established: nothing is published to GHCR; amd64 cuda is unbuilt; the published arm64 image is SBSA (`targets/sbsa-linux`), so Tegra -- Thor `sm_110`, Orin `sm_87` -- is untested and NOT covered** | [container-images.md](specs/container-images.md); issues [#170](https://github.com/mudler/vllm.cpp/issues/170), [#312](https://github.com/mudler/vllm.cpp/issues/312), [#394](https://github.com/mudler/vllm.cpp/issues/394) | `ACTIVE` | `CLAIM-ENG-RELEASE-CONTAINERS-W1-W7` | | `ENG-DOCS-SITE` | Publish the 11 `docs/*.md` as a browsable GitHub Pages site at `https://mudler.github.io/vllm.cpp/` WITHOUT a second copy of the prose. A Hugo site at `website/` mounts `../docs` READ-ONLY and derives everything else from what is already in the files: each page title from the file's first `# H1`, the sidebar order from `website/data/nav.yaml`, and links through a Goldmark render hook (internal `.md` → site URL; the 139 `../.agents/**` and `../AGENTS.md` escapes → GitHub blob URLs, since the protocol tree is deliberately NOT published). **No file under `docs/` is modified, moved, renamed, or given front matter**, so `check-doc-checkpoint.py` and every protocol path reference keep working and there is no second surface that can drift — the whole point of the row. Custom lean layouts, NO theme and NO submodule: off-the-shelf docs themes read titles, weights and menus out of front matter this design deliberately does not have, so each would need its title partial, menu and link hook overridden anyway, and hugo-book additionally floors at Hugo 0.158 against the 0.146.3 pin CI and the local toolchain share. Hard prerequisite inside the repo: `classify_path` in `scripts/check-pr-size.py` FAILS CLOSED on `website/**` (verified: raises `ValueError: unclassified repository path`), so the classifier must learn the path or the PR cannot pass the project's own size gate. Hard prerequisite outside it: GitHub Pages must be enabled with the source set to GitHub Actions — the workflow is inert otherwise. A marketing landing page is explicitly OUT of scope (`README.md` stays the front door), as is any restructuring of `docs/`; the custom domain is parked behind the pending vLLM trademark question | T1 | NO vLLM analogue — upstream's docs are a separate mkdocs site and nothing in this row mirrors upstream *behavior*, so it carries no parity obligation. The STRUCTURAL reference is LocalAI's `.github/workflows/gh-pages.yml` (two Hugo sites merged into one Pages artifact), reduced to the docs half | read-only mount `website/hugo.toml:29`; title-from-H1 `website/layouts/partials/title.html:10`; link rewriting `website/layouts/_default/_markup/render-link.html:27`; guard `scripts/check-site.py:70`; deploy `.github/workflows/gh-pages.yml` | `tests/scripts/test_check_site.py:51,56,66,80,89,97` (6 mutation cases: clean tree, H1 stripped, doc absent from nav, nav entry with no file, duplicated entry, missing nav file); build evidence 14 pages with `docs/bench-evidence` + `docs/superpowers` absent from `public/` and no `href` ending in `.md`; 48 protocol links rewritten in `docs/status/`. NO published page is claimed: GitHub Pages is not yet enabled on the repository, which is the recorded stop condition holding this row at `GATING` | [gh-pages-docs-site.md](specs/gh-pages-docs-site.md); issue [#224](https://github.com/mudler/vllm.cpp/issues/224) | `READY` | `CLAIM-ENG-DOCS-SITE` | | `ENG-RECORD-CONFLICT-SURFACES` | Retire the shared record surfaces that make concurrent PRs conflict by construction. MEASURED at `origin/main` `d928e2c3` with `git merge-tree --write-tree` over every open PR: **16 of 29 conflict (55%), and 13 of the 16 conflict in bookkeeping files ONLY**, with no product code involved — `.agents/coordination.md` in 8, `.agents/NOW.md` in 5, `.agents/roadmap_v1.md` in 4, `scripts/check-public-doc-tables.py` in 4, `docs/STATUS.md` in 4, and any `src/`/`tests/` path in just 3. Three defects, each of which GUARANTEES rather than risks a collision. (1) `.agents/NOW.md` is a fixed-size shared buffer at EXACTLY 6000/6000 chars (`check-now-current.py:31`), so adding a row requires evicting another and every PR is a read-modify-write of one global — and the conflict is the LUCKY outcome, since a clean three-way merge would apply both evictions and both additions, silently dropping live rows and blowing the very budget the checker defends. (2) `STATUS_RATCHET = {"chars": 243245}` (`check-public-doc-tables.py:557`) is a hardcoded byte count of a DIFFERENT file that may only fall, so a PR owing `docs/STATUS.md` one lifecycle line must delete unrelated prose from another row to pay for it and edit the checker too; the checker's own comment at `:331` already records the failure (*"a ratchet pinned to the byte turns every concurrently merged row's one-line status edit into a spurious failure"*) and answered it with slack instead of removing the coupling. (3) `.agents/coordination.md`'s active-claims table is insert-at-one-anchor: the six ROCm GDN PRs (#334 #336 #341 #343 #345 #348) are ONE author's sequential stack that conflicts on nothing else, each appending a ~1,500-char row — the PR description, transcribed into a file every other claim also writes. It also contradicts the protocol it serves: `AGENTS.md` holds that *"History is git"* and *"There is no state log"*, yet both claims tables ARE state logs duplicating `gh pr list`, `row/` branch names and issue state; the argument that refuses a waiver registry applies unchanged to a claims registry. Precedent twice over — `policy.csv` retired in `0f3e44ee`, per-class line budgets retired 2026-08-10 because the gate fired on ordinary work. The exonerated surfaces share ONE property, one writer per file: `.agents/specs/.md` (one file per row, **zero conflicts** in the sample), the `*-matrix.md` inventories, and the append-only `.agents/benchmark-record.md`. SCOPE: remove `STATUS_RATCHET` and the doc-gating global counters while KEEPING the per-cell/per-paragraph caps (local, so they couple nothing); remove the active-claims table and derive claims from open PRs and branch names; drop `NOW.md`'s byte budget; order the roadmap's keyed tables by ID so distinct keys stop colliding at one anchor; and record the invariant — **no surface that every PR must write** — in `AGENTS.md`. No product source, kernel or gate semantic moves | T0 | NO vLLM analogue — this is local protocol machinery, so the mirror rule does not apply and no upstream `file:line` exists to port from. Governed instead by `AGENTS.md` §"Changing the rules or a checker", which requires a spec, a red-before test or mutation, and green-after evidence | - | - (spec-before-code: the red-before suites are named in the spec's Tests section — `tests/scripts/test_check_public_doc_tables.py`, `tests/scripts/test_check_now_current.py`, a mutation case per removed rule proving the obligation survives in the retained caps and `check-doc-checkpoint.py`, and a `git merge-tree` merge-shape regression that must be RED before the `NOW.md`/roadmap work and GREEN after) | [retire-shared-record-surfaces.md](specs/retire-shared-record-surfaces.md); issue [#364](https://github.com/mudler/vllm.cpp/issues/364) | `READY` | `CLAIM-ENG-RECORD-CONFLICT-SURFACES` | -| `ENG-TRAILER-MERGE-ARTIFACTS` | The trailer gate rejects CORRECT commits because of paragraph placement, and that is why `main` is red on `agent-record`. `check-commit-trailers.py` reads trailers via `git interpret-trailers --parse`, which treats ONLY the final paragraph as the block; GitHub appends `Co-authored-by:` as a SEPARATE trailing paragraph on a squash merge, so a complete correct block becomes invisible and the gate reports it missing. MEASURED: piping `git show -s --format=%B dbd0d51c` into `git interpret-trailers --parse` prints nothing but the co-author line, and 13 of the last 30 commits on `main` fail the check -- unnoticed only because those runs were cancelled (#274), which HID the defect rather than causing it. FIX: fuse consecutive trailing TRAILER-SHAPED paragraphs before parsing. Nothing is relaxed -- the block must still exist, the marker must still sit above it, each declaration must still appear exactly once, and an AI co-author is still forbidden; the block is merely FOUND where the merge tool left it. A prose paragraph still terminates it. REJECTED IN FLIGHT and recorded because it is the more instructive half: a first attempt also collapsed identical duplicate trailers to fix the multi-commit-squash shape, which relaxes the uniqueness rule an existing test already pins. Rewriting that assertion to suit the change is what AGENTS.md forbids, and the distinction is real -- a doubled block is genuinely malformed and fixable at source, whereas the co-author case is a correct commit defeated by the parser. Reverted in full. SCOPE LIMIT, stated rather than implied: this fixes ONE of five observed shapes. `f64f2b71` (bot co-author) is a REAL violation the parse had been hiding and now correctly fails; `87308dea` (GitHub's `---------` separator), `b8293c88` (squash doubled the block) and `b580452d` (merge button, no trailers) stay red by design. Closing those is a merge-method change, not a checker change | T0 | NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream `file:line` to port from. Governed by `AGENTS.md` §"Changing the rules or a checker" | `scripts/check-commit-trailers.py:60` (`join_trailing_trailer_paragraphs`, `_is_trailer_paragraph`, and the fused `parsed_trailers`) | `tests/scripts/test_check_commit_trailers.py:1` 21 cases -- the RED-BEFORE appended-co-author case plus four GUARDS that keep the fusion bounded (doubled block still fails, contradictory declarations still fail, a no-trailer merge message still fails, prose after the block still fails), all four green before and after | [trailer-merge-artifacts.md](specs/trailer-merge-artifacts.md); issue [#406](https://github.com/mudler/vllm.cpp/issues/406) | `ACTIVE` | `CLAIM-ENG-TRAILER-MERGE-ARTIFACTS` | +| `ENG-TRAILER-MERGE-ARTIFACTS` | The trailer gate rejects CORRECT commits because of paragraph placement, and that is why `main` is red on `agent-record`. `check-commit-trailers.py` reads trailers via `git interpret-trailers --parse`, which treats ONLY the final paragraph as the block; GitHub appends `Co-authored-by:` as a SEPARATE trailing paragraph on a squash merge, so a complete correct block becomes invisible and the gate reports it missing. MEASURED: piping `git show -s --format=%B dbd0d51c` into `git interpret-trailers --parse` prints nothing but the co-author line, and 13 of the last 30 commits on `main` fail the check -- unnoticed only because those runs were cancelled (#274), which HID the defect rather than causing it. FIX: fuse consecutive trailing TRAILER-SHAPED paragraphs before parsing. Nothing is relaxed -- the block must still exist, the marker must still sit above it, each declaration must still appear exactly once, and an AI co-author is still forbidden; the block is merely FOUND where the merge tool left it. A prose paragraph still terminates it. REJECTED IN FLIGHT and recorded because it is the more instructive half: a first attempt also collapsed identical duplicate trailers to fix the multi-commit-squash shape, which relaxes the uniqueness rule an existing test already pins. Rewriting that assertion to suit the change is what AGENTS.md forbids, and the distinction is real -- a doubled block is genuinely malformed and fixable at source, whereas the co-author case is a correct commit defeated by the parser. Reverted in full. SCOPE LIMIT, stated rather than implied: this fixes ONE of five observed shapes. `f64f2b71` (bot co-author) is a REAL violation the parse had been hiding and now correctly fails; `87308dea` (GitHub's `---------` separator), `b8293c88` (squash doubled the block) and `b580452d` (merge button, no trailers) stay red by design. Closing those is a merge-method change, not a checker change | T0 | NO vLLM analogue -- local protocol machinery, so the mirror rule does not apply and there is no upstream `file:line` to port from. Governed by `AGENTS.md` §"Changing the rules or a checker" | `scripts/check-commit-trailers.py:60` (`join_trailing_trailer_paragraphs`, `_is_trailer_paragraph`, and the fused `parsed_trailers`) | `tests/scripts/test_check_commit_trailers.py:1` 21 cases -- the RED-BEFORE appended-co-author case plus four GUARDS that keep the fusion bounded (doubled block still fails, contradictory declarations still fail, a no-trailer merge message still fails, prose after the block still fails), all four green before and after; closure [parity-ledger.md#L941](parity-ledger.md#L941) | [trailer-merge-artifacts.md](specs/trailer-merge-artifacts.md); issue [#406](https://github.com/mudler/vllm.cpp/issues/406) | `DONE` | `157080c8` | | `ENG-NOW-DERIVED` | W1-W5 remove the per-row `.agents/NOW.md` write: each moved row's own spec carries `## Now`, `scripts/now.py` renders the live roster offline-first, and the digest cannot regrow a row table. Implementation merge `dbd0d51c`; progressive legacy-spec backfill is the selected compatibility policy, not remaining work. Runtime/performance/parity are `VOID` because this is local protocol machinery | T0 | No vLLM analogue; governed by `AGENTS.md` §Changing the rules or a checker | `scripts/now.py:163`; `scripts/check-doc-checkpoint.py:181`; `scripts/check-now-current.py:57` | `tests/scripts/test_doc_checkpoint.py:142`; `tests/scripts/test_now_render.py:34`; `tests/scripts/test_check_now_current.py:1`; closure [parity-ledger.md#L939](parity-ledger.md#L939) | [now-derived.md](specs/now-derived.md); issue [#374](https://github.com/mudler/vllm.cpp/issues/374) | `DONE` | `dbd0d51c` | | `SERVE-CLI-CHAT` | Interactive `chat` and `complete` commands against a running OpenAI-compatible server, plus preservation of the existing local-model completion invocation | T1 | registration `vllm/entrypoints/cli/main.py:17-37,73-98`; client/model resolution + stream shaping `vllm/entrypoints/cli/openai.py:30-100`; chat `:155-234`; complete `:237-312` at `5559679229` | current in-process completion only `examples/cli/main.cpp:1-207`; remote command implementation absent | C-ABI stream baseline `tests/capi/test_capi.cpp:567-711`; chat-template baseline `tests/capi/test_chat_prompt.cpp:37-89`; command/fake-server tests absent | [cli-chat-complete.md](specs/cli-chat-complete.md) | `ANCHOR-BACKFILL` | `CLAIM-SERVE-CLI-CHAT-SPIKE` | | `SERVE-POOLING-ENDPOINTS` | Embeddings, pooling, score, rerank, classify HTTP surface (`/v1/embeddings`, `/pooling`, `/score`, `/rerank`, `/classify`). **SPIKED 2026-07-28 (`CLAIM-POOLING`):** the whole pooling task class is scoped in [pooling-task-class.md](specs/pooling-task-class.md). **`/v1/embeddings` LIVE 2026-08-08 (ARCH-ONE-SURFACE ROW 6, `CLAIM-EMBEDDINGS-ONE-SURFACE`):** task-conditional registration (embed/api_router.py:22-28 mirror; the route exists ONLY on a pooling-model server, and the generate routes do not — both directions socket-404-pinned), OpenAI request/response shape (string-or-array input; `dimensions`/base64/token-arrays are named-residual 400s), handler drives the ONE engine path (`LoadedEngine -> LLMEngine::embed -> registry forward -> PoolingRunner`) — the same path `vllm_embed` (ABI v15) drives. RESIDUALS: `/pooling`, `/score`, `/rerank`, `/classify` (need a classify arch) | T2 | `vllm/entrypoints/pooling/embed/api_router.py:28`; `vllm/entrypoints/pooling/embed/protocol.py:34,173-185`; `vllm/entrypoints/pooling/scoring/api_router.py:37,71`; `vllm/entrypoints/pooling/classify/api_router.py:26` | `src/vllm/entrypoints/openai/api_server.cpp` `handle_embeddings` + the `if (embedder_)` route gate; `examples/server/main.cpp` pooling task dispatch | `tests/vllm/entrypoints/openai/test_api_server.cpp` embeddings section (dispatch shape + socket smoke + BOTH-direction 404 pins) | [embeddings-one-surface.md](specs/embeddings-one-surface.md) | `ACTIVE` | `CLAIM-EMBEDDINGS-ONE-SURFACE` | diff --git a/.agents/parity-ledger.md b/.agents/parity-ledger.md index 5c2fc625c..5534f5284 100644 --- a/.agents/parity-ledger.md +++ b/.agents/parity-ledger.md @@ -938,3 +938,4 @@ Columns: | 2026-08-08 (`KERNEL-SSM-MAMBA`; sm_120 causal-conv K4/channel-tile residual; local-4B only) | Adds same-binary K=4 causal-conv arms: `VT_CONV_CHANNEL_TILE=1` specializes width at the current 128-channel tile; `=2` also gives each thread two channels/256-channel tile. Unset/`0` keeps the runtime-width kernel. A shared portable/production dispatcher is mutation-gated. | Pinned vLLM `_causal_conv1d_fwd_kernel` compile-time `KERNEL_WIDTH`, `BLOCK_M=8`, `BLOCK_N=256` in `causal_conv1d.py:16-63,78-79,692-742`; local `cuda_gdn.cu`, `gdn_prefill_conv.h`, portable/CUDA tests; [spike/result](specs/sm120-qwen35-conv-channel-tile-2026-08-08.md). | **ARM 1 IMPLEMENTED OPT-IN; ARM 2 FALSIFIED.** Byte-exact rebuilt same-binary trace: arm 1 **234.605→219.506 ms (-6.44%)**, enclosing total/output +0.122%, TTFT -0.282%, TPOT -0.086%; vLLM residual **1.508x**. Arm 2 is 228.401 ms, 4.05% slower than arm 1 and enclosing-neutral/negative. Registers 43→52→58 refute the occupancy thesis. Portable 9/9·88, CUDA GDN 67/67·4631, paged-forward 4/4·8; default/repeated and 27B/35B gates OPEN. | | 2026-08-11 (`ENG-NOW-DERIVED`; implementation merge `dbd0d51c`, issue #374) | W1-W5 replace the per-row `.agents/NOW.md` write with each moved row spec's `## Now`, add the offline-first `scripts/now.py` renderer, and prevent digest table regrowth. Progressive backfill is the selected compatibility policy. | No vLLM analogue: local protocol/checker machinery governed by `AGENTS.md`; nothing was ported. | **VOID for runtime correctness, performance, memory, and vLLM parity.** Paired record suites prove STATUS/BENCHMARKS remain lifecycle projections, the row spec carries the live position, NOW-free lifecycle changes pass, missing/empty `## Now` fails, offline rendering reports `REMOTE_UNVERIFIED`, and restoring either eliminated obligation fails. Product behavior is untouched. | | 2026-08-10 (**`FUSION-DENSE-MIGRATE` — the merged-GEMM allowlist's no-blocker half CLOSED**; issue [#299](https://github.com/mudler/vllm.cpp/issues/299), spec `specs/fusion-dense-migrate.md`; `row/FUSION-DENSE-MIGRATE`, base `origin/main` `c70f42b9` (rebased from the `e17e8f8a` pinned at worktree creation, via `688eea12`), isolated worktree `/home/mudler/_git/vllm.cpp-fusion-fold`; CPU-only, `benchmark_binding=false`) | Routes the gate/up of the five plain bf16 dense SwiGLU MLPs that bypassed the MUST-route merged-GEMM seam with no stated blocker — `commandr`, `glm4`, `minicpm`, `minicpm3`, `phi3` — through `layers::UnquantizedMlpGateUpMethod`, and deletes their five `pending FOLD-MIGRATE` entries from `scripts/merged-gemm-consistency-allowlist.txt` (11 → 6). The six survivors all name a blocker that needs the SHARED LAYER extended (f32 activations + rank-1 biases, ggml block-quant vs the explicitly UNQUANTIZED arm, up-front device staging vs `OwnedTensor`/`ResidentWeight` residency, a GeGLU arm on the SwiGLU-only grouped MoE op for `gemma4_moe`, an NVFP4-Marlin-resident arm for `laguna`'s raw-device-pointer w13) and were NOT touched: extending the seam is its own row. The `gemma4_moe` and `laguna` reasons were REWRITTEN in this branch: both previously read as a bare `pending fold`, which is the vague reason this row's own thesis says let the allowlist grow. Direct Unquantized arm, not `MakeMlpGateUpMethod` — no loader for the three `Qwen3DenseMlpWeights` models ever populates `*_fp4`. Shared-layer TUs (`linear.h`/`nvfp4.h`) and every `vt::` op UNTOUCHED. No env flag: the fold is unconditional and bit-exact, so a rollback arm would be dead code. | Upstream expresses all five as ONE `MergedColumnParallelLinear(gate_up_proj, output_sizes=[I]*2)` + `SiluAndMul()` at pin `555967922` (0.26.0.dev0): `commandr.py:91,102-108,116`; `glm4.py:46` → `llama.py:79,92-99,113`; `minicpm.py:193,204-211,219`; `minicpm3.py:186` (inherits `MiniCPMMLP`); `phi3.py:10` → `llama.py:79`. The fold moves us TOWARD that shape; no new upstream code was ported. | **BYTE-EXACT BY CONSTRUCTION, and that construction is what was gated** (a routing change, so the bar is op-sequence identity, never a tolerance). Each replaced body was the seam's own `{ResidentWeight; MatmulBT[2I,H]; SiluAndMul}` with `M` spelled `T`, and every call site passes a `DBuf{T,H}` so `x.shape[0] == T` identically. NEW byte-exact CPU case in `test_linear_method` for the DIRECTLY-constructed arm at BOTH the decode shape (M=1) and a prefill shape (M=4) vs the standalone sequence — RED-first PROVEN (mutating the seam's `SiluAndMul`→`GeluAndMul` fails 2 cases / 11 assertions; GREEN byte-for-byte on restore) → **6 cases / 76 assertions GREEN**. `check-fusion-consistency.py` RC=0 with 0 drift; two NEW mutation cases in `tests/scripts/test_check_fusion_consistency.py` make BOTH regressions RED (re-allowlisting a folded stem; reverting a fold) → **20/20**. MECHANICAL CORRECTION to issue #299: a fully-folded TU has NO hand-call left, so it leaves the detector's DENOMINATOR rather than entering its numerator — the checker reads `15 scanned / 6 routed / 11 allowlisted` → `10 / 6 / 6`, not the `11 routed / 15` the issue predicted; drift is 0 either way, which is what the gate asserts. Full CPU `ctest -j 6` on the final rebased base `60e71a0e`: **369/369, 0 failed**, 1288.75 s. RE-RUN on the MERGED head `4b99cefb` (after merging `origin/main` `5812b8b6` and adding the new coverage binary): **369/370, 1 failed**, 1441.85 s — the single failure is `test_engine_core_proc`, a STARVATION FLAKE and not a regression: serially on the same binary it is **10/10 cases, 93 assertions GREEN**, whereas under `-j 6` at load average ~170 (two other worktrees running their own suites) it failed in 0.06 s on `CHECK(abort_seen)` (`test_engine_core_proc.cpp:345`) having spun to 1089 assertions waiting for the abort. It is one of the four known starvation-prone binaries, loads none of the five folded TUs, and the other three passed in this run. `test_dense_gate_up_seam_forward` passed inside the suite (32.96 s), proving the new binary is registered and wired. An earlier run on the intermediate base read **367/369**, and both numbers are reported rather than the red one deleted: `test_async_llm` and `test_openai_conformance` failed while a SECOND worktree ran its own suite at load average 89-122, and re-run alone on a quiet box (load 12.8) passed in **0.04 s** and **20.76 s** (vs 605 s of `statuses == -1`, the client's 30 s read timeout, under load); `test_openai_conformance` builds a synthetic `Qwen3_5MoeForConditionalGeneration` in-process and loads none of the five folded TUs, so it could not be this row's, and the clean 369/369 settles it. The #274 ASan/UBSan five did not appear in either run — this gate is Release with no sanitizer. **OWED / NOT CLAIMED:** the five paged-engine SACRED gates (`test_{commandr,glm4,minicpm,minicpm3,phi3}_paged_engine`) are checkpoint-gated dgx-only and emit a loud SKIP on a CPU box, so empirical token-exact confirmation is PENDING for the next GPU holder — the same shape A1 carried for Granite/StableLM — and is tracked by [#337](https://github.com/mudler/vllm.cpp/issues/337) so the handle outlives #299. EXECUTED CPU COVERAGE OF THE FOLDED TUs (added on review finding F4, which proved that mutating `phi3`'s `I` to `I - 1` at the call site survived 176 CPU tests): NEW `tests/vllm/models/test_dense_gate_up_seam_forward.cpp` drives the REAL forward of four of the five folded TUs (`commandr`/`glm4`/`minicpm`/`phi3`) over synthetic in-memory weights with no checkpoint and no GPU — **4 cases / 1940 assertions GREEN** — pinning the gate/up split analytically (zeroing the UP half and zeroing `down_proj` both make the MLP contribute exactly zero, so they must be BYTE-IDENTICAL, which holds only at a split of exactly `I`) plus the half order and a vacuity guard. RED-first EXECUTED both ways: `I` → `I - 1` at all four call sites fails all four cases (`phi3` alone fails only its own, so each TU is genuinely reached), and a SHAPE-PRESERVING mutation of `vt::SiluAndMul`'s CPU kernel (`silu * up` → `silu + up`) fails all four on the split assertion itself while `test_linear_method` stays GREEN at 76/76 — a defect class the seam unit test structurally cannot see. Both restored byte-for-byte (md5 verified). This also retires the row's original "no e2e evidence is possible on a CPU box" framing as too strong: ORACLE evidence needs the GPU, SELF-CONSISTENCY evidence does not. `minicpm3` is the one folded TU that harness does not drive (MLA + load-time `kv_b_proj` absorption belong to the DeepSeek-V2 synthetic harness). Also REJECTED as evidence: an object-code A/B — compiling each of the five TUs from main's source and from the folded source with the identical production command and diffing the disassembly gives 3689-6888 differing instruction lines per TU, which is GCC re-allocating registers around a header-inlined method, not a numerical signal in either direction. STATED RATHER THAN HIDDEN: the OP sequence is identical but the ALLOCATION sequence is not — `DBuf` is pooled and returns its block on destruction (`dense_device_glue.h:99`), so the `[T,2I]` gate_up buffer is now released when `Apply` returns instead of at the end of the MLP block and the `[T,H]` output may reuse it. That cannot move a value (`vt::MatmulBT` writes every output element from a fresh f32 accumulator rather than accumulating into `out`) and peak pool usage is unchanged or lower; it is the same shape every earlier fold produced. ALSO REPOINTED: `glm4`/`phi3` sit on the OTHER (glue) allowlist reading `pending FUSION-DENSE-MIGRATE`; closing this row would leave both aimed at closed work, so their reasons now name [#314](https://github.com/mudler/vllm.cpp/issues/314), which owns the glue half — the glue fold itself is NOT done here. | +| 2026-08-11 (`ENG-TRAILER-MERGE-ARTIFACTS`; implementation merge `157080c8`, issue [#406](https://github.com/mudler/vllm.cpp/issues/406)) | The trailer gate was rejecting CORRECT commits. `check-commit-trailers.py` reads through `git interpret-trailers --parse`, which treats only the FINAL paragraph as the block, and GitHub appends `Co-authored-by:` as a separate trailing paragraph on squash merge — so a complete block became invisible and 13 of the last 30 commits on `main` failed the check, unnoticed because those runs were cancelled (#274). Fixed by fusing consecutive trailing TRAILER-SHAPED paragraphs before parsing; no rule relaxed, and a prose paragraph still terminates the block. | `test_check_commit_trailers.py` 21/21 — the RED-BEFORE appended-co-author case plus four guards (doubled block, contradictory declarations, no-trailer merge message, prose after the block) green before and after; the five real `main` commits re-verified per commit and the verdict table reproduces. | Closes ONE of five shapes. `f64f2b71` (bot co-author) is a REAL violation the parse had hidden and now correctly fails; `87308dea`, `b8293c88` and `b580452d` stay red by design — merge-method artifacts, not checker defects. A first attempt that also collapsed identical duplicate trailers was REVERTED in full: it relaxed a uniqueness rule an existing test pins. | diff --git a/.agents/specs/trailer-merge-artifacts.md b/.agents/specs/trailer-merge-artifacts.md index 2c78872a0..643ab838b 100644 --- a/.agents/specs/trailer-merge-artifacts.md +++ b/.agents/specs/trailer-merge-artifacts.md @@ -148,9 +148,35 @@ forbidden-AI-trailer rule. Those are the guarantees the gate exists to hold. ## Now -W3 done; the row is landing. Next: decide the merge-method change that closes the -four remaining shapes, which is process, not checker. +`DONE` at `157080c8`. Nothing scheduled. The merge-method decision that would +close the remaining four shapes is a separate question, recorded in Outcome. ## Outcome -Pending. +Landed `157080c8` (PR #409). One of five observed shapes fixed, and that is the +honest measure of this row. + +**What was measured.** Fusing consecutive trailing trailer-shaped paragraphs +makes `dbd0d51c` pass, where it had been failing while carrying a complete, +correct trailer block. The other four commits keep their prior verdicts, which is +the intent. + +**What the fix newly surfaced.** `f64f2b71` names a BOT co-author. That is a real +`AGENTS.md` violation which the broken parse had been hiding, so making the block +visible turned a silent pass into a correct failure. Worth stating because it +looks like a regression and is the opposite. + +**What was rejected, and why it is the more useful half.** The first attempt also +collapsed identical duplicate trailers, to fix the multi-commit-squash shape. An +existing test, `test_protocol_and_ai_declarations_are_unique_and_exact`, pins that +uniqueness rule. Rewriting an assertion to suit the change is what `AGENTS.md` +forbids, and the distinction turned out to be substantive rather than procedural: +a doubled block is a genuinely malformed message fixable at source, whereas the +`Co-authored-by` case is a correct commit defeated by the parser. Reverted in +full; `b8293c88` stays red deliberately. + +**What is still open.** Four of five shapes are merge-method artifacts — GitHub's +`---------` squash separator, the doubled block, the trailer-less merge-button +message, and bot co-authors. Closing them means changing how commits land, not +what the checker accepts. That decision is the developer's, and it is the reason +this row does not claim to have made `main` green. diff --git a/scripts/check-gate-commands.py b/scripts/check-gate-commands.py index ef5bd2e84..a87ad61ef 100755 --- a/scripts/check-gate-commands.py +++ b/scripts/check-gate-commands.py @@ -275,15 +275,12 @@ def audit() -> list[dict]: # baseline member. All three departures are the same lifecycle-policy closure, # not downgraded verdicts or hidden work. Re-adding DONE to GATED_STATES is the # load-bearing mutation pinned in the paired suite. -# 2026-08-11: +ENG-TRAILER-MERGE-ARTIFACTS. The row reaches ACTIVE on its -# committed spec (issue #406), whose Gates section names the preflight, -# tests/scripts and agent-integration invocations plus the per-commit -# re-verification of the five real main commits, and records that no -# CUDA/GPU/SACRED gate is implicated because no product source is touched. -# Growth, so the set is re-pinned in the same change. +# 2026-08-11: +ENG-TRAILER-MERGE-ARTIFACTS on arrival at ACTIVE, then REMOVED +# the same day on reaching DONE (closing commit 157080c8) -- a DONE row leaves +# the gated population, so its verdict is None rather than a downgraded one. +# A shrink for a real record edit, named as the message demands. RUNNABLE_BASELINE = frozenset({ "ATTN-CHUNKED-LOCAL", - "ENG-TRAILER-MERGE-ARTIFACTS", "ENG-RECORD-CONFLICT-SURFACES", "SAMPLE-PROMPT-LOGPROBS", "ATTN-ROPE-FAMILY", diff --git a/tests/scripts/test_check_gate_commands.py b/tests/scripts/test_check_gate_commands.py index 29c4c7439..3f228a516 100644 --- a/tests/scripts/test_check_gate_commands.py +++ b/tests/scripts/test_check_gate_commands.py @@ -274,7 +274,7 @@ def test_now_derived_left_the_gated_population_cleanly(self): self.assertNotIn("ENG-NOW-DERIVED", gates.RUNNABLE_BASELINE) def test_re_adding_done_to_the_gated_population_breaks_the_pin(self): - # MUTATION: restoring the departed lifecycle state must expose the three + # MUTATION: restoring the departed lifecycle state must expose the four # runnable DONE rows and disagree with the re-pinned baseline. original = gates.GATED_STATES gates.GATED_STATES = frozenset(original | {"DONE"}) @@ -284,30 +284,23 @@ def test_re_adding_done_to_the_gated_population_breaks_the_pin(self): } finally: gates.GATED_STATES = original - departed = {"ENG-ASYNC-SCHED", "SERVE-HTTP-TRANSPORT", "ENG-NOW-DERIVED"} + departed = { + "ENG-ASYNC-SCHED", + "SERVE-HTTP-TRANSPORT", + "ENG-NOW-DERIVED", + "ENG-TRAILER-MERGE-ARTIFACTS", + } self.assertEqual(runnable - set(gates.RUNNABLE_BASELINE), departed) self.assertNotEqual(runnable, set(gates.RUNNABLE_BASELINE)) - def test_trailer_merge_artifacts_is_credited_for_real_commands(self): - # ENG-TRAILER-MERGE-ARTIFACTS (#406) joins the runnable population on - # arrival, so it earns the credit the same way: its spec's Gates section - # must name commands that can actually fail. Its gate is the record gate - # plus a per-commit re-verification of the five real main commits. + def test_trailer_merge_artifacts_left_the_gated_population_cleanly(self): + # Credited runnable on arrival at ACTIVE, then gone the same day on + # reaching DONE (157080c8). Assert the departure on BOTH sides -- gone + # from the audit AND gone from the baseline -- because a row present in + # one and not the other is exactly what the exact pin exists to catch. verdicts = {r["id"]: r["verdict"] for r in gates.audit()} - self.assertEqual(verdicts.get("ENG-TRAILER-MERGE-ARTIFACTS"), "runnable") - spec = (ROOT / ".agents/specs/trailer-merge-artifacts.md").read_text( - encoding="utf-8" - ) - for command in ("scripts/agent-preflight.sh", "agent-integration.py"): - with self.subTest(command=command): - self.assertIn(command, spec) - - def test_the_trailer_row_re_pin_is_load_bearing(self): - # MUTATION: drop the entry and the exact pin must break. - reduced = set(gates.RUNNABLE_BASELINE) - {"ENG-TRAILER-MERGE-ARTIFACTS"} - runnable = {r["id"] for r in gates.audit() if r["verdict"] == "runnable"} - self.assertNotEqual(runnable, reduced) - self.assertEqual(runnable, set(gates.RUNNABLE_BASELINE)) + self.assertIsNone(verdicts.get("ENG-TRAILER-MERGE-ARTIFACTS")) + self.assertNotIn("ENG-TRAILER-MERGE-ARTIFACTS", gates.RUNNABLE_BASELINE) def test_record_conflict_surfaces_is_credited_for_real_commands(self): # ENG-RECORD-CONFLICT-SURFACES (#364) joined the runnable population on