Repository navigation
fix(OMN-20490): size local-omnipc2-chat max_tokens to its slot share of the .202 pool - #4542
Conversation
Adds tests/ci/test_bifrost_endpoint_capacity.py to refuse lane-overlay backends on unified-KV-pool endpoints where max_tokens plus prompt headroom exceeds pool_tokens / parallel_slots. Introduces ModelBifrostLaneOverlay.endpoint_capacity as a tuple of ModelBifrostLaneEndpointCapacity with extra=forbid; the renderer does not write this block into the rendered contract. Declares .202 llama.cpp endpoint capacity in docker/lane-overlays/dev.bifrost.yaml. The test covers all committed docker/lane-overlays/*.bifrost.yaml files and asserts the dev-202 overlay binds no backend. This commit is intentionally failing: the dev overlay's local-omnipc2-chat backend has max_tokens 16384, which with 12288 headroom is 28672 against a per-slot share of 16384, causing two test failures.
Reduce backend max_tokens from 16384 to 4096 in dev.bifrost.yaml. The 65536-token KV pool is shared by 4 slots, making 16384 the per-slot fair share. The previous value left no room for the prompt. 4096 is the share minus the 12288-token prompt headroom declared in endpoint_capacity. Measured data (n=1882) shows output p99 at 3142 and max at 8478, with 3 responses exceeding 4096. Prompt p50 is 12301. Context window and placement ceiling comments are relabelled as the whole pool, unchanged. This turns the contract test added in the previous commit green.
Adds tests/integration/runtime/test_dev_overlay_pool_share_omn20490.py. Renders committed dev lane overlay via real renderer and checks max_tokens. Validates local-omnipc2-chat rung against endpoint_capacity (max_tokens + headroom). Negative control uses whole per-slot share; renderer carries it, check refuses.
|
Lab: head=0de2977104212724d3ae455062ca0199076f34b6 The first push (head cb2fd13) failed the Integration Test Coverage check because the PR adds feature code without a test under tests/integration. This head adds tests/integration/runtime/test_dev_overlay_pool_share_omn20490.py (126 lines, tests only; the overlay, schema and renderer files are unchanged since the lab waves in the PR body). Its two tests pass on host h201 (uv run pytest on that file: 2 passed): the rendered local-omnipc2-chat max_tokens fits the declared per-slot share, and a copy of the overlay with max_tokens equal to the whole share renders through and is refused by the same check. The lab waves in the PR body (4 x HTTP 200 at the rendered max_tokens 4096, twice) therefore still describe the shipped values. The deploy-gate check names the OCC contract for OMN-20490 as missing, which the companion mint resolves; it is not hand-written here. |
…12711) * evidence(OMN-20490): author OCC companion for OmniNode-ai/omnibase_infra#4542 OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head 0de2977104212724d3ae455062ca0199076f34b6. * evidence(OMN-20490): self-bind OCC#12711 + rebind contract_sha256 --------- Co-authored-by: omnimarket-bot <bot@omninode.ai>
There was a problem hiding this comment.
Hostile Reviewer — adversarial findings (OMN-17492)
Models succeeded: qwen3-review, gpt-oss-review
Models failed: none
New finding threads: 2
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 7
Nit-level findings suppressed: 2
The model is the FINDER, never the gate: merge is gated only by the
deterministic Hostile Review Thread Gate, which blocks while
hostile-reviewer threads are unresolved. Resolve each thread after
addressing (or rejecting, with a reply) its finding.
Below quorum: 7 finding(s) raised by one model only (OMN-18479)
These are reported and NOT dropped, but they get no thread and do not block: a single model's finding no other model reproduced is not evidence enough to stop a merge. Read them; act on them if they are right.
- [MAJOR]
src/omnibase_infra/models/delegation/model_bifrost_lane_endpoint_capacity.py(qwen3-review) — authority_of returns None for URLs with default ports, breaking capacity matching | The authority_of method returns None when the URL omits a port and the scheme has no entry in _DEFAULT_PORTS, or whe - [MAJOR]
src/omnibase_infra/models/delegation/model_bifrost_lane_endpoint_capacity.py(qwen3-review) — max_output_tokens can be negative if prompt_headroom_tokens > per_slot_tokens | The model_validator checks that prompt_headroom_tokens < per_slot_tokens, so max_output_tokens should always be positive - [MAJOR]
tests/ci/test_bifrost_endpoint_capacity.py(qwen3-review) — Test test_dev_202_overlay_declares_no_backend_by_design assumes a specific file name | The test hardcodes the file name 'dev-202.bifrost.yaml' and asserts that it exists in the committed overlays. If - [MAJOR]
src/omnibase_infra/runtime/models/model_bifrost_lane_overlay.py(gpt-oss-review) — Endpoint capacity declarations are not cross‑validated against backend bindings | ModelBifrostLaneOverlay adds anendpoint_capacityfield but only checks for duplicate endpoint entries. It does not - [MINOR]
src/omnibase_infra/models/delegation/model_bifrost_lane_endpoint_capacity.py(qwen3-review) — No validation that endpoint host is a valid hostname or IP | The endpoint field is validated to have a numeric port, but the host portion is not validated to be a valid hostname or IP address. A value - [MINOR]
src/omnibase_infra/models/delegation/model_bifrost_lane_endpoint_capacity.py(qwen3-review) — No test for authority_of with IPv6 addresses | The authority_of method uses urlsplit, which handles IPv6 addresses with brackets. However, the endpoint field validation uses rpartition(':'), which wou - [MINOR]
src/omnibase_infra/runtime/models/model_bifrost_lane_overlay.py(gpt-oss-review) — Duplicate endpoint detection ignores default port normalization | The duplicate‑endpoint check compares rawendpointstrings. If one entry uses an explicit port (e.g., "example.com:80") and another
Findings demoted from threads (anchor rejected)
-
[MINOR] hostile-reviewer (qwen3-review)
rpartition on endpoint string may misparse if host contains colon | The rpartition(':') on the endpoint string will split on the last colon. If the host part contains a colon (e.g., a malformed host), it would be misparsed. The validation checks that port is decimal, but does not check that host does not contain a colon. | Evidence: host, separator, port = self.endpoint.rpartition(":") | Fix: Add a check that the host portion does not contain a colon.
Resolve this thread when addressed — the
Hostile Review Thread Gateblocks while hostile-reviewer threads are unresolved (OMN-17492). -
[MINOR] hostile-reviewer (gpt-oss-review)
IPv6 endpoint parsing fails in authority_of |
ModelBifrostLaneEndpointCapacity.authority_ofusesurlsplitfollowed byrpartition(':')to split host and port. For IPv6 literals such as "[::1]:8000" the colon inside the brackets is treated as part of the host, causing the split to produce an empty host and incorrect port, leading to aValueErrorin the validator even though the endpoint is syntactically valid. | Evidence: The_validate_capacitymethod callsself.endpoint.rpartition(":")without haResolve this thread when addressed — the
Hostile Review Thread Gateblocks while hostile-reviewer threads are unresolved (OMN-17492).
✅ Hostile Reviewer — REVIEWEDCritical findings: 0
Semantics (OMN-17492 — the model finds, thread resolution gates)
Powered by omniintelligence.review_pairing.cli_review — multi-model adversarial review: qwen3-review (Qwen3.8-27B), gpt-oss-review (gpt-oss-120b) (OMN-8468/OMN-8524/OMN-17492) |
Lab: host=h201 (lane 202-rung-max-tokens, head cb2fd13); values rendered from docker/lane-overlays/dev.bifrost.yaml (local-omnipc2-chat max_tokens=4096, pool 65536, 4 slots, headroom 12288) by the repo renderer against a synthetic base, then 4 CONCURRENT POST http://192.168.86.202:8000/v1/chat/completions with that max_tokens and prompts of 12063-12387 prompt tokens: 4 x HTTP 200 in both waves (wave 1 finish_reason stop x4; wave 2, outputs forced to the cap, finish_reason length x4 at 4096 tokens, largest total 16306 of the 16384 share). Negative control, same pool, same prompts, max_tokens=65536: 2 x HTTP 500, 1 x client timeout at 300 s, 1 x HTTP 200 (stop, 22439 total tokens).
OMN-20490
Summary
docker/lane-overlays/dev.bifrost.yamlto setmax_tokensfor thelocal-omnipc2-chatbackend from 16384 to 4096.ModelBifrostLaneOverlay.endpoint_capacity: a tuple ofModelBifrostLaneEndpointCapacity(endpoint host:port, pool_tokens, parallel_slots, prompt_headroom_tokens), defined insrc/omnibase_infra/models/delegation/model_bifrost_lane_endpoint_capacity.py. Unknown keys are still rejected, a duplicate endpoint is refused, and the renderer does not write the block into the rendered contract.tests/ci/test_bifrost_endpoint_capacity.pyto validate capacity constraints.Why 4096
.202llama.cpp server runs--kv-unified --parallel 4 -c 65536, creating one 65536-token pool shared by four slots.max_tokensof 16384 equaled the whole per-slot share, leaving no room for any prompt.max_tokensof 4096 is derived from the formula: 65536 / 4 - 12288 = 4096.local-omnipc2-chat, 2026-09-28 to 2026-10-04, n=1882): prompt tokens p50 = 12301; 54.6% of prompts are at most 4096 tokens, 68.6% at most 12288, 72.4% at most 16384. Output tokens p50 170, p90 861, p99 3142, max 8478; 3 of 1882 answers exceeded 4096 output tokens and none exceeded 12288.local-omnipc2-chatanswered HTTP 500 "Context size has been exceeded" (2026-10-01 to 2026-10-03); their events have prompt tokens p50 25222.Lab proof
Surfaces on the .202 llama.cpp server exercised:
GET /propsandGET /slots(read-back of total_slots, n_ctx and slot activity, before and after each wave),GET /health,POST /tokenize(prompt sizing) andPOST /v1/chat/completions(the waves). The server unit, its flags and its configuration were not touched. The dev-202 overlay binds no backend, so no request used it.Values sent came from the rendered overlay, not typed by hand: max_tokens 4096, per-slot share 16384, headroom 12288. In wave 1 the model stopped on its own; wave 2 forced every request to the cap.
Wave 1, rendered max_tokens 4096, 4 concurrent (start 2026-10-04T01:22:37.705+00:00, end 2026-10-04T01:24:01.843+00:00; all slots idle at start: True)
Wave 2, same, outputs forced to the cap (start 2026-10-04T01:24:11.926+00:00, end 2026-10-04T01:26:15.420+00:00; all slots idle at start: True)
Negative control, max_tokens 65536, 4 concurrent (start 2026-10-04T01:26:21.896+00:00, end 2026-10-04T01:31:24.803+00:00; all slots idle at start: True)
TimeoutError('timed out'){"error":{"code":500,"message":"got exception: speculative batch index 8 is not inside the current sub-batch [0, 8)","type":"server_error"}}{"error":{"code":500,"message":"got exception: speculative batch index 9 is not inside the current sub-batch [0, 8)","type":"server_error"}}The control reproduced failure under the same pool: two requests were refused with HTTP 500 at 117.66 s, about when four requests of this prompt size had each generated about 4100 tokens and the pool would be full (inferred from timing; the server's own log was not readable from here). The error text is
speculative batch index N is not inside the current sub-batch [0, 8), not the "Context size has been exceeded" text recorded in delegation_events, so the wave shows a 500 at pool exhaustion but not that exact message. Live dev-lane traffic can also reach this server, so each wave started after a poll found every slot idle;/healthanswered ok with every slot idle afterwards. The waves show the new ceiling fits the pool at four concurrent requests; they do not show that the new test is what prevented the failures.Deployed per-host files, recorded and not edited:
~/.omninode/delegation/bifrost_overrides.pc2.yamlrepointslocal-coderat .202:8000 with max_tokens 16384, andbifrost_overrides.yamlcarrieslocal-omnipc2-chatat 16384. Both sit outside this repo.Not changed, and a finding for a decision
context_window65536 and placementmax_context_tokens65536 keep their values; comments now clarify they represent the whole pool, not one slot's share.~/.omninode/delegationbifrost_overrides files are untouched; they carrymax_tokens16384 forlocal-coderandlocal-omnipc2-chatand are per-host files outside the repo..202and fits only while other slots leave the pool free.Tests
tests/ci/test_bifrost_endpoint_capacity.pyloads every committeddocker/lane-overlays/*.bifrost.yaml.max_tokens+prompt_headroom_tokensexceedspool_tokens/parallel_slotsfor any binding whose host:port is a declared pool endpoint.tests/ci/test_bifrost_endpoint_capacity.pytests/unit/runtime/models/test_model_bifrost_lane_endpoint_capacity.pytests/ci/test_bifrost_lane_overlay.pyruff format,ruff check, andmypy --strictpass on the changed source files.Evidence-Ticket: OMN-20490
Evidence-Source: OCC#12711