Skip to content

Commit 0702ea2

Browse files
committed
docs(plan): replan ONNX runtime for Rust execution
Replace the Python sidecar direction with an in-process Rust ONNX provider/session architecture across the ONNX Runtime embedding serving plan, ADR, contracts, risks, milestones, and execution notes. The re-plan keeps Pumas /v1 as the public facade, moves ONNX execution and dependency ownership into Rust, makes the first implementation slice a Rust provider skeleton with a fake backend, and records the Python ONNX sidecar as rejected and out of scope. Removed the aborted uncommitted onnx-server skeleton before this documentation update; no sidecar implementation files are committed. Verification: - git diff --check - rg -n "onnx-server|ONNX Sidecar Skeleton|ruff check onnx-server|python -m unittest|sidecar-local|ONNX sidecar lifecycle|managed sidecar|future ONNX managed sidecar|future ONNX sidecar|sidecar launch wiring" docs/plans/onnx-runtime-embedding-serving docs/adr/0001-onnx-runtime-provider-model.md Agent: codex
1 parent 53d0574 commit 0702ea2

9 files changed

Lines changed: 299 additions & 270 deletions

File tree

docs/adr/0001-onnx-runtime-provider-model.md

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ embedding models through the existing OpenAI-compatible `/v1` gateway. Current
1515
runtime profile, serving, gateway, launcher, and frontend paths are shaped
1616
around Ollama and llama.cpp. Adding ONNX as another branch would preserve the
1717
existing two-provider assumptions and make route identity, endpoint capability,
18-
and sidecar lifecycle behavior harder to reason about.
18+
and ONNX runtime/session lifecycle behavior harder to reason about.
1919

2020
This ADR records the Milestone 0 provider-model decision required by
2121
`docs/plans/onnx-runtime-embedding-serving/`.
@@ -34,8 +34,8 @@ The provider model separates these contracts:
3434
provider-side model id policy, launch-on-serve behavior, and unload behavior.
3535
- Runtime profile: persisted managed or external runtime configuration for one
3636
provider.
37-
- Launch strategy: binary process, Python sidecar, or external-only lifecycle
38-
plan selected by provider behavior.
37+
- Launch/runtime strategy: binary process, in-process Rust runtime, or
38+
external-only lifecycle plan selected by provider behavior.
3939
- Model route: provider-scoped saved route keyed by `(provider, model_id)`.
4040
- Served instance: backend-owned loaded model status with enough provider
4141
identity to disambiguate the same model id served by multiple providers.
@@ -58,13 +58,13 @@ before ONNX serving is accepted.
5858
| System | Current Owner | ONNX Treatment |
5959
| ------ | ------------- | -------------- |
6060
| App/plugin registry | Plugin JSON, Rust `AppId`, RPC version-manager composition, frontend app registry | Refactor or update as one app identity slice. ONNX extends this only after drift tests or a descriptor owner exists. |
61-
| Version/process management | `pumas-app-manager`, `pumas-rpc` composition, `pumas-core` process helpers | Refactor launch strategy first. ONNX uses Python sidecar launch behavior, not Ollama/llama.cpp binary constructors. |
61+
| Version/process management | `pumas-app-manager`, `pumas-rpc` composition, `pumas-core` process helpers | Refactor launch/runtime strategy first. ONNX uses an in-process Rust ONNX Runtime session manager, not Ollama/llama.cpp binary constructors or a Python sidecar. |
6262
| Runtime profiles | `pumas-core` runtime profile service and DTOs | Refactor to provider behavior and provider-scoped routes before ONNX routes. |
6363
| Model library | `pumas-core` model library and frontend projection helpers | Extend executable format/compatibility helpers; keep generic ONNX embedding compatibility separate from custom ONNX app metadata. |
6464
| Serving state | `pumas-core` serving contracts and `pumas-rpc` serving handler | Refactor to provider serving adapters and provider-aware served identity before ONNX load/unload. |
6565
| OpenAI gateway | `pumas-rpc` gateway handlers and Axum routes | Refactor endpoint capability checks, shared HTTP client, body limits, and provider model-id rewriting before ONNX gateway routing. |
6666
| Frontend runtime/profile UI | Frontend app panels, runtime profile sections, route rows, serve dialog | Refactor to provider descriptors and provider-scoped route helpers before ONNX panel and route assignment. |
67-
| Torch sidecar | `torch-server/` and Torch-specific process/client integration | Use as sidecar API reference only. It is not the runtime-profile provider architecture. |
67+
| Torch sidecar | `torch-server/` and Torch-specific process/client integration | Keep as unrelated Torch architecture. It is not the ONNX Runtime implementation target. |
6868

6969
## App And Runtime Descriptor Strategy
7070

@@ -113,7 +113,7 @@ The first complete public-contract acceptance path is:
113113
2. Save a provider-scoped route for an ONNX-compatible model.
114114
3. Call `serve_model` without an explicit profile and resolve the saved ONNX
115115
route.
116-
4. Load through a fake or fixture ONNX sidecar adapter.
116+
4. Load through a fake or fixture Rust ONNX provider adapter.
117117
5. Record backend-owned `ServedModelStatus`.
118118
6. Confirm `GET /v1/models` lists the public alias.
119119
7. Confirm `POST /v1/embeddings` proxies through the Pumas gateway.
@@ -159,12 +159,15 @@ targets include:
159159
- Keep model-only runtime routes: rejected because the same model id can be
160160
served by multiple providers, and ONNX missing-route behavior must not fall
161161
back to a llama.cpp or default profile.
162-
- Expose the raw ONNX sidecar as the supported external app contract: rejected
163-
because Pumas owns aliases, served state, future auth policy, and the existing
164-
`/v1` facade.
162+
- Add a Python ONNX sidecar: rejected because ONNX Runtime can be hosted through
163+
Rust bindings, and adding a second Python sidecar would expand packaging,
164+
process lifecycle, and cross-language contracts without a clear need.
165+
- Expose a raw ONNX provider endpoint as the supported external app contract:
166+
rejected because Pumas owns aliases, served state, future auth policy, and the
167+
existing `/v1` facade.
165168
- Copy the Torch sidecar integration path as-is: rejected because Torch is app
166-
specific and does not provide the runtime-profile provider contract, bounded
167-
ONNX inference queue, or ONNX shutdown semantics required here.
169+
specific and does not provide the runtime-profile provider contract or Rust
170+
ONNX session lifecycle required here.
168171

169172
## Invariants
170173

@@ -176,8 +179,8 @@ targets include:
176179
- Gateway endpoint capability checks happen before proxying.
177180
- Generic ONNX embedding compatibility remains separate from custom ONNX app
178181
metadata.
179-
- ONNX dependencies remain sidecar-local unless another owner demonstrably
180-
executes them.
182+
- ONNX dependencies remain owned by the Rust crate/module that executes ONNX
183+
Runtime.
181184

182185
## Revisit Triggers
183186

docs/plans/onnx-runtime-embedding-serving/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ requirements change.
3838
- Provider-scoped route identity replaces one-route-per-model semantics.
3939
- Generic ONNX embedding compatibility remains separate from custom ONNX app
4040
metadata such as KittentTS.
41-
- ONNX dependencies remain sidecar-local unless another owner demonstrably
42-
executes them.
41+
- ONNX dependencies remain owned by the Rust module/crate that executes ONNX
42+
Runtime.
4343

4444
## Usage
4545

docs/plans/onnx-runtime-embedding-serving/execution-and-coordination.md

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Update during implementation:
137137
returns a Pumas-shaped HTTP 413 error response when exceeded, and
138138
applies the endpoint request timeout to the forwarded request. The explicit
139139
per-endpoint body ceilings preserve the existing 32 MiB gateway limit until a
140-
narrower ONNX sidecar endpoint contract lands.
140+
narrower Rust ONNX provider endpoint contract lands.
141141
- 2026-05-11: Added provider to served-instance unload identity. Backend
142142
serving state now compares provider when replacing, finding, and unloading
143143
served models; unload events carry the provider; `UnserveModelRequest`
@@ -200,10 +200,10 @@ Update during implementation:
200200
implementation slices.
201201
- 2026-05-11: Made runtime-profile management-mode validation consume provider
202202
launch kinds. `ProviderBehavior::supports_management_mode` now maps
203-
`binary_process` and the reserved `python_sidecar` kind to managed profiles,
203+
`binary_process` and the then-reserved sidecar launch kind to managed profiles,
204204
and `external_only` to external profiles. This is the launch-strategy contract
205-
slice only; process launch still needs the later binary/Python sidecar
206-
abstraction before ONNX managed launch is wired.
205+
slice only; ONNX managed launch now needs the Rust in-process runtime strategy
206+
recorded by the 2026-05-11 re-plan.
207207
- 2026-05-11: Reconciled Milestone 0 registry usage after the launch-kind
208208
validation slice. The built-in provider registry is now consumed by
209209
runtime-profile validation/capability projection, serving adapter selection,
@@ -258,17 +258,17 @@ Update during implementation:
258258
- 2026-05-11: Added the typed runtime-profile launch strategy abstraction under
259259
`rust/crates/pumas-core/src/runtime_profiles/`. Managed Ollama and llama.cpp
260260
launch specs now carry `RuntimeProfileLaunchStrategy::BinaryProcess(...)`,
261-
external profiles map to `ExternalOnly`, and the enum reserves the
262-
`PythonSidecar` path for the ONNX managed sidecar slice. Runtime lifecycle
263-
launch-config construction now consumes the typed strategy instead of
264-
matching provider ids directly. Added the directory README required for the
265-
new launch-strategy module.
261+
external profiles map to `ExternalOnly`, and the previously reserved sidecar
262+
path is superseded for ONNX by the Rust in-process runtime strategy recorded
263+
by the re-plan. Runtime lifecycle launch-config construction now consumes the
264+
typed strategy instead of matching provider ids directly. Added the directory
265+
README required for the new launch-strategy module.
266266
- 2026-05-11: Moved managed launch target selection into provider behavior.
267267
`ProviderBehavior` now declares per-mode `ProviderManagedLaunchStrategy`
268268
values, runtime-profile launch-spec derivation consumes the composed provider
269269
registry to project those targets into `RuntimeProfileLaunchStrategy`, and
270270
provider contract serialization tests cover the new launch target wire shape.
271-
ONNX sidecar process launch remains deferred to the managed ONNX lifecycle
271+
ONNX in-process runtime wiring remains deferred to the managed ONNX lifecycle
272272
slice.
273273
- 2026-05-11: Moved runtime-profile launch version-manager selection onto
274274
provider behavior. `ProviderBehavior` now declares the managed runtime app id
@@ -319,22 +319,21 @@ Update during implementation:
319319
`ProviderBehavior`, and updated launch-spec derivation to consume those
320320
provider-owned values. Existing provider-specific env/arg construction still
321321
remains in launch-spec derivation and is recorded as a remaining Milestone 0
322-
cleanup before ONNX sidecar launch wiring.
322+
cleanup before ONNX in-process runtime wiring.
323323
- 2026-05-11: Updated managed launch-spec env/arg derivation to consume
324324
`RuntimeProfileLaunchStrategy` instead of matching directly on provider ids.
325-
Existing Ollama and llama.cpp launch output remains unchanged; Python sidecar
326-
env/args now fail explicitly until the ONNX lifecycle slice implements that
327-
launch target.
325+
Existing Ollama and llama.cpp launch output remains unchanged; non-binary
326+
runtime strategies fail explicitly until a provider lifecycle slice
327+
implements that target.
328328
- 2026-05-11: Added provider-owned launch-on-serve support and moved stopped
329329
managed profile acceptance in serving validation onto `ProviderBehavior`.
330330
Existing Ollama remains rejected for stopped managed serve requests, and
331331
llama.cpp router/dedicated launch-on-serve behavior is preserved through the
332332
provider contract.
333333
- 2026-05-11: Updated runtime-profile lifecycle launch preparation to consume
334334
`RuntimeProfileLaunchStrategy` for llama.cpp router/dedicated preset/model
335-
prep instead of matching on provider id plus provider mode. ONNX Python
336-
sidecar launch preparation remains explicitly unwired until the managed
337-
sidecar lifecycle slice.
335+
prep instead of matching on provider id plus provider mode. ONNX in-process
336+
runtime preparation remains unwired until the Rust ONNX lifecycle slice.
338337
- 2026-05-11: Extracted runtime-profile route config initialization, one-way
339338
legacy route migration, and model-route validation into
340339
`rust/crates/pumas-core/src/runtime_profiles/route_config.rs`. The
@@ -354,10 +353,16 @@ Update during implementation:
354353
launch strategy/spec derivation, and frontend provider row/view-model
355354
components. Large unrelated legacy files remain outside this plan's ONNX
356355
write surface.
356+
- 2026-05-11: Re-plan trigger accepted: ONNX Runtime will be hosted through
357+
Rust ONNX Runtime bindings rather than a Python sidecar. Removed the aborted
358+
uncommitted `onnx-server/` skeleton from the worktree and updated plan
359+
contracts, risks, milestones, and ADR language to target an in-process Rust
360+
ONNX provider/session manager. Candidate binding is `ort`, pending focused
361+
Rust dependency review and native-library packaging decision.
357362

358363
## Commit Cadence Notes
359364

360-
- Commit the sidecar skeleton and tests as the first verified slice.
365+
- Commit the Rust ONNX provider skeleton and tests as the first verified slice.
361366
- Commit Rust provider/profile contracts separately from frontend UI when
362367
feasible.
363368
- Commit gateway routing with Rust tests before release validation.
@@ -376,9 +381,9 @@ integration files unless one explicit owner is assigned for the current wave.
376381

377382
| Owner/Agent | Primary Write Set | Allowed Adjacent Write Set | Forbidden/Shared Files | Output Contract | Handoff Checkpoint |
378383
| ----------- | ----------------- | -------------------------- | ---------------------- | --------------- | ------------------ |
379-
| Sidecar worker | `onnx-server/` | Sidecar README and sidecar-local dependency manifest/lock files | Rust DTOs, frontend types, root/workspace dependency manifests unless explicitly assigned | Python sidecar, validation, fake and real-session tests, README | Sidecar tests pass, dependency ownership evidence recorded, endpoint contract documented. |
380-
| Rust worker | `rust/crates/pumas-core/`, `rust/crates/pumas-rpc/` | `launcher-data/plugins/onnx-runtime.json`, Rust docs/README updates when assigned | Frontend components, Python sidecar internals, lockfiles not owned by Rust slice | Provider contracts, route migration/cleanup, serving, gateway tests | Rust focused tests pass, serialization/migration evidence recorded, no old route shape active. |
381-
| Frontend worker | `frontend/src/` | Electron bridge/types only when required by the frozen contract | Rust DTOs, sidecar internals, plugin metadata unless explicitly assigned | ONNX app icon/panel/profile/model-route UI and tests | Typecheck/build/focused frontend tests pass, no optimistic backend-owned state introduced. |
384+
| Rust ONNX worker | `rust/crates/pumas-core/`, `rust/crates/pumas-rpc/` ONNX provider/session modules | Rust README updates and dependency manifest/lockfile changes when assigned | Frontend components, plugin metadata unless explicitly assigned | Rust ONNX provider/session boundary, fake and real-session tests, gateway adapter contracts | Rust focused tests pass, dependency ownership evidence recorded, endpoint contract documented. |
385+
| Rust contract worker | `rust/crates/pumas-core/`, `rust/crates/pumas-rpc/` | `launcher-data/plugins/onnx-runtime.json`, Rust docs/README updates when assigned | Frontend components, ONNX execution internals unless explicitly assigned | Provider contracts, route migration/cleanup, serving, gateway tests | Rust focused tests pass, serialization/migration evidence recorded, no old route shape active. |
386+
| Frontend worker | `frontend/src/` | Electron bridge/types only when required by the frozen contract | Rust DTOs, ONNX execution internals, plugin metadata unless explicitly assigned | ONNX app icon/panel/profile/model-route UI and tests | Typecheck/build/focused frontend tests pass, no optimistic backend-owned state introduced. |
382387
| Integration owner | Plan, ADR, cross-layer docs, release notes, shared schema/manifest files | Coordination reports and final verification notes | None; this owner serializes cross-cutting edits | Contract sync, docs, release evidence, final verification | Full vertical acceptance path passes and worker outputs match assigned write sets. |
383388

384389
Worker reports must be written under this plan directory if workers are used:
@@ -394,7 +399,8 @@ changes remain.
394399
- The available ONNX model package does not include enough tokenizer/config
395400
files for local tokenization.
396401
- `nomic-embed-text-v1.5` ONNX exports require model-specific custom ops or
397-
output handling that cannot be represented by a generic embedding sidecar.
402+
output handling that cannot be represented by a generic Rust embedding
403+
provider.
398404
- ONNX Runtime GPU packaging differs enough by platform to require separate CPU
399405
and GPU plugin/runtime profiles.
400406
- The Pumas gateway cannot safely route embedding-only providers without the new
@@ -420,8 +426,9 @@ changes remain.
420426
gateway composition root without a broader RPC server state refactor.
421427
- Provider-scoped model routes reveal a broader route/default-profile redesign
422428
is required before ONNX route assignment can be implemented cleanly.
423-
- Dependency evaluation finds ONNX Runtime packaging, transitive dependency
424-
cost, license, or CPU/GPU split is not acceptable for sidecar-local ownership.
429+
- Dependency evaluation finds ONNX Runtime Rust packaging, transitive
430+
dependency cost, license, or CPU/GPU split is not acceptable for Rust
431+
ownership.
425432
- Required lifecycle/concurrency guarantees require a broader process manager
426433
refactor than this feature can safely include.
427434
- Cross-platform launch or path handling cannot be expressed through existing
@@ -445,11 +452,11 @@ changes remain.
445452
policy in one place.
446453
- Recommendation 3: Keep the first slice embedding-only. Add reranking or other
447454
ONNX tasks later behind explicit provider capability flags.
448-
- Recommendation 4: Do Milestone 0 before sidecar integration. It reduces the
455+
- Recommendation 4: Do Milestone 0 before ONNX execution integration. It reduces the
449456
risk that ONNX support cements current Ollama-vs-llama.cpp assumptions.
450-
- Recommendation 5: Keep the first complete vertical slice managed-sidecar
451-
first because the expected UX is setup, profile save, model route assignment,
452-
and serving from the ONNX app panel.
457+
- Recommendation 5: Keep the first complete vertical slice managed in-process
458+
runtime first because the expected UX is setup, profile save, model route
459+
assignment, and serving from the ONNX app panel.
453460
- Recommendation 6: Treat the ONNX model library panel as a provider-specific
454461
sibling of `LlamaCppModelLibrarySection`, not as a generic `ModelManager`
455462
variant. The user workflow is route/profile assignment plus serving, which is
@@ -502,7 +509,7 @@ changes remain.
502509
- llama.cpp router catalog compatibility projection now uses typed executable
503510
artifact values.
504511
- Runtime-profile managed/external validation now derives from provider launch
505-
kinds, including the reserved Python sidecar kind.
512+
kinds, including the previously reserved sidecar kind now superseded for ONNX.
506513
- Backend provider registry usage across existing runtime profiles, serving,
507514
gateway, compatibility, and launch-kind validation is complete.
508515
- RPC gateway and serving handlers now consume the provider registry from
@@ -557,6 +564,11 @@ changes remain.
557564
component below the size threshold before ONNX adds sibling UI.
558565
- Milestone 0 large-file split work is complete for the named ONNX provider
559566
prerequisite surfaces.
567+
- Rust ONNX re-plan is complete: the future Python sidecar milestone is
568+
replaced by a Rust ONNX provider/session skeleton, real ONNX Runtime
569+
execution moves into Rust dependency review/execution slices, and the aborted
570+
uncommitted Python sidecar files were removed before this documentation
571+
update.
560572

561573
### Deviations
562574

0 commit comments

Comments
 (0)