Files
OmniRoute/docs/architecture/admission-lanes.md
Brandon Bennett 6615a5445b feat: combo-lane awareness + activation UX + MCP visibility (Wave 2 of #9654) (#10039)
* feat(admission): per-target lane-aware probes for combo/fusion fan-out (#9654 Wave 2)

Combo and fusion fan out N targets without ever consulting the adaptive-admission
layer: the parent request holds one lease, but each fan-out target is dispatched
unconditionally. With virtual lanes enabled (OMNIROUTE_CHAT_VIRTUAL_LANES=1), a
connection whose lane queue is full now SKIPS additional fan-out targets instead
of piling more queued work onto an already-congested session.

Adds PerTargetAdmissionHook (admission/types.ts) + createPerTargetAdmissionHook
factory (chatAdmission.ts): strictly non-blocking (maxWaitMs 0 - skip, never
queue), a no-op when virtual lanes are off, keyed to the parent tenantKey, and
release-on-admit so the probe is a capacity gate, not a hold.

Threaded through every parallel fan-out path:
- priority/weighted executeTarget + round-robin skip chains (combo.ts)
- fusion panel before fan-out (fusion.ts), judge fallback prefers survivors
- chaos parallel panel (autoCombo/chaosEngine.ts)
- tryFusionDispatch / tryRuntimeUnitDispatch / buildBaseOptions (dispatchPrelude.ts)
- chat.ts primary + safety-net redirect call sites

Snapshot exposes virtualLanes so the no-op gate is cheap and honest.

Tests: tests/unit/combo-lane-awareness-9654.test.ts (10 tests) - factory
semantics, priority/RR skip, fusion panel drop + all-skipped 503, no-hook
backward-compat baseline.

* feat(flags): activation UX - env-wins adaptive virtual-lanes flag + env docs (#9654 Wave 2)

U7: make adaptive virtual admission lanes discoverable + activatable.
- New OMNIROUTE_CHAT_VIRTUAL_LANES feature flag (boolean/runtime/requiresRestart) in featureFlagDefinitions + en.json i18n key.
- lib/admissionVirtualLanes.ts: env-wins resolver (env > DB > default) + boot warm folding a DB-sourced override into the process-global runtime env via reloadAdaptiveAdmissionRuntime(options.env) - no process.env mutation, no open-sse changes. Env still wins; DB toggle gates at next boot.
- GET /api/settings/feature-flags special-cases the flag to report the gate true source (ccDiscoveryAliases precedent); flagPayload helper dedupes the payload shape.
- Wire the warm into instrumentation-node registerNodejs (non-fatal, DB-ready).
- Document the master switch in .env.example + ENVIRONMENT.md with the system-1/system-2 distinction; zero new env-doc-sync drift.
- 11 new tests (resolver precedence + warm); 60/60 across feature-flag suites; typecheck core clean; ESLint + doc gates green.

* feat(mcp): surface adaptive admission lane data in omniroute_get_health (#9654 Wave 2)

U8: make adaptive virtual-lane admission visible to agents via the MCP health tool. handleGetHealth now surfaces a curated adaptiveAdmission block from the health payload (which already carried the runtime snapshot but was dropping it): virtualLanes/pressure/utilization/laneCount/laneQueuedCount/laneQueuedCost, laneTenants capped at top-10 by queued cost, admitted/rejected/wouldReject counts, shutdown. Block omitted entirely when the health endpoint reports none.

isLaneFlagOn mirrors the runtime 1|true convention so a string serialization can never invert a boolean lane report. getHealthOutput schema extended with the matching optional shape; tool description updated.

4 new dispatch tests (full block, top-10 cap/order, omission, defensive coercion of string flags + malformed lane entries) - 22/22 in essentialTools.test.ts. README: Adaptive Admission Lane Data table + Skills & Tool Navigability audit (29/43 schema entries covered, 14 undocumented, tool_search keyword runtime discovery, full catalog in docs/frameworks/MCP-SERVER.md).

No new lint errors (4 pre-existing in server.ts), typecheck core clean, doc counts + fabricated-docs gates green.

* docs: add changelog entry for #9654 Wave 2 (#10039)

* fix(codeql): suppress js/insufficient-password-hash false positive in lane-key fingerprinting (#10039)

resolveSessionId sha256-hashes bearer/x-api-key/x-goog-api-key to derive a deterministic, non-reversible per-key lane-bucket ID for virtual admission lanes (#9654). This is not password storage or verification, so the rule is a false positive; suppress it inline (same house style as src/lib/sync/tokens.ts) to clear the codeqlAlerts ratchet (2 > baseline 1) that blocks #10039 and every PR against release/v3.8.50.

* docs(mcp): complete MCP server README tool reference (#10039)

The MCP server README covered only 29 of the 43 schema entries, listing the
remaining tools solely as a gap note with omniroute_tool_search as the runtime
fallback. Add tool-reference tables for the agent-skills trio, oneproxy trio,
web_fetch/web_search, tool_search, create_combo, set_routing_strategy,
pick_fastest_model, sync_pricing, and db_health_check so the README covers the
full schemas catalog, and fold the coverage note into the tool_search discovery
paragraph.

* fix(chat): drop unused correlationId from safety-net combo redirect (#10039)

handleComboChat's HandleComboChatOptions has no correlationId member and
the combo pipeline never consumes it; the property was copied from the
handleSingleModelChat options shape by accident and introduced a new
TS2353 under the open-sse workspace typecheck gate.

* fix(i18n): translate featureFlagChatVirtualLanesEnabledDescription into 42 locales (#10039)

en.json gained the flag description in this PR but the locale catalogs
were never mirrored, failing the pt-BR key-parity (#6695) and vi
completeness gates. Adds a real translation to every locale, keeping the
zh-CN/zh-TW glossary canonical terms (提供者/儀表板) and no ICU drift.

* chore(quality): ratchet open-sse-typecheck baseline down (#10039)

The Wave 2 admission refactor removed 66 baselined open-sse type errors;
re-freeze the baseline so the gate pins the new, tighter state.

* docs: resync provider reference to 341 and CLI tools to 34

The release branch gained an 11th no-auth provider (freeaiapikey registry
resync, #10233) and a 26th CLI Code tool without regenerating the
auto-generated docs, leaving every PR against release/v3.8.50 failing the
Docs Gates strict validator (code 341 vs doc 340, CLI 34 vs "33 tools").

Regenerate docs/reference/PROVIDER_REFERENCE.md and sync the provider/tool
counts across README.md, AGENTS.md, llm.txt plus 42 i18n mirrors,
package.json description, and the four diagram SVGs.

* fix(tests): align count expectations with live catalogs (pre-existing release drift)

Release/v3.8.50 currently fails five gates on its own tree; this PR inherits
them. Fix the stale expectations to match live code:

- feature-flags-settings: 48 -> 49 flags (Wave 2 adds OMNIROUTE_CHAT_VIRTUAL_LANES)
- cli-tools-schema / cli-catalog-counts: 33 -> 34 tools (zcode added; 26 code = 21 visible + 5 none)
- optional-transformers-dependency: onnxruntime-node ~1.24.3 -> ~1.27.0 (bump #10382)
- stryker.conf.json: register chatcore-header-drop-warn-dedupe-10315 test
- check-public-creds: freeze zcodeProtocol clientId false positive (client identifier, not a credential)

* fix(tests): follow release's onnxruntime-node revert to ~1.24.3

release/v3.8.50's #10543 pinned onnxruntime-node back to ~1.24.3 after
#10403's ~1.27.0 bump caused npm to nest a second native copy under
@huggingface/transformers and broke the Docker SONAME contract. This
PR's own drift-alignment commit (57b9c033) predates that revert and
still expected ~1.27.0; the 3-way merge did not flag it as a textual
conflict since only one side touched this exact line, but the merged
tree became internally inconsistent (package.json ~1.24.3 vs test
expecting ~1.27.0). Align the test with the now-canonical release
value.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

* fix(quality): dedupe stryker.conf.json chatcore-header-drop-warn-dedupe entry

The 3-way merge applied both sides' insertion of the same test-file entry
at different positions, producing a duplicate with broken indentation.
Adopted release's clean version of the file.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Brandon Bennett <brandonbennett@macbookair.myfiosgateway.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Brandon Bennett <branben@users.noreply.github.com>
2026-08-18 11:31:46 -03:00

5.4 KiB

title, status, lastUpdated
title status lastUpdated
Admission lanes — two lane systems, what gates each, where each reports active 2026-08-10

Admission lanes (#9654) — two lane systems, what gates each, where each reports

OmniRoute has two process-local lane systems with different scopes. They are complementary; operators should know which one they are looking at.

1. Byte-level per-connection lanes (chatBodyAdmission.ts)

  • Scope: the buffered-body/heap path for POST /v1/chat/completions. Guards against heap amplification from large coding-agent bodies (#4380).
  • Gate: always on. Each distinct API key (hashed) — or anonymous — gets its own lane with CHAT_MAX_HEAVY_IN_FLIGHT capacity, so one session's burst cannot starve another session's heavyweight slot.
  • Tuning:
    • OMNIROUTE_CHAT_VIRTUAL_TTL_MS — idle-lane eviction (default 60000)
    • OMNIROUTE_CHAT_VIRTUAL_MAX_SESSIONS — lane count cap (default 64)
    • OMNIROUTE_CHAT_ADMISSION_QUEUE_MS — queue-wait before 503 (default 2000)
    • OMNIROUTE_CHAT_ADMISSION_MAX_QUEUED_BYTES — queued-bytes heap valve (default 4 MB)
  • Reports: not in GET /api/monitoring/health today; observable via PerConnectionAdmissionController.snapshot() (sessionId hash, activeHeavy, idleMs).

2. Adaptive runtime virtual lanes (open-sse/services/admission)

  • Scope: tenant-key admission for provider dispatch — queue cost, latency-guided limit adaptation, lane queueing, and lane metrics.
  • Gate: opt-in. Disabled unless OMNIROUTE_CHAT_VIRTUAL_LANES=true. Without it, the adaptive controller keeps the shared queue behavior (criterion 1 of #9654 only holds once an operator enables lanes).
  • Tuning: OMNIROUTE_CHAT_VIRTUAL_LANES + adaptive config (maxQueueCount, maxQueueCost, defaultMaxWaitMs, …).
  • Reports: GET /api/monitoring/healthadaptiveAdmissionlaneCount, laneQueuedCount, laneQueuedCost, laneTenants (opaque lane IDs, never raw keys), and virtualLanes — the authoritative "lanes are on" flag in the snapshot.

3. Fan-out probes — per-target admission for combo/fusion (#9654 Wave 2)

Combo (priority / round-robin) and fusion fan out N model targets under one parent request. Since #9654 Wave 2, each fan-out target is gated before dispatch by a per-target probe (PerTargetAdmissionHook, built by createPerTargetAdmissionHook) against the parent's tenant lane.

  • Scope: every fan-out target dispatched by combo, fusion, and the chaos engine. System 1 (byte-level) is unaffected — it never probes fan-out targets.
  • Gate: opt-in with system 2. A no-op when OMNIROUTE_CHAT_VIRTUAL_LANES is unset — the parent request already holds the shared-queue lease in that mode, so probing would double-count and reject combo targets.
  • Semantics:
    • Strictly non-blocking — skip, never queue. maxWaitMs 0: a full lane skips the target and the combo's fallback machinery (or fusion's survivor panel) serves instead. This is deliberate: a fan-out target is redundant work, and queueing it piles more load onto the exact congestion lanes exist to stop. defaultMaxWaitMs therefore applies to the parent request only; fan-out probes never wait, and there is intentionally no knob to make them wait (issue history shows wait knobs produced the mass-502/504 class #9654 prevents — revisit only if an operator reports skipped fan-out targets hurting response quality).
    • Release-on-admit. An admitted probe releases its lease immediately: it is a capacity gate, not a hold. The parent's lease covers the fan-out; holding N more would inflate shared active cost and reject other tenants. Best-effort, not a reservation: the lane can refill between probe and dispatch, so under heavy contention the gate may admit into a lane that is full again by the time the target dispatches.
    • Priced from the real fan-out body. The probe estimates cost from the target's actual body — including the request class derived from its stream flag, exactly like the parent path — so fusion panel members (stream: false) are priced at the non-streaming class they will truly occupy, and priority/RR targets at whatever the user requested.
  • Reports: a probe skip after the first target bumps combo's per-request fallbackCount (mirroring the existing fallback semantics; visible in combo logs); fusion returns 503 when every panel member is skipped. There is no aggregate counter (e.g. virtualFanoutSkipped) on the snapshot today — if an operator reports they cannot tell how often the lane gate skips fan-out targets, that is the trigger to add one.

Which one is showing in a dashboard

  • adaptiveAdmission.laneCount / laneTenantsadaptive virtual lanes (system 2).
  • adaptiveAdmission.virtualLanes === true → the fan-out probes of section 3 are also active. A payload with virtualLanes missing or false means OMNIROUTE_CHAT_VIRTUAL_LANES is unset — the byte-level lanes (system 1) are still active, but nothing under adaptiveAdmission (and no fan-out gating) is in effect until it is enabled.

Why both exist

The byte-level lanes bound the memory-heavy parse/compress path; the adaptive lanes bound dispatch cost per tenant. #9654's criterion 1 ("one session's burst does not 503 another") is enforced by system 1 unconditionally and by system 2 once opt-in is enabled.