Skip to content

Commit 537a70e

Browse files
docs(capi): define stable ABI contract (#10)
Backfill SERVE-C-ABI with an accepted spike, record the remaining compatibility and safety gates, and correct stale public ABI v9 labels to v10. FOLLOWING_AGENTS_PROTOCOL Assisted-by: Codex:gpt-5 [Codex] Co-authored-by: localai-org-maint-bot <[email protected]>
1 parent 5d1e16f commit 537a70e

10 files changed

Lines changed: 293 additions & 5 deletions

File tree

.agents/coordination.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,19 @@ without the selected contention proof for their entire run are discarded.
118118

119119
## Active claims
120120

121+
**Stable C ABI contract spike (`SERVE-C-ABI`, 2026-07-31,
122+
`CLAIM-SERVE-C-ABI-SPIKE`).** Codex (GPT-5), isolated worktree
123+
`.worktrees/serve-c-abi-spike`, branch `codex/serve-c-abi-spike`, base
124+
`upstream/main` `a10bd428`. CPU-only records/spec pass: inventory the original
125+
packaging layer, its ABI/versioning/ownership/error/concurrency contracts, exact
126+
implementation and test anchors, and a row-sized follow-on breakdown. Owns only
127+
NEW `.agents/specs/c-api-library.md` plus the `SERVE-C-ABI` row, this claim,
128+
roadmap/status checkpoint text, `README.md`, `docs/BENCHMARKS.md`,
129+
`.agents/parity-ledger.md`, and append-only `.agents/state.md`. No source,
130+
header, CMake, test, model, kernel, or generated fixture changes; verification
131+
is the existing CPU C/C++/dlopen/export suite plus all record checkers. The row
132+
is unclaimed at base; no GPU or model download is required.
133+
121134
**CUDA keep-quant GGUF k-quant GEMM — the kCUDA provider for `kMatmulBTQuant`
122135
(2026-07-29, `CLAIM-CUDA-KEEPQUANT-GEMM`, LANDED + GB10-GATED, NOT pushed; FULL
123136
SHA reported to caller).** Base `main` HEAD `2191f771`; isolated worktree

.agents/engine-matrix.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ claims it.
188188
| `SERVE-CHAT-TEMPLATE` | Full-surface Jinja chat templates (vendored google/minja `021c229` + documented lstrip guard) | T0 | `vllm/renderers/hf.py:673,986`; `vllm/entrypoints/chat_utils.py:1248,1335` | `src/vllm/entrypoints/chat_template.cpp:101,168,181,220` | `tests/vllm/entrypoints/test_chat_template.cpp:65,75,84,96` | `planned: specs/chat-templating.md` | `ANCHOR-BACKFILL` | - |
189189
| `SERVE-ASYNC-LLM` | AsyncLLM-equivalent streaming engine API: per-request collectors, concurrent submit/generate/abort, live completion/chat SSE with disconnect abort, additive nonblocking C requests, and enough HTTP delivery capacity for configured concurrent streams. GATING: deterministic c32 capacity is implemented and GPU-classified; broader every-axis parity remains open | T0 | `vllm/v1/engine/async_llm.py:70,280,524,637,709`; `vllm/v1/engine/output_processor.py:45-105`; asyncio server path `vllm/entrypoints/openai/api_server.py:1`; `tests/v1/engine/test_async_llm.py:109,157,228,306,340,598` | existing async path `include/vllm/v1/engine/async_llm.h:45`, `src/vllm/v1/engine/async_llm.cpp:32`; fixed/legacy pool API `include/vllm/entrypoints/openai/api_server.h:41-57,101-104`; capacity selection `src/vllm/entrypoints/openai/api_server.cpp:23-62`; production max-seqs wiring + `VLLM_CPP_HTTP_FIXED_POOL=0` A/B `examples/server/main.cpp:230-247`; cpp-httplib defect `third_party/httplib/httplib.h:161-169,10359-10377` | persistent 32-client + control reserve, validation and diagnostic-mode cases `tests/vllm/entrypoints/openai/test_api_server.cpp:937-1000`; focused Release/help pass, API **100/100**, ASan+UBSan **1/1**, TSan **1/1**; known unrelated serial C-API flake isolated. Exact fixed/legacy c32 AB/BA/AB is healthy and steady-state-neutral: **1097.031/1097.290 tok/s = 0.999764×**, 8/20 axes, 1,152/1,152 requests and six memory returns; neither legacy arm samples the rare old stall. Exact `4e1d8ca` fixed c32 is healthy 3/3 and 0.9910× vLLM | [async-serving.md](specs/async-serving.md) | `GATING` | - |
190190
| `SERVE-HTTP-TRANSPORT` | Serving-socket transport parity: mirror vLLM's uvicorn/asyncio default `TCP_NODELAY` on every accepted SSE socket so per-token stream frames are not held by Nagle against the peer's delayed ACK. Implemented + CPU-tested; the non-binding localhost A/B sizing is COMPLETE and NEUTRAL within noise on c1/c2 ITL/TPOT/throughput (loopback ACKs are instant, so Nagle never coalesces ~100 ms-cadence token frames) — no gate-axis credit expected; the mirror stays for real-network parity. Future keep-alive / read-write-timeout / listening-socket option parity noted, not done | T0 | vLLM serves via uvicorn over asyncio `vllm/entrypoints/launcher.py:71,76`, `vllm/entrypoints/openai/api_server.py:591,630`; asyncio disables Nagle per accepted TCP stream socket `asyncio/base_events.py:192-197` (`_set_nodelay`) called from `asyncio/selector_events.py:950`; cpp-httplib default-off `third_party/httplib/httplib.h:142`, applied on accept only when set `third_party/httplib/httplib.h:12083` | `src/vllm/entrypoints/openai/api_server.cpp:69` (`set_tcp_nodelay(true)` in the ApiServer setup) | behavioral accepted-socket `getsockopt(TCP_NODELAY)` case `tests/vllm/entrypoints/openai/test_api_server.cpp:1076` (helper `:380`); RED accepted `TCP_NODELAY` 0 → GREEN 1, full `test_openai_api_server` **22/22 cases / 242 assertions**; non-binding sizing root `~/work/vllm.cpp-tcpnodelay-sizing/ff915e8…` (raw-set SHA `f5b52900…2128`) neutral within noise; closure [ledger](parity-ledger.md#L451) | [serve-tcp-nodelay.md](specs/serve-tcp-nodelay.md) | `DONE` | `ff915e8` |
191-
| `SERVE-C-ABI` | Stable LocalAI-style C FFI (**19** exported `VLLM_API` symbols at `VLLM_ABI_VERSION 9`; blocking and nonblocking request handles. Count corrected 2026-07-24 from a stale `17`, which predated ABI v4/v5 adding `tool_parser`/`reasoning_parser` and the chat entry points; `include/vllm.h` is the source of truth and README:231 already said 19). **ABI v9 2026-07-28 (`CLAIM-CAPI-ENGINE-CONFIG-V9`): the ABI carried strictly LESS engine config than `EngineParams` does** - `max_num_batched_tokens`, the scheduler `scheduling_policy` (`fcfs` / `priority` / `lpm`), and `kv_transfer_config` (the external KV connector / LMCache JSON) were reachable from the bundled server's flags and from NO embedder. All three added, inert at their defaults (zero-filled v8 growth == byte-identical pre-v9 engine); the connector NAME is validated against `KVConnectorFactory` at load, mirroring the server's startup check. `tokenizer_config_path` stopped being a declared-since-v1 no-op and now selects the chat template's source file. Malformed `speculative_config`/`kv_transfer_config` documents now report `VLLM_ERR_INVALID_ARGUMENT` (the contract vllm.h documented since v6) instead of `VLLM_ERR_MODEL_LOAD`, via a catch scoped to the parse block so a real `FromModelDir` failure still reports MODEL_LOAD. Driver: the LocalAI vllm-cpp backend could not expose LMCache or the prefill budget in a model config) | T0 | Original project ABI; pinned vLLM has no C ABI | `include/vllm.h:143,181,207`; `src/capi/vllm_c.cpp:229,264,327,391` | `tests/capi/test_capi.cpp:320,428,505,574,606,640`; `tests/capi/test_dlopen.cpp:77,86`; `tests/capi/c_header_compile.c:1` | `planned: specs/c-api-library.md` | `ANCHOR-BACKFILL` | - |
191+
| `SERVE-C-ABI` | Stable LocalAI-style C FFI (**19** exported `VLLM_API` symbols at `VLLM_ABI_VERSION 10`; blocking and nonblocking request handles. Count corrected 2026-07-24 from a stale `17`, which predated ABI v4/v5 adding `tool_parser`/`reasoning_parser` and the chat entry points; `include/vllm.h` is the source of truth and README:231 already said 19). **ABI v9 2026-07-28 (`CLAIM-CAPI-ENGINE-CONFIG-V9`): the ABI carried strictly LESS engine config than `EngineParams` does** - `max_num_batched_tokens`, the scheduler `scheduling_policy` (`fcfs` / `priority` / `lpm`), and `kv_transfer_config` (the external KV connector / LMCache JSON) were reachable from the bundled server's flags and from NO embedder. All three added, inert at their defaults (zero-filled v8 growth == byte-identical pre-v9 engine); the connector NAME is validated against `KVConnectorFactory` at load, mirroring the server's startup check. `tokenizer_config_path` stopped being a declared-since-v1 no-op and now selects the chat template's source file. Malformed `speculative_config`/`kv_transfer_config` documents now report `VLLM_ERR_INVALID_ARGUMENT` (the contract vllm.h documented since v6) instead of `VLLM_ERR_MODEL_LOAD`, via a catch scoped to the parse block so a real `FromModelDir` failure still reports MODEL_LOAD. Driver: the LocalAI vllm-cpp backend could not expose LMCache or the prefill budget in a model config) | T0 | Original project ABI; pinned vLLM has no C ABI | `include/vllm.h:143,181,207`; `src/capi/vllm_c.cpp:229,264,327,391` | `tests/capi/test_capi.cpp:320,428,505,574,606,640`; `tests/capi/test_dlopen.cpp:77,86`; `tests/capi/c_header_compile.c:1` | [c-api-library.md](specs/c-api-library.md) | `ANCHOR-BACKFILL` | `CLAIM-SERVE-C-ABI-SPIKE` |
192192
| `SERVE-CPP-API` | Rich `LLM` and `AsyncLLM` C++ API | T1 | `vllm/entrypoints/llm.py:66,422`; `vllm/v1/engine/async_llm.py:70` | - | - | `planned: specs/cpp-api.md` | `INVENTORIED` | - |
193193
| `SERVE-CLI-BENCH` | Serve and latency/throughput/serve benchmark modes | T0 | `vllm/entrypoints/cli/serve.py:44`; `vllm/entrypoints/cli/benchmark/main.py:29` | separate binaries + explicit scheduler-capacity flags `examples/server/main.cpp:63,96,116,170`; `examples/bench/main.cpp:40,109`; `examples/bench/bench_core.h:96,468` | server help contract `examples/CMakeLists.txt:34`; benchmark `tests/examples/test_bench.cpp:15,48` | `planned: specs/cli-serve-bench.md` | `PARTIAL` | - |
194194
| `SERVE-GATE-ONLINE` | Same-corpus online correctness, TTFT/TPOT/ITL, throughput and peak-memory gate vs vLLM v0.25.0 | T0 | `vllm/benchmarks/serve.py:1,581-615`; [v0.25 audit](sync/2026-07-12-702f481.md); `tests/benchmarks/test_serve_cli.py:1` | Schema-v5 harness plus [trace controller](../include/vt/cuda/cuda_profiler_control.h#L13), [production component driver](../scripts/dgx-gdn-packed-component.sh), and fail-closed [component finalizer](../tools/bench/gdn_packed_component.py) | **BINDING `9ecd9d0`: 114/124** (async default ON; mem 4/4, c1 20/20, c2 20/20, c16 19/20, c4 & c32 18/20, c8 15/20; `benchmark_binding` refers here, superseding `3f256ab` 55/124 and `246a23c` 49/124, both retained immutable). Two-grid totality with `f0fb727` (111/124) is 115/124 effective parity vs vLLM 0.25.0 (27B). Async CLOSED the c16/c32 ITL tails (ours now BEATS vLLM: c16 p99 1.055, c32 p90 1.034/p99 1.078) and leaves a stable c8 `p99_itl` ~0.86 residual, ROOT-CAUSED (2026-07-18, `CLAIM-C8-P99-TAIL-1`, [spec](specs/c8-p99-itl-tail-2026-07-18.md)) as IRREDUCIBLE-AS-MIRRORED: our deterministic synchronous forward keeps co-admitted c8 requests in byte-identical lockstep where vLLM's async-future jitter de-phases them; the c16/c32 INVERSION proves this is the trailing edge of the per-step determinism that wins c16/c32 + throughput, not a capability gap (scheduler + async placeholder byte-identical, `tests/vllm/v1/test_scheduler_wave.cpp`, [tail spec](specs/tail-stall-analysis-2026-07-16.md)). Full grid + per-binding forensics: roadmap_v1.md + parity ledger; no packed speed credit | [online serving gate](specs/cuda-online-serving-gate.md); [merged GDN projections](specs/gdn-merged-input-projections.md); [packed decode](specs/gdn-packed-decode.md) | `ACTIVE` | CLAIM-SERVE-GATE-1 |

0 commit comments

Comments
 (0)