Skip to content

feat(plugin): add owned dynamic host activation#364

Open
bbednarski9 wants to merge 8 commits into
NVIDIA:mainfrom
bbednarski9:bbednarski/plugin-host-activation
Open

feat(plugin): add owned dynamic host activation#364
bbednarski9 wants to merge 8 commits into
NVIDIA:mainfrom
bbednarski9:bbednarski/plugin-host-activation

Conversation

@bbednarski9

@bbednarski9 bbednarski9 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Overview

This promotes dynamic-plugin activation from CLI-private orchestration into a core-owned lifecycle for harness-native embedding hosts. It deliberately does not replace the existing static plugin lifecycle: static-only callers continue to use normal plugin initialization, while PluginHostActivation requires at least one explicit dynamic plugin specification.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Lifecycle contract

  • initialize_plugins* / clear_plugin_configuration remain the static-only API.
  • PluginHostActivation::activate(base_config, dynamic_specs) is the owned dynamic API and rejects an empty dynamic_specs list with an actionable error.
  • The base config may include registered static components. Those initialize first; components contributed by loaded plugins are appended afterward, all in one transaction.
  • A process has one active plugin-configuration owner. Calling dynamic activation after static initialization is rejected; mixed users must pass static components in the dynamic activation's base config before initialization.
  • Manifest and worker-environment references are explicit paths resolved by the embedding host. Relay reads them during startup activation; this API does not discover installation state or continuously revalidate mutable files.

Details

  • Add public PluginHostActivation and DynamicPluginActivationSpec APIs for native and worker plugins.
  • Load plugin runtimes, append their configured components, and initialize the complete configuration transactionally.
  • Reject duplicate dynamic IDs before loading and protect built-in plugin IDs from preclaimed implementations.
  • Track registry registrations by unique ownership ID so teardown removes only the adapter it installed; a replacement is preserved and reported as a conflict.
  • Run plugin mutations on a process-wide, cancellation-resistant Relay executor with a stable Tokio runtime. Callers must not rely on activation callbacks running on their thread or runtime.
  • Clear callbacks and flush subscribers before deregistering owned plugin kinds, stopping workers, and unloading libraries.
  • Retain runtimes and the host owner when cleanup cannot prove safe unloading; otherwise release ownership while surfacing teardown errors.
  • Provide explicit clear() plus best-effort Drop cleanup that logs failures.
  • Refactor the CLI server to retain the legacy static lifecycle for static-only configurations and use the owned host only when dynamic specifications are present. CLI discovery and sidecar behavior are unchanged.

Where should the reviewer start?

Start with crates/core/src/plugin/dynamic/host.rs for the public lifecycle and executor contract, then crates/core/src/plugin.rs for ownership and transactional rollback. crates/cli/src/server.rs shows the static/dynamic dispatch. Native and worker integration tests cover mixed static/dynamic activation, conflicts, rollback, in-flight callbacks during teardown, cancellation, explicit clear, and drop cleanup.

Validation

  • cargo fmt --all -- --check
  • cargo clippy -p nemo-relay --features worker-grpc --all-targets -- -D warnings
  • cargo clippy -p nemo-relay-cli --all-targets -- -D warnings
  • Native plugin-host integration suite: 13 passed
  • Worker shutdown/recovery regression passed
  • Built-in ownership regression passed
  • Static activation cancellation regression passed
  • Static-only CLI lifecycle tests passed

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

None.

Summary by CodeRabbit

  • New Features
    • Added an owned activation/teardown lifecycle for dynamic native and worker plugins via an activation handle, with clearer activation/clear semantics.
    • Introduced tracked plugin registration ownership and stronger built-in kind protections to prevent conflicting activations.
  • Bug Fixes
    • Made plugin initialization rollback/deregistration panic-safe and more observable, improving reliability during partial failures.
    • Hardened dynamic host clearing/shutdown behavior, including safer worker shutdown and clearer error surfacing.
  • Tests
    • Expanded CLI coverage and core integration/unit tests for ownership, builtin reservation, clear behavior, cancellation/rollback, and worker lifecycle.
  • Documentation

@willkill07 willkill07 added this to the 0.6 milestone Jul 6, 2026
@github-actions github-actions Bot added size:XL PR is extra large Feature a new feature lang:rust PR changes/introduces Rust code labels Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 4bf17938-ec1c-4ac7-a0b6-e87de9ed5f31

📥 Commits

Reviewing files that changed from the base of the PR and between 004e35a and a7f7db1.

📒 Files selected for processing (1)
  • crates/core/tests/unit/plugin_tests.rs
📜 Recent review details
⏰ Context from checks skipped due to timeout. (20)
  • GitHub Check: Python / Test (linux-arm64)
  • GitHub Check: Node.js / Test (macos-arm64)
  • GitHub Check: Node.js / Test (windows-arm64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Node.js / Test (linux-arm64)
  • GitHub Check: Go / Test (macos-arm64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: Node.js / Test (linux-amd64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: Node.js / Test (windows-amd64)
  • GitHub Check: Rust / Test (linux-arm64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: License Diff / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (12)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/core/tests/unit/plugin_tests.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/unit/plugin_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/core/tests/unit/plugin_tests.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/core/tests/unit/plugin_tests.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/core/tests/unit/plugin_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/plugin_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/unit/plugin_tests.rs
🔇 Additional comments (2)
crates/core/tests/unit/plugin_tests.rs (2)

41-49: LGTM!

Also applies to: 1249-1249, 1283-1287


1279-1279: 🩺 Stability & Availability

Confirm teardown covers registered fixtures. Need to see whether the local teardown helper already deregisters the plugins or only resets other state.


Walkthrough

The plugin system now uses ownership-tracked registrations, serialized mutation transactions, dynamic host activation handles, checked teardown, and expanded lifecycle tests. CLI startup supports static and dynamic activation paths, while built-in plugins use explicit builtin ownership.

Changes

Plugin host lifecycle

Layer / File(s) Summary
Registry ownership and mutation transactions
crates/core/src/plugin.rs, crates/core/tests/unit/plugin_tests.rs
Plugin registrations track owners and IDs; initialization, clearing, rollback, panic handling, and mutation serialization report incomplete cleanup.
Dynamic host activation and runtime teardown
crates/core/src/plugin/dynamic/*
PluginHostActivation loads dynamic plugins, owns configuration, and performs checked native or worker teardown using registration IDs and guarded worker shutdown.
CLI lifecycle and builtin registration
crates/cli/src/server.rs, crates/core/src/plugins/*, crates/cli/tests/coverage/server_tests.rs
CLI initialization selects static or dynamic activation, and built-in components use explicit builtin registration semantics.
Host lifecycle integration coverage
crates/core/tests/integration/*, crates/core/tests/fixtures/*, crates/core/Cargo.toml
Integration fixtures and tests cover activation ownership, collisions, cancellation, rollback, native callbacks, worker shutdown, and builtin reservation behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant PluginHostActivation
  participant PluginRegistry
  participant NativeOrWorkerRuntime
  CLI->>PluginHostActivation: initialize dynamic plugin specifications
  PluginHostActivation->>PluginRegistry: acquire host lease and register built-ins
  PluginHostActivation->>NativeOrWorkerRuntime: load native or worker plugins
  NativeOrWorkerRuntime->>PluginRegistry: register tracked plugin kinds
  PluginHostActivation->>PluginRegistry: initialize owned configuration
  CLI->>PluginHostActivation: clear activation during shutdown
  PluginHostActivation->>PluginRegistry: clear callbacks and configuration
  PluginHostActivation->>NativeOrWorkerRuntime: deregister and stop runtimes
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits, uses a valid scope, stays under 72 characters, and accurately summarizes the change.
Description check ✅ Passed The description covers the required template sections and provides enough lifecycle, implementation, and validation detail.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

License Diff

Compared against origin/main.

Lockfile license changes

Lockfile License Changes

Rust

Added

  • None

Removed

  • switchyard-translation 0.1.0 (Apache-2.0)

Updated/Changed

  • None

Node

Added

  • None

Removed

  • None

Updated/Changed

  • None

Python

Added

  • None

Removed

  • None

Updated/Changed

  • None
Status output
[license-diff] selected languages: rust, node, python
[license-diff] generating current inventory
[license-diff] current: generating Rust inventory
[license-diff] current: Rust inventory complete (378 packages)
[license-diff] current: generating Node inventory
[license-diff] current: Node inventory complete (363 packages)
[license-diff] current: generating Python inventory
[license-diff] current: Python inventory complete (105 packages)
[license-diff] current inventory complete
[license-diff] checking out base ref origin/main into a temporary worktree
[license-diff] base: generating Rust inventory
[license-diff] base: Rust inventory complete (379 packages)
[license-diff] base: generating Node inventory
[license-diff] base: Node inventory complete (363 packages)
[license-diff] base: generating Python inventory
[license-diff] base: Python inventory complete (105 packages)
[license-diff] base inventory complete
[license-diff] removing temporary base worktree
[license-diff] comparing inventories
[license-diff] rendering Markdown output
[license-diff] done

Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
@bbednarski9 bbednarski9 force-pushed the bbednarski/plugin-host-activation branch from f73370e to 277f24e Compare July 13, 2026 16:36
@bbednarski9 bbednarski9 marked this pull request as ready for review July 13, 2026 16:47
@bbednarski9 bbednarski9 requested a review from a team as a code owner July 13, 2026 16:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/core/src/plugin.rs`:
- Around line 902-908: Update ensure_builtin_plugins_registered and the three
builtin registration helpers to use a read-lock fast path that confirms each
expected builtin is already correctly registered, returning without acquiring
write locks when all are present. Only escalate to the existing write-lock
registration and revalidation path when a builtin is missing, while preserving
replacement rejection and retry behavior for ownership conflicts.

In `@crates/core/src/plugin/dynamic/native.rs`:
- Around line 91-116: The checked teardown loops in
crates/core/src/plugin/dynamic/native.rs:91-116 and
crates/core/src/plugin/dynamic/worker.rs:137-162 duplicate
registration-accounting logic; extract it into a shared helper such as
deregister_tracked_registrations_checked that accepts the tracked registrations
and the “native” or “worker” label, then have deregister_plugin_kinds_checked in
both activation types call that helper while preserving all existing outcomes
and error handling.

In `@crates/core/tests/unit/plugin_tests.rs`:
- Around line 1236-1310: Make the PLUGIN_MUTATION_OWNER cleanup panic-safe in
test_legacy_clear_retains_mutation_owner_after_incomplete_teardown and
test_legacy_replace_retains_mutation_owner_after_incomplete_teardown. Add an
RAII guard after acquiring the runtime-owner lock that restores the owner to
Idle on Drop, including assertion failures, and remove the manual reset
statements at the test ends.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: c7bbf793-7860-4a03-93a5-444feae4b5b2

📥 Commits

Reviewing files that changed from the base of the PR and between e5eab9d and 277f24e.

📒 Files selected for processing (18)
  • crates/cli/src/server.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/tests/unit/plugin_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Check / Run
🧰 Additional context used
📓 Path-based instructions (21)
**/*.rs

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

When changing the core Rust runtime or Rust-facing API surface, format Rust code with cargo fmt (rustfmt defaults), keep cargo clippy -- -D warnings clean, and satisfy cargo deny check per deny.toml.

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
{crates/core,crates/adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions in Rust and Python: use snake_case.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,py,js,mjs,cjs,ts,tsx}: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/*.{rs,py,go,js,ts,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use language-appropriate naming conventions: Rust snake_case, C FFI exports prefixed nemo_relay_, Go PascalCase, Node.js camelCase, and Python snake_case.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/*.{rs,go,js,ts}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding // comment form.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings,
documentation, integrations, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
skills/       # Published Codex/agent skills for NeMo Relay usage patterns

Prerequisites

Insta...

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs
  • crates/core/tests/unit/dynamic_worker_tests.rs
  • crates/cli/tests/coverage/server_tests.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/integration/worker_plugin_tests.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/tests/unit/plugin_tests.rs
  • crates/core/tests/integration/native_plugin_tests.rs
{crates/**/src/**/*.rs,python/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not add tests under src; Rust tests belong in crate tests/ trees, and Python SDK tests belong under python/tests.

Files:

  • crates/core/src/observability/plugin_component.rs
  • crates/core/src/plugins/model_pricing.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/tests/fixtures/native_plugin/src/lib.rs
  • crates/core/tests/fixtures/worker_plugin/src/main.rs
  • crates/core/src/plugin/dynamic.rs
  • crates/cli/src/server.rs
  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
  • crates/core/src/plugin.rs
**/Cargo.toml

📄 CodeRabbit inference engine (.agents/skills/prepare-code-freeze/SKILL.md)

Confirm or infer the target release version from upstream/main:Cargo.toml. Derive the release branch as release/<major>.<minor>.

Keep Rust package names and workspace metadata in Cargo.toml internally consistent across the project.

Files:

  • crates/core/Cargo.toml
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add the SPDX license header to all TOML files using the # comment form.

Files:

  • crates/core/Cargo.toml
{crates/core/src/plugin/dynamic/**,crates/plugin/**,crates/worker/**,crates/worker-proto/**,crates/types/**,python/plugin/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Keep the stable boundary explicit: native plugins cross a C ABI, and worker plugins cross grpc-v1.

Files:

  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
{crates/core/src/plugin/dynamic/**/*.rs,examples/rust-native-plugin/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Do not pass Rust runtime types, trait objects, futures, or allocator-owned strings across the native dynamic-library boundary.

Files:

  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
{crates/core/src/plugin/dynamic/**,examples/rust-native-plugin/**,examples/python-grpc-worker-plugin/**,docs/build-plugins/**}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Native and worker plugins are trusted extensions; document that native plugins are in-process and unsandboxed, and worker plugins provide process isolation but not a security sandbox.

Files:

  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
{crates/core/src/plugin/dynamic/**/*.rs,crates/plugin/**/*.rs,crates/worker/**/*.rs,crates/worker-proto/**/*.rs,python/plugin/**/*.py}

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

Manifest validation must cover kind, compatibility, load contract, integrity, capability mismatch, and disabled-plugin behavior.

Files:

  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
crates/core/src/plugin/dynamic/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)

The native loader must keep libraries alive until registered callbacks are cleared and must deregister plugin kinds before unload.

Files:

  • crates/core/src/plugin/dynamic/host.rs
  • crates/core/src/plugin/dynamic/native.rs
  • crates/core/src/plugin/dynamic/worker.rs
🔇 Additional comments (27)
crates/core/tests/unit/dynamic_worker_tests.rs (1)

1481-1481: LGTM!

crates/core/tests/unit/plugin_tests.rs (5)

12-12: LGTM!

Also applies to: 30-40


304-413: LGTM!

Also applies to: 433-436


950-978: LGTM!


1027-1066: LGTM!

Also applies to: 1096-1184


1186-1235: LGTM!

crates/core/src/plugin.rs (4)

863-896: LGTM!


926-993: LGTM!


1186-1389: LGTM!


1536-1712: LGTM!

Also applies to: 1738-1885

crates/core/src/plugin/dynamic.rs (1)

21-58: LGTM!

crates/core/src/plugin/dynamic/native.rs (1)

118-133: LGTM!

Also applies to: 145-158

crates/core/src/plugin/dynamic/worker.rs (1)

164-179: LGTM!

Also applies to: 191-204, 265-424, 603-603

crates/core/src/observability/plugin_component.rs (1)

58-58: LGTM!

Also applies to: 547-549

crates/core/src/plugins/model_pricing.rs (1)

17-25: LGTM!

crates/core/src/plugins/nemo_guardrails/component.rs (1)

18-18: LGTM!

Also applies to: 400-402

crates/core/tests/integration/native_plugin_tests.rs (2)

8-144: LGTM!


1110-1614: LGTM!

Also applies to: 1649-1657, 1776-1789

crates/core/src/plugin/dynamic/host.rs (2)

33-63: LGTM!

Also applies to: 88-166, 210-425


167-196: 🩺 Stability & Availability

No action needed The panic path still drops PendingPluginRegistrations/PendingPluginRegistrationContext, so rollback failures are recorded during unwinding before this branch runs. failures.is_empty() here means there was nothing left to retain, so unloading the runtimes is safe.

			> Likely an incorrect or invalid review comment.
crates/cli/src/server.rs (1)

149-203: LGTM!

Also applies to: 317-379

crates/cli/tests/coverage/server_tests.rs (1)

1705-1734: LGTM!

crates/core/Cargo.toml (1)

124-127: LGTM!

crates/core/tests/fixtures/native_plugin/src/lib.rs (1)

283-298: LGTM!

crates/core/tests/fixtures/worker_plugin/src/main.rs (1)

87-87: LGTM!

Also applies to: 133-133, 156-159

crates/core/tests/integration/plugin_host_builtin_ownership_tests.rs (1)

19-80: LGTM!

crates/core/tests/integration/worker_plugin_tests.rs (1)

26-31: LGTM!

Also applies to: 48-128

Comment thread crates/core/src/plugin.rs
Comment thread crates/core/src/plugin/dynamic/native.rs
Comment thread crates/core/tests/unit/plugin_tests.rs

@mnajafian-nv mnajafian-nv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is moving in a good direction. I left two focused inline comments on validation/activation alignment and the retained-owner activity contract.

Comment thread crates/core/src/plugin.rs
@@ -908,10 +985,11 @@ pub fn list_plugin_kinds() -> Vec<String> {
/// The returned plugin is shared by [`Arc`], so callers receive a cheap clone.
pub fn lookup_plugin(plugin_kind: &str) -> Option<Arc<dyn Plugin>> {
let _ = ensure_builtin_plugins_registered();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I’d tighten before merge: this drops builtin-registration failure on the read path, while activation now treats the same condition as a hard error. With a preclaimed builtin kind, that can let validation or lookup-based checks proceed and only fail later during activation. I’d rather keep those paths aligned by surfacing the failure here, or add a regression that makes the intended mismatch explicit if that behavior is deliberate.

if !self.active {
return Ok(());
}
self.active = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One contract detail seems worth making explicit before merge: self.active flips to false before teardown is proven safe, but later paths intentionally retain the runtimes and host claim when callbacks cannot be cleared or unload is unsafe. In that state a binding can report inactive even though a new activation would still conflict on retained ownership. I’d either keep active true until the claim is actually released, or document and test that is_active() means 'this handle is no longer reusable' rather than 'the process is ready for another activation.'

@bbednarski9

Copy link
Copy Markdown
Contributor Author

CLI lifecycle selection:

flowchart TD
    A["Relay CLI startup"] --> B{"Any plugin configuration"}
    B -->|"No"| C["Run without plugin activation"]
    B -->|"Yes"| D{"Dynamic plugin specs present"}
    D -->|"No"| E["Use existing static initialization"]
    D -->|"Yes"| F["Create PluginHostActivation"]
    E --> G["Run gateway"]
    F --> G
    G --> H["Close sessions and flush subscribers"]
    H --> I{"Activation type"}
    I -->|"Static"| J["Clear static configuration"]
    I -->|"Dynamic"| K["Clear dynamic host"]
Loading

@bbednarski9

Copy link
Copy Markdown
Contributor Author

Dynamic activation:

sequenceDiagram
    participant Caller
    participant Executor as Lifecycle executor
    participant Owner as Process owner
    participant Loader
    participant Registry
    participant Config as Configuration runtime

    Caller->>Executor: Activate base config and specs
    Executor->>Executor: Validate nonempty and unique IDs
    Executor->>Owner: Acquire exclusive host lease
    Owner-->>Executor: Return owner ID
    Executor->>Registry: Ensure built-in plugin kinds
    Executor->>Loader: Load native libraries
    Executor->>Loader: Start worker processes
    Loader->>Registry: Register adapters with registration IDs
    Executor->>Config: Append dynamic components after static components
    Executor->>Config: Validate and initialize components

    alt Initialization succeeds
        Config-->>Caller: Activation guard and report
    else Initialization fails cleanly
        Config->>Registry: Roll back component registrations
        Loader->>Registry: Deregister adapters
        Loader->>Loader: Unload libraries and workers
        Owner->>Owner: Release lease
        Config-->>Caller: Activation error
    else Rollback cannot prove safety
        Loader->>Loader: Retain loaded runtimes
        Owner->>Owner: Retain lease
        Config-->>Caller: Incomplete rollback error
    end
Loading

@bbednarski9

Copy link
Copy Markdown
Contributor Author

Safe teardown:

flowchart TD
    A["Clear activation"] --> B["Flush subscribers and remove component callbacks"]
    B --> C{"Callbacks proven removed"}
    C -->|"No"| D["Retain runtimes and owner for process lifetime"]
    D --> E["Return teardown error"]
    C -->|"Yes"| F["Deregister plugin adapters by registration ID"]
    F --> G{"Adapters safe to unload"}
    G -->|"No"| D
    G -->|"Yes"| H["Shut down worker processes"]
    H --> I{"Worker shutdown safe"}
    I -->|"No"| D
    I -->|"Yes"| J["Unload libraries and runtimes"]
    J --> K["Release process owner"]
    K --> L["Return success or recoverable teardown error"]
Loading

Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Signed-off-by: Bryan Bednarski <bbednarski@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature a new feature lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants