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
5 changes: 5 additions & 0 deletions .agents/claims/CLAIM-SERVE-RECIPE-ARGS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# CLAIM-SERVE-RECIPE-ARGS

| Claim | Row IDs | Agent | Worktree / remote dir | Branch | Owned scope | State | Last update |
|---|---|---|---|---|---|---|---|
| `CLAIM-SERVE-RECIPE-ARGS` | `SERVE-RECIPE-ARGS` (`SPIKE`) | Claude Code (opus-5), operator role — spec only; implementation goes to a fresh implementer | isolated worktree; no GPU, no oracle run, no publication | `row/serve-recipe-args`, issue [#606](https://github.com/mudler/vllm.cpp/issues/606) | Owns ONLY: NEW `.agents/specs/serve-recipe-args.md`; the NEW `SERVE-RECIPE-ARGS` row plus the two summary counts it moves in `.agents/engine-matrix.md`; and, at implementation time, the accepted-and-inert table in `src/vllm/entrypoints/openai/server_main.cpp`, its `docs/USAGE.md` entries, and its RED-first tests. EXCLUDES `--language-model-only` (#607, a real capability gap), the `--tool-call-parser` default (`hermes` vs upstream `None`, pre-existing and out of scope), and every flag that is inert because we lack the capability — TP, EP, `--mm-encoder-tp-mode` — which must keep aborting | `SPIKE` | 2026-08-13 — spec committed; implementation not started |
5 changes: 3 additions & 2 deletions .agents/engine-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,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 | 32 | 10 | 2 | 0 | 2 | 9 | 2 | 3 | 4 |
| Serving, API, CLI, library | 33 | 10 | 2 | 0 | 2 | 10 | 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** | **152** | **35** | **16** | **4** | **9** | **29** | **8** | **11** | **39** |
| **Total** | **153** | **35** | **16** | **4** | **9** | **30** | **8** | **11** | **39** |

## Engine core and scheduling

Expand Down Expand Up @@ -219,6 +219,7 @@ claims it.
| `ENG-FORGE-COAUTHOR` | The forbidden-AI-trailer rule was catching ATTRIBUTION rather than an authorship claim, which is why bot-opened PRs red `main` on merge. GitHub composes the squash message itself and appends the account that opened the PR — `Co-authored-by: localai-org-maint-bot <...@users.noreply.github.com>` — and most PRs here are opened by a bot, so nearly every squash trips the AI-identity check. Real instance `f64f2b71`, invisible until #406 repaired the parse, which is why it reads as a new failure and is not one. The rule exists so an AI cannot claim it WROTE the code, and that stays; GitHub is recording who pressed the button, and the AI-involvement claim is already carried separately by `AI-Assisted` and `Assisted-by` in the same block. FIX: accept a `Co-authored-by` at a GitHub account noreply address even when the name matches an AI identity token, keyed on the FORGE'S OWN DOMAIN rather than the name so the exemption cannot be borrowed. A hand-written `Co-authored-by: Claude <claude@anthropic.com>` still fails; `Signed-off-by` is excluded from the exemption entirely, because a sign-off is a legal assertion about provenance rather than attribution. `AGENTS.md` records the same distinction in the same change so prose and checker cannot drift | 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:38` (`FORGE_ACCOUNT_EMAIL` and the forbidden-trailer skip) | `tests/scripts/test_check_commit_trailers.py:1` 25 cases -- the RED-BEFORE forge-bot case plus THREE guards that matter more than the relaxation because this LOOSENS a rule: a hand-written AI co-author still fails, `Signed-off-by` at the same noreply address still fails, and a human co-author still passes; all three green before and after. Real commit `f64f2b71` re-verified per commit | [forge-coauthor-attribution.md](specs/forge-coauthor-attribution.md); issue [#418](https://github.com/mudler/vllm.cpp/issues/418) | `ACTIVE` | `CLAIM-ENG-FORGE-COAUTHOR` |
| `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-RECIPE-ARGS` | Accepted-and-inert serve arguments: an enumerated table of flags that published recipes pass, that are no-ops for this engine, and that must therefore not abort argument parsing. Not a catch-all — anything unlisted still aborts, and mirrored validation still fires. Found by the 2026-08-13 recipe-surface sweep: `vllm-serve` rejects unknown arguments (`src/vllm/entrypoints/openai/server_main.cpp:440`), so `--enable-auto-tool-choice` (89/157 official recipes) and `--trust-remote-code` (82/157) stop the server before model load even though neither means anything here — including for models we ship token-exact and gated | T1 | `vllm/entrypoints/openai/cli_args.py:105` (`enable_auto_tool_choice` default), `:395` (requires `--tool-call-parser`, a `TypeError` otherwise — mirrored, not dropped); threading `vllm/entrypoints/openai/api_server.py:426,441,529,544` at `5559679229` | `src/vllm/entrypoints/openai/server_main.cpp:289` (`kAcceptedInertArgs`, the enumerated table), `:312` (`FindAcceptedInertArg` — returns `nullptr` for anything unlisted, so the existing `unknown argument` abort is untouched), `:505` (the parse branch + the per-flag notice), `:560` (the mirrored `cli_args.py:395` validation); `docs/USAGE.md` § "Accepted for recipe compatibility" | `tests/vllm/entrypoints/openai/test_serve_recipe_args.cpp:141` (listed flags reach model load), `:165` (an unlisted flag STILL aborts — the load-bearing case), `:188` (the mirrored `cli_args.py:395` refusal), `:212` (the per-flag notice); registered `tests/CMakeLists.txt:877`. 4 cases / 58 asserts GREEN; RED-first against the pre-change binary (17 failed, `Status: FAILURE!`). Each case re-execs the binary into the REAL `VllmServerMain`. MUTATION PROVEN in a scratch copy: widening `FindAcceptedInertArg` into a catch-all turns exactly `:165` RED (8 asserts) and leaves the other three GREEN | [serve-recipe-args.md](specs/serve-recipe-args.md) | `ACTIVE` | `CLAIM-SERVE-RECIPE-ARGS` |
| `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` |
| `ENG-POOLER-SEQ` | The non-generative POOLER OP — turn hidden states into a pooled embedding/logit row instead of a sampled token. **W1 LANDED + CPU-GATED 2026-07-28 (`CLAIM-POOLING`, NOT pushed):** the sequence pooling methods `CLSPool`/`LastPool`/`MeanPool` (+ `GetSeqPoolingMethod` factory) over a packed `[num_tokens, hidden]` CPU buffer keyed by a minimal `PoolingCursor` (CLS/MEAN reject partial prefill, LAST allows it, MeanPool upcasts to float32) and the activation heads `PoolerIdentity`/`PoolerNormalize` (L2 `F.normalize`)/`PoolerMultiLabelClassify` (sigmoid)/`PoolerClassify` (sigmoid if `num_labels<2` else `softmax`). Unit-gated vs DOUBLE-PRECISION references, RED-first. **W2 LANDED + CPU-GATED 2026-07-29 (`CLAIM-POOLING`, NOT pushed):** the pooler HEADS composite (`EmbeddingPoolerHead` = projector→matryoshka→normalize; `ClassifierPoolerHead` = classifier→`(logit-mean)/sigma`→activation), the `SequencePooler` (method∩head task intersection) + `PoolerForEmbed`/`PoolerForClassify` factories, the `DispatchPooler` groupby-task routing (`ForEmbedding`/`ForSeqCls` + a mixed embed+classify batch + ctor task-support validation), and the `PoolerConfig`/`PoolingParams`/`PoolingParamsUpdate` structs; `test_pooler_heads` 27/27 (240 asserts) vs double-precision refs, RED-first (disable matryoshka slice + logit_mean calibration → 8 cases / 50 asserts fail). RESIDUALS (named, spec §Work breakdown): the endpoints (W4), tokwise `AllPool`/`StepPool` (W5), a concrete pooling MODEL + real-oracle cosine gate (W3-model — see `ENG-POOLING-RUNNER`) | T2 | `vllm/model_executor/layers/pooler/seqwise/methods.py:35-121`; `vllm/model_executor/layers/pooler/activations.py:106-158`; `vllm/model_executor/layers/pooler/seqwise/heads.py:19-196`; `vllm/model_executor/layers/pooler/seqwise/poolers.py:41-138`; `vllm/model_executor/layers/pooler/special.py:23-140`; `vllm/model_executor/layers/pooler/common.py:12-30`; `vllm/pooling_params.py:35-70`; `vllm/config/pooler.py:16-90`; `vllm/v1/pool/metadata.py:13-71`; `tests/model_executor/layers/test_pooler_methods.py`, `tests/model_executor/layers/test_pooler_activations.py`, `tests/model_executor/layers/test_pooler_heads.py` | `include/vllm/model_executor/layers/pooler/{methods,activations,pooling_metadata,common,pooling_params,pooler_config,heads,poolers,dispatch_pooler}.h` + `src/vllm/model_executor/layers/pooler/{methods,activations,heads,poolers,dispatch_pooler}.cpp` — anchor `src/vllm/model_executor/layers/pooler/dispatch_pooler.cpp:13` | `tests/vllm/model_executor/layers/pooler/test_pooler.cpp` (CLS/LAST/MEAN + factory + activations, 50 asserts) + `test_pooler_heads.cpp` (Embedding/Classifier heads + SequencePooler + DispatchPooler, 240 asserts) — anchor `tests/vllm/model_executor/layers/pooler/test_pooler.cpp:81` | [pooling-task-class.md](specs/pooling-task-class.md) | `ACTIVE` | `CLAIM-POOLING` |
| `ENG-POOLING-RUNNER` | The pooling RUNNER path — where the generation runner SAMPLES a token, the pooling runner applies the model's `Pooler` to the last hidden state and returns the POOLED DATA (embedding vector / classification logit row). **W3 LANDED + CPU-GATED 2026-07-29 (`CLAIM-POOLING`, NOT pushed):** `PoolingRunner` over a packed `[num_tokens, hidden]` last-hidden-state buffer + a `PoolingMetadata` — `Pool()` delegates to the model pooler (`DispatchPooler.ForEmbedding`), `GetSupportedTasks()`, `ComputeValid()` (`seq_lens==prompt_len`). GATE: a STRUCTURAL cosine-parity gate — the runner's embedding vs an independent double-precision LAST+normalize reference is cosine≈1 (5 cases / 14 asserts), RED-first (CLS-instead-of-LAST drops cosine <0.5; disable normalize → 2 unit-L2 asserts fail). GENERALIZATION DEVIATION: upstream `pooling_runner.py` hardcodes LAST+normalize; we route through the model `Pooler` (the general bert.py path), strictly more capable. HONEST RESIDUAL (named): the REAL-model oracle cosine gate (`vllm.LLM(task="embed").encode`) needs a registered concrete embedding model's forward — no such model is registered yet (W3-model), so no cosine-vs-oracle number is fabricated. **LIVE IN THE ENGINE STEP 2026-08-08 (ARCH-ONE-SURFACE ROW 6, `CLAIM-EMBEDDINGS-ONE-SURFACE`):** `GPUModelRunner` builds a `PoolingRunner` iff the loaded model registration declares `is_pooling_model` (gpu/model_runner.py:368-369 mirror) and `sample_tokens` routes to `pool_tokens()` — pooled data instead of sampled tokens (model_runner.py:1586-1607), validity = the discard predicate (`seq_len < num_tokens` == upstream is_valid, pooling_runner.py:40-41); the scheduler finishes a pooling request on pooled output (scheduler.py:1718-1721) and `EngineCoreOutput.pooling_output` carries it out; async scheduling resolves OFF for pooling models (config/vllm.py:1068-1073, the landed ResolveAsyncScheduling arm now WIRED at model_loader.cpp). First registered pooling arch: `LlamaModel` (`MODEL-EMBED-llama-llama-for-causal-lm`). The fold gate re-anchors the lane's cosine gate THROUGH the registry/runner path: engine path == direct `ModelRegistry::Forward`+`PoolingRunner` path, identical vectors + f64 LAST+normalize reference + chunked-prefill arm (`test_llama_embedding_fold` 4/4-231). REMAINING RESIDUAL: the REAL-model `vllm.LLM(task="embed").encode` oracle cosine (synthetic fixture only — no number fabricated) | T2 | `vllm/v1/worker/gpu/pool/pooling_runner.py:18-46`; `vllm/v1/worker/gpu/model_runner.py:368-369,1586-1607`; `vllm/v1/core/sched/scheduler.py:1718-1721,1837`; `vllm/tasks.py:10`; `tests/models/language/pooling/test_embedding.py` (real-oracle gate, DEFERRED) | `include/vllm/v1/worker/gpu/pool/pooling_runner.h` + `src/vllm/v1/worker/gpu/pool/pooling_runner.cpp:11`; live invocation `src/vllm/v1/worker/gpu/runner.cpp` `pool_tokens` + the `pooling_runner_` ctor gate; scheduler stop `src/vllm/v1/core/sched/scheduler.cpp` pooling elif | `tests/vllm/v1/worker/gpu/pool/test_pooling_runner.cpp:136` (structural cosine gate) + `tests/vllm/models/test_llama_embedding_fold.cpp:206` (registry/engine-path arm, 4/4-231, mutation-killed x9) | [pooling-task-class.md](specs/pooling-task-class.md) + [embeddings-one-surface.md](specs/embeddings-one-surface.md) | `ACTIVE` | `CLAIM-EMBEDDINGS-ONE-SURFACE` |
Expand Down
Loading
Loading