Skip to content

spec(SERVE-RECIPE-ARGS): a published recipe command must reach model load (#606) - #613

Closed
localai-bot wants to merge 2 commits into
mainfrom
row/serve-recipe-args
Closed

spec(SERVE-RECIPE-ARGS): a published recipe command must reach model load (#606)#613
localai-bot wants to merge 2 commits into
mainfrom
row/serve-recipe-args

Conversation

@localai-bot

Copy link
Copy Markdown
Collaborator

Closes the spec-before-code gate for #606. Adds .agents/specs/serve-recipe-args.md,
the new SERVE-RECIPE-ARGS row at SPIKE, and its claim file.

The defect

vllm-serve rejects any argument it does not recognise
(src/vllm/entrypoints/openai/server_main.cpp:440). That is the right default —
and it is why two flags that mean nothing to us stop the server before it loads a
model:

Flag Recipes passing it Why inert here
--enable-auto-tool-choice 89 / 157 tool parsing is already unconditional once --tool-call-parser resolves
--trust-remote-code 82 / 157 no Python runtime, so no remote code to trust

The reproducer is a recipe's own copy-paste block, for a model we ship token-exact
and gated:

vllm serve Qwen/Qwen3.5-27B-FP8 --enable-auto-tool-choice --tool-call-parser qwen3_coder
#                               ^ server: unknown argument '--enable-auto-tool-choice'

What the spec commits to

An enumerated accepted-and-inert table, one entry per flag carrying the reason
it is inert — not a catch-all. Three rules:

  1. Unlisted flags still abort. Silently swallowing --tensor-parallel-size
    would let a user believe they got TP. That the table is enumerated is the whole
    value of the seam.
  2. Accepting is announced, so a log reader learns the flag did nothing rather
    than inferring it worked.
  3. Mirrored validation still firescli_args.py:395 makes
    --enable-auto-tool-choice without a parser a TypeError upstream. Inert is
    not unvalidated.

Explicitly excluded: flags inert because we lack the capability (TP, EP,
--mm-encoder-tp-mode) keep aborting, and --language-model-only (#607) is a real
capability gap that must not be quietly absorbed here.

Recorded, not papered over

Upstream defaults --tool-call-parser to None; we default it to hermes
(docs/USAGE.md:878). Upstream's flag therefore gates something ours cannot. That
is pre-existing and out of scope, and the spec says so, so the notice text cannot
overclaim parity.

Tests named in the spec

RED-first, with the load-bearing case being "an unlisted unknown flag still
aborts"
— a mutation turning the table into a catch-all must turn it RED, proven
in a scratch copy with the tree restored byte-for-byte.

Row accounting

ENGINE_ROWS 152 → 153 with the justification check-agent-record.py's own
comment ledger asks for. No checker semantics change: the row claims no seam, no
test, no docs/USAGE.md entry — none exists yet.

Spec and records only, no product code. scripts/agent-preflight.sh --staged: exit 0.

🤖 Generated with Claude Code

mudler added 2 commits August 13, 2026 10:37
…load (#606)

FOLLOWING_AGENTS_PROTOCOL

vllm-serve rejects any argument it does not recognise (server_main.cpp:440). That
is the right default, and it is why two flags that mean nothing to us stop the
server before it loads a model: --enable-auto-tool-choice, which 89 of the 157
official vLLM recipes pass, and --trust-remote-code, which 82 pass. We parse tool
calls whenever --tool-call-parser resolves, so there is no second gate to open;
and we have no Python, so there is no remote code to trust. Both are inert, and
both abort -- including for Qwen3.5-27B, which we ship token-exact and gated. The
kernels are not what stands between a user and a running server here.

The spec is deliberately narrow about what the seam may swallow. An enumerated
table, one entry per flag with the reason it is inert; anything unlisted still
aborts, because silently accepting --tensor-parallel-size would let a user believe
they got tensor parallelism, and that is the failure mode this exists to prevent.
Flags inert because we LACK the capability -- TP, EP, --mm-encoder-tp-mode -- are
explicitly excluded and keep aborting. So is --language-model-only (#607), which
is a real capability gap wearing the same costume.

Two things the spec records rather than papers over. cli_args.py:395 makes
--enable-auto-tool-choice without --tool-call-parser a TypeError upstream, so
inert must not mean unvalidated and the mirrored failure is a named test case. And
upstream defaults --tool-call-parser to None where we default it to hermes, so
upstream's flag genuinely gates something ours cannot -- pre-existing, out of
scope, and called out so the notice text does not overclaim parity.

ENGINE_ROWS 152 -> 153 for the new row, with the justification the checker's own
comment ledger asks for. No checker semantics change: the row claims no seam, no
test and no USAGE entry, because none exists yet.

Spec and records only, no product code touched.
scripts/agent-preflight.sh --staged: exit 0.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
…#606)

FOLLOWING_AGENTS_PROTOCOL

check-pr-size.py classifies scripts/check-agent-record.py as a governance
checker and requires companion evidence in tests/scripts/test_agent_record.py for
any change to it -- including the ENGINE_ROWS 152 -> 153 bump that carries the new
row. That rule is right: without it, a bump made to silence a broken count looks
identical to a bump made for a real row.

Mirrors test_windows_release_row_is_inside_the_engine_ratchet, added for the same
reason when the constant last moved.

Two mutations were run in the worktree and BOTH were caught, but neither by this
assertion: deleting the row is caught by the count ratchet in setUpClass
(152 engine rows; expected 153), and renaming it while keeping the count is caught
by the claim cross-check (owner CLAIM-SERVE-RECIPE-ARGS does not claim active row
SERVE-RECIPE-ARGZ). So this test is a third pin on an invariant two existing guards
already defend, not an independent guard -- the same is true of the Windows test it
mirrors, and it is worth saying plainly rather than reporting a mutation proof that
was actually someone else's assertion firing. The tree was restored byte-for-byte
after each mutation; git diff HEAD over .agents/ is empty.

python3 -m unittest tests.scripts.test_agent_record: 50 tests, OK.

Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:claude-opus-5 [Claude Code]
@localai-bot

Copy link
Copy Markdown
Collaborator Author

windows-msvc-cpu / windows-msvc-vulkan red here are pre-existing, not this diff.

Tracked by #503 and #603. Recording the attribution so a reviewer does not
re-derive it:

Neither this PR nor #616 touches src/, include/, tests/*.cpp, or CMake.

Not claimed as green, and not waived: the jobs are genuinely failing, the cause is
recorded elsewhere, and closing it belongs to #503/#603 rather than to a records
change.

@localai-bot

Copy link
Copy Markdown
Collaborator Author

Correction to my earlier comment: the specific cause is #584, not #503/#603.

I attributed the red Windows lanes to #503 / #603 — a compile break (POSIX
setenv, absent in MSVC). I inferred that from issue titles because the run logs
were not retrievable while the run was in progress. That inference was wrong about
the mechanism.

The observed failure is a runtime crash, not a compile error:
test_openai_api_server.exe exits -1073740791 = 0xC0000409
(STATUS_STACK_BUFFER_OVERRUN)
— which is
#584, "test_openai_api_server
crashes on Windows with STATUS_STACK_BUFFER_OVERRUN (0xC0000409), unmasked by the
#512 fix". The failing CI step is "Build and execute the native Windows CPU
focused gate", which does both, so a crash at the execute half presents the same
way as a build failure from the outside.

What does not change: the failure is still not attributable to this PR.

Recording the correction rather than editing the original comment, so the wrong
attribution does not silently disappear from the thread. My apologies to whoever
would have chased setenv.

@localai-bot

Copy link
Copy Markdown
Collaborator Author

Closing as superseded by #624, which contains this branch's spec commit
(0d8274ac3) plus the implementation.

Verified rather than assumed:

The one thing this branch had that #624 initially lacked was that test commit,
because #624 branched before it was pushed. #624 then wrote its own, so nothing is
carried over.

row/serve-recipe-args stays until #624 merges, since #624 is based on it.

Closed per AGENTS.md: obsolete PRs are closed with the reason recorded, never left
open alongside their successor.

@localai-bot
localai-bot deleted the row/serve-recipe-args branch August 13, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants