# WeavePort
> Embedded .NET 10 backend plugin platform for owner-controlled C#, Python and TypeScript plugins.
Read the current status and exact package compatibility before generating integration code. The public core release is 0.3.1 with an evolving pre-1.0 API. The historical internal distribution is separate. Native processes are trusted execution and do not sandbox hostile plugins. Applications own authorization, domain contracts and durable state.
Generated by `python3 scripts/generate-llms.py`. This is retrieval documentation, not an MCP endpoint. A client must fetch these files or index them through a documentation MCP service.
Prefer the smaller llms.txt index for targeted retrieval. Sources below belong to the same checkout.
---
## Overview
Source: https://weaveport.dev/overview.md
# Turn your .NET app into a platform.
**Add C#, Python and TypeScript plugins—and reuse local MCP tools—in your .NET product.** WeavePort runs them, connects them to approved application services and manages their workers. Your application owns the data, permissions and business rules.
Build document readers, evaluation strategies or customer-specific scheduling rules as plugins. Give each one the access it needs and call it through the same .NET client contract.
[Get started](https://weaveport.dev/docs/getting-started.md) · [Why WeavePort?](https://weaveport.dev/docs/introduction.md) · [Write a plugin](https://weaveport.dev/docs/plugin-sdk.md) · [NuGet packages](https://weaveport.dev/docs/packages.md) · [Use MCP tools](https://weaveport.dev/docs/mcp-plugins.md)
**MIT · .NET 10 · Windows, Linux & macOS · Public release 0.3.1**
Built for .NET. Designed for Windows, Linux and macOS. The supported cross-platform execution path uses standard input/output (stdio) for owner-controlled plugins. Current release validation covers macOS arm64; Windows and Linux release validation is pending. See the [platform support and validation matrix](https://weaveport.dev/docs/platform-qualification.md). The pre-1.0 API is evolving; native processes are not a sandbox for hostile code.
## Build with your AI assistant
Point your assistant at [llms.txt](https://weaveport.dev/llms.txt), or load the [full reference](https://weaveport.dev/llms-full.txt). [Connect GitHub MCP](https://weaveport.dev/docs/ai-documentation.md#connect-the-official-github-mcp-server) to retrieve matching source, examples and API contracts directly from the repository.
## Why WeavePort?
- **Let each extension use the right language.** Write plugins in C#, Python or TypeScript and invoke them through one .NET client interface. Function names and JSON schemas remain your application's contract.
- **Keep data access in your application.** Give native plugins explicit callback capabilities. Your host supplies the authenticated context and checks access to individual objects.
- **Share the runtime work.** One host manages worker startup, deadlines, admission and cleanup. The coordinator template shares those budgets across application operations.
- **Keep your product's architecture.** Your application chooses its database, workflows and recovery policy. WeavePort arrives as NuGet libraries you embed in your backend.
## Reuse tools your team already has
A capability may already have an MCP server. Hosting can launch that trusted local server, discover its tools and call them from C# under the same lifecycle and tenant budgets as native plugins. One server can expose many ordinary functions; no AI model is required.
Choose native plugins for application-specific contracts, granted callbacks and result streams. Choose the optional MCP tools subset for existing local servers. Native remains the default; MCP adds no runtime package dependency to Hosting.
[Run the C# MCP example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/mcp/README.md) or [follow the integration guide](https://weaveport.dev/docs/mcp-plugins.md). Supported revisions: **2025-11-25 and 2026-07-28**, over **local stdio**, with `tools/list` and `tools/call`. Remote HTTP, interactive continuations and an exported MCP gateway are outside this release. Local servers still require trusted code.
## See it working
Decision Room runs C# and Python strategies against the same proposals. The application grants knowledge access and saves the resulting evaluations. With the default configuration, **B — Automate support** wins with a score of **11**.
This Bash walkthrough is validated on macOS arm64. Linux can use the same source workflow, with release validation pending; native Windows needs equivalent build steps and Windows interpreter paths (the script assumes a Unix virtual environment). Install the .NET SDK in [global.json](https://raw.githubusercontent.com/yesbert/WeavePort/main/global.json) and Python 3.11+ with `venv` and `pip`, then run:
```sh
git clone https://github.com/yesbert/WeavePort.git
cd WeavePort
./scripts/decision-room.sh --build
```
The first build restores packages and creates a private Python environment. The example needs no external database, account or Docker service. [Follow the walkthrough](https://weaveport.dev/docs/getting-started.md) to change a strategy, resume a journal and run verification.
## A plugin is an ordinary function
This minimal Python provider exposes an `echo` function to an authorized host binding:
```python
from weaveport_sdk import PluginApplication
app = PluginApplication()
@app.function("echo")
async def echo(value, context):
return value
app.run()
```
The same SDK supports asynchronous result streams and granted host callbacks. Python and TypeScript SDKs are built from the repository; they are not yet published to PyPI or npm. See the complete [Python](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/sdk/python/plugin.py), [C#](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/sdk/csharp/Program.cs) and [TypeScript](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/sdk/typescript/plugin.ts) examples and the [authoring guide](https://weaveport.dev/docs/plugin-sdk.md).
## Add WeavePort to your application
In the .NET application project:
```sh
dotnet add package WeavePort.Hosting --version 0.3.1
dotnet add package WeavePort.Sdk.Client --version 0.3.1
```
For a C# plugin, reference `WeavePort.Sdk` at the same version. `WeavePort.Abstractions` contains the shared contracts. These are the four public packages; optional Gateway, Composition and Testing are outside this release.
[Compose one host](https://weaveport.dev/docs/embedded-coordinator.md), [select approved plugin artifacts](https://weaveport.dev/docs/installed-plugins.md) and [check exact compatibility](https://weaveport.dev/docs/package-compatibility.md). Package installation supplies the libraries; the runnable examples show the complete integration.
## Start from a real use case
| You want to… | Start here | What you will learn |
|---|---|---|
| Let customers choose an evaluation strategy | [Decision Room](https://weaveport.dev/docs/examples/DecisionRoom.md) | C#/Python strategies, scoped knowledge and replay |
| Add readers for different document sources | [Document Workshop](https://weaveport.dev/docs/examples/DocumentWorkshop.md) | Interchangeable readers, bounded access and staged commits |
| Make scheduling rules replaceable | [Appointment Desk](https://weaveport.dev/docs/examples/AppointmentDesk.md) | Shared admission, idempotent actions and recovery |
Each example includes a `--build --verify` runner under `scripts/`. Its domain contracts and storage belong to the application, so you can study the integration independently of a particular database or sibling framework.
## Choose with the full picture
WeavePort is a fit when you control the plugin code and want an extensible .NET backend. Native workers have the application's OS-user rights. If you need to execute arbitrary untrusted uploads, that requires a stronger, separately qualified execution boundary.
Worker memory is temporary; applications own durable state and the handling of uncertain external effects. Windows, Linux and macOS are supported targets for trusted stdio execution; platform-specific release validation and remote production qualification are separate. See the [platform matrix](https://weaveport.dev/docs/platform-qualification.md). Read [current status](https://weaveport.dev/docs/status.md), [security boundaries](https://weaveport.dev/docs/security-architecture.md) and [recovery guidance](https://weaveport.dev/docs/native-operations.md) before deployment.
## Documentation, help and contributions
- [Introduction](https://weaveport.dev/docs/introduction.md), [first example](https://weaveport.dev/docs/getting-started.md) and [FAQ](https://weaveport.dev/docs/faq.md).
- [Architecture](https://weaveport.dev/docs/architecture.md), [worker lifecycle](https://weaveport.dev/docs/worker-lifecycle.md) and [diagnostics](https://weaveport.dev/docs/runtime-diagnostics.md).
- [AI documentation](https://weaveport.dev/docs/ai-documentation.md) and the [llms.txt index](https://weaveport.dev/llms.txt).
- [Report an issue or suggest an improvement](https://github.com/yesbert/WeavePort/issues).
- [Contribute](https://raw.githubusercontent.com/yesbert/WeavePort/main/CONTRIBUTING.md), [run focused checks](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/README.md) or [build the documentation website](https://raw.githubusercontent.com/yesbert/WeavePort/main/website/README.md).
Maintained by [Norbert Rosenwinkel](https://github.com/yesbert). Released under the [MIT license](https://raw.githubusercontent.com/yesbert/WeavePort/main/LICENSE).
---
## Introduction
Source: https://weaveport.dev/docs/introduction.md
---
title: Introduction
description: Make your .NET product extensible with owner-approved C#, Python and TypeScript plugins. Learn where WeavePort fits and run a complete example.
---
# Build a product others can extend
WeavePort adds a plugin execution layer to your .NET application. Use it to run document readers, evaluation strategies and business rules written in C#, Python or TypeScript. You define the extension points; WeavePort handles the workers behind them.
## When WeavePort helps
Your application already has a workflow, but part of it needs to vary. One customer needs a different scheduling rule. A team wants to add a document reader. An evaluator is easier to implement in Python while the product is written in .NET.
Make that part a plugin. The application selects the approved artifact, supplies its context and calls a function. Plugins can request data or actions through callbacks that the host explicitly grants.
## What you gain
| Application need | WeavePort's part | Your part |
|---|---|---|
| Support more than one plugin language | C#, Python and TypeScript SDKs with one .NET client interface | Define function names and request/result schemas |
| Connect plugins to application data | Host-bound context and callback grants | Authenticate callers and authorize individual objects |
| Run many application operations | Shared worker management, deadlines and admission | Choose budgets and handle overload |
| Recover after interrupted work | Worker restart, cancellation and cleanup accounting | Persist state and reconcile uncertain effects |
## How it fits
1. **Define the contract.** Choose an operation such as reading a document or scoring a proposal, along with its JSON request and result.
2. **Write the plugin.** Register an ordinary asynchronous function or result stream through a language SDK.
3. **Bind it in your application.** Select an installed artifact, trusted execution profile, tenant context and callback grants.
4. **Call it and use the result.** Validate the response and commit application state under your own rules.
The [core concepts](https://weaveport.dev/docs/concepts.md) explain bindings, callbacks and ownership. The [integration guide](https://weaveport.dev/docs/embedded-coordinator.md) shows how operations share one host.
## Start with the right expectations
WeavePort's native execution is for **owner-controlled code**. Workers run with the application's OS-user rights; separate processes are not a hostile-plugin sandbox. The current public release is 0.3.1 under MIT, with an evolving API. Windows, Linux and macOS are supported targets for trusted stdio execution. Current release validation covers macOS arm64; Windows and Linux release validation is pending. See [platform support and validation](https://weaveport.dev/docs/platform-qualification.md) for transport and tooling differences.
Your application keeps its database and workflow architecture. It also keeps responsibility for durable state, retries and the meaning of external effects. A cancelled call does not prove an action never happened.
See [packages and support](https://weaveport.dev/docs/packages.md) and the [FAQ](https://weaveport.dev/docs/faq.md), then choose a [running example](https://weaveport.dev/docs/getting-started.md).
## Bring existing MCP tools into the same host
If a team already maintains an MCP server, you can reuse its local tools from C# instead of writing another protocol wrapper. WeavePort owns startup, deadlines, capacity and cleanup; your application chooses which tools it may invoke. Ordinary strategies can keep using native plugins with granted callbacks and streams.
The optional integration supports `tools/list` and `tools/call` over local stdio, with explicitly selected 2025-11-25 and 2026-07-28 revisions. It requires trusted code and does not add a network endpoint or AI runtime. [Try the MCP example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/mcp/README.md).
---
## Quickstart
Source: https://weaveport.dev/docs/getting-started.md
---
title: Run your first plugin workflow
description: Run Decision Room, see C# and Python plugins score proposals, and follow the application from granted knowledge access to a saved result.
---
# Run your first plugin workflow
See WeavePort in a complete application: two participants evaluate three proposals using C# or Python plugins. The host grants knowledge access, validates the evaluations and saves the decision. You will finish with a result you can inspect and a host you can adapt.
> **Expected result:** with the default version 1 configuration, **B — Automate support** wins with a total score of **11**.
## Before you start
WeavePort supports Windows, Linux and macOS for trusted stdio execution. This walkthrough uses a Bash runner with Unix virtual-environment paths and has been validated on macOS arm64. Linux can use the same source workflow, with release validation pending. For native Windows, use equivalent .NET build steps and Windows interpreter paths; this Bash runner is not a native Windows launcher. See [platform support and validation](https://weaveport.dev/docs/platform-qualification.md).
Install Git, the .NET SDK selected by [global.json](https://raw.githubusercontent.com/yesbert/WeavePort/main/global.json) (currently 10.0.401) and Python 3.11+ with `venv` and `pip`.
The first build restores packages from the network. The example runs locally without an external database, an account or a Docker service. Native plugins run as trusted code with your OS-user rights.
## 1. Clone and run
```sh
git clone https://github.com/yesbert/WeavePort.git
cd WeavePort
./scripts/decision-room.sh --build
```
The runner packs the platform libraries, builds the host and C# worker, installs the Python SDK into a private environment and runs the example. It consumes packages built from that checkout. To inspect the exact public release source, select the `v0.3.1` tag; main may contain later work.
## 2. Check the result
With the default configuration, the application combines the participants' evaluations:
| Proposal | Combined score |
|---|---:|
| A — Improve documentation | 3 |
| B — Automate support | **11** |
| C — Build analytics | -3 |
B wins. The [sample walkthrough](https://weaveport.dev/docs/examples/DecisionRoom.md) explains the calculation and the knowledge profiles behind it.
## 3. Follow one plugin call
1. The application selects a plugin artifact and binds a participant's context.
2. The plugin requests knowledge through a granted callback.
3. The host returns knowledge scoped to that participant.
4. The plugin calculates an evaluation.
5. The application validates and commits the result to its journal.
This is the extension point you can reuse: plugin-specific logic, application-owned access and durable results.
## 4. Make it your own
Read the sample's [configuration guide](https://weaveport.dev/docs/examples/DecisionRoom.md#change-behavior-through-configuration) to switch languages or scoring priorities. Use a separate journal for a new configuration. The host keeps the workflow while plugin selection changes the evaluation strategy.
To resume the existing run or execute the verification fixtures:
```sh
./scripts/decision-room.sh --resume
./scripts/decision-room.sh --build --verify
```
A fresh run refuses to overwrite an existing journal. Pass `--journal artifacts/decision-room/runs/another.json` for a separate run. Rebuilding changed artifacts can intentionally invalidate earlier journal identity checks. Verification uses dedicated fixtures, including worker termination and recovery.
## Choose your next example
Ready to integrate? [Write a plugin](https://weaveport.dev/docs/plugin-sdk.md), [embed one coordinator](https://weaveport.dev/docs/embedded-coordinator.md) and [select installed artifacts](https://weaveport.dev/docs/installed-plugins.md). See [packages and support](https://weaveport.dev/docs/packages.md) for release and deployment boundaries.
---
## FAQ
Source: https://weaveport.dev/docs/faq.md
---
title: Frequently asked questions
description: Decide whether WeavePort fits your .NET application, understand plugin trust and language support, and find the right starting point.
---
# Is WeavePort right for my product?
Start here if you are deciding how to make your .NET backend extensible. These answers describe the current 0.3.1 release and link to the detailed contracts.
## What would I use it for?
A replaceable part of an application workflow: a document reader, a scoring strategy or a scheduling rule. WeavePort runs the plugin; your application decides which plugin to use, what it may access and which results to save.
The [three example applications](https://weaveport.dev/docs/getting-started.md#choose-your-next-example) show those patterns end to end.
## Does my whole application have to use WeavePort?
You embed the libraries where you need plugin execution. Your existing services, domain types and data stores remain application-owned. The [coordinator template](https://weaveport.dev/docs/embedded-coordinator.md) is copyable application source for sharing a host and execution budgets.
## Can I use a Python plugin in a C# application?
Yes. WeavePort has author SDKs for C#, Python and TypeScript and a shared .NET client interface. Your application defines the function name and JSON schema, then selects a compatible artifact. Changing language is not a promise that arbitrary implementations have the same business behavior.
C# packages are public on NuGet. Python and TypeScript SDKs are built and packaged from the repository; they are not currently published to PyPI or npm. See [author SDKs](https://weaveport.dev/docs/plugin-sdk.md).
## Does it sandbox plugins?
Native workers are trusted processes running with the application's OS-user rights. They are suitable for code controlled by the operator. They do not prevent hostile code from accessing that user's files or network.
Callback grants govern access through the WeavePort callback API. They are not an OS sandbox. Read [security and trust boundaries](https://weaveport.dev/docs/security-architecture.md) before choosing an execution profile.
## Is it a workflow engine or database?
Your application owns workflows, persistence and external-action semantics. WeavePort provides the execution layer, including binding, invocation, callbacks, admission and worker lifecycle. The examples demonstrate application-owned journals and recovery policies; these do not become a universal storage guarantee.
## Can I run it on Windows or Linux?
Yes. Windows, Linux and macOS are supported targets for trusted plugin execution over standard input/output (stdio), with .NET 10 and the required plugin runtimes installed. Windows is explicitly handled in process startup, environment setup and workspace creation. The optional Unix-socket mode is available on Linux and macOS only.
Support describes the implemented execution path, not completed testing on every OS: current release validation covers macOS arm64; Windows and Linux release validation is pending. Historical Linux tests cover specific VM/container environments. The example Bash scripts assume Unix paths and are not native Windows launchers. See the [platform support and validation matrix](https://weaveport.dev/docs/platform-qualification.md).
## What happens when a plugin crashes?
The host observes worker failure and manages restart and cleanup under its lifecycle policy. Worker-local memory is temporary. The application decides whether a request can be repeated and whether an external effect is uncertain. The [recovery runbook](https://weaveport.dev/docs/native-operations.md) and [worker lifecycle](https://weaveport.dev/docs/worker-lifecycle.md) explain the limits.
## Is it free to use?
The four public core NuGet packages are released under the [MIT license](https://raw.githubusercontent.com/yesbert/WeavePort/main/LICENSE). The current version is 0.3.1. Review [packages and compatibility](https://weaveport.dev/docs/packages.md) before adopting or upgrading the evolving API.
## Where should I start?
[Run Decision Room](https://weaveport.dev/docs/getting-started.md). It builds the C# and Python plugins, executes a complete application workflow and gives you an expected result to check. For questions or reproducible problems, [open a GitHub issue](https://github.com/yesbert/WeavePort/issues).
## Can I reuse an existing MCP server?
Yes, if it offers the supported local stdio tools subset. Hosting 0.3.1 can discover and call tools using MCP 2025-11-25 or 2026-07-28, with the same lifecycle and tenant budgets as native plugins. You deploy the trusted server and select the protocol explicitly. One server may offer several tools; no AI model is required. See [MCP tools](https://weaveport.dev/docs/mcp-plugins.md).
This does not turn every plugin into an MCP server. Native callbacks and streams remain native; remote HTTP, resources, prompts and interactive continuations are outside this release.
---
## Platforms
Source: https://weaveport.dev/docs/platform-qualification.md
# Platform support and validation
**Windows, Linux and macOS are supported targets for trusted plugin execution over standard input/output (stdio).** Install .NET 10 and the runtimes required by your plugins on an OS/architecture supported by those runtimes. Support here identifies the implemented execution path; it does not claim that the current release has passed validation on every target. Current release validation covers macOS arm64; Windows and Linux release validation is pending.
WeavePort's contracts, tenant binding and protocol are shared .NET code. Process launch, communication, filesystem permissions and resource enforcement are platform-specific concerns. Successful compilation is not runtime, security or performance qualification.
| Environment | Execution and evidence | Remaining limits |
| --- | --- | --- |
| macOS arm64 | Trusted process stdio/socket; qualified packaged multilingual checks; current benchmarks are linked from [status](https://weaveport.dev/docs/status.md) | No hostile-code sandbox; unsigned developer bundle; system-wide memory/swap includes background applications |
| Linux arm64, Docker Desktop VM | Historical container and trusted-process comparisons; no current delivered-package qualification | Ordinary children still live inside the trusted coordinator container; not bare metal or independent hardware |
| Windows x64, GitHub-hosted Windows Server 2025 | Native stdio adapter fixtures passed: 38 checks across C#, Python and TypeScript | Current public-package installation, performance and stronger security qualification remain separate |
| Linux x64, GitHub-hosted Ubuntu 24.04 | Native adapter fixtures passed: 38 stdio and 39 socket checks | Current release installation, other distributions/architectures and performance remain separate |
| Other CPU architectures/distributions | Intended platform targets where .NET and required plugin runtimes are available | Not implied by arm64 results |
## Transport and tooling
Stdio is the default on all three operating systems. The optional `UseUnixSocket` profile is supported on Linux and macOS and explicitly rejected on Windows. Windows startup handles its system directory, path separator and workspace creation explicitly. Native workers run with the application's OS-user rights on every platform.
The NuGet libraries are distinct from the example launch scripts and historical offline distribution. Repository Bash runners assume Unix executable and virtual-environment paths; native Windows needs equivalent build steps and Windows interpreter paths. The historical offline bundle targets macOS arm64 and cannot be installed unchanged on Windows or Linux.
The [first native CI run](https://github.com/yesbert/WeavePort/actions/runs/34828099259) passed on Windows x64 and Ubuntu x64 with Python 3.14.7 and Node 24.20.0, using freshly packed source libraries and the existing multilingual adapter fixtures. This is source functional evidence, not installation qualification of every public package or an OS sandbox. [Continuous integration](https://weaveport.dev/docs/continuous-integration.md) describes the recurring jobs and retained reports. Windows performance qualification remains open.
## Common acceptance matrix
Each actual target must run the same tenant A/B fixtures for C#, Python and TypeScript: context separation, callbacks, independent workspace/state, crash/hang/cancellation, restart, and cleanup. Capacity evidence includes one outstanding request per active customer, small/large payloads, per-customer tails, all errors, growth, stop reason and recovery. BenchmarkDotNet iteration statistics stay separate from request-level capacity evidence.
Select an explicit supported transport; never silently downgrade a requested security profile. Buffer sizes measured on macOS are workload-specific configuration, not portable defaults. Native execution currently trusts plugin code on every platform: separate processes alone do not establish an adversarial tenant boundary.
## Windows qualification entry point
Use a Windows machine with the repository SDK, Python 3.14+ and Node 24.12+. Keep interpreter paths explicit in a local JSON configuration if `python3`/`node` discovery does not resolve the intended installation. Execute the existing C# consumer, not a reimplementation of its tests:
```powershell
# After packing the three src packages into artifacts/packages and publishing the C# fixture:
dotnet restore tests/WeavePort.Local.Tests --force --no-cache
dotnet build tests/WeavePort.Local.Tests -c Release
# Configure writes fixture paths relative to this checkout; doctor checks actual prerequisites.
dotnet tests/WeavePort.Local.Tests/bin/Release/net10.0/WeavePort.LocalDemo.dll configure . artifacts/local/config.json
$env:WEAVEPORT_LOCAL_TRANSPORT = 'stdio'
Remove-Item Env:WEAVEPORT_LOCAL_SOCKET_BUFFER_BYTES -ErrorAction SilentlyContinue
dotnet tests/WeavePort.Local.Tests/bin/Release/net10.0/WeavePort.LocalDemo.dll verify artifacts/local/config.json artifacts/runs/windows-functional
```
The CI runner uses equivalent build/verification steps with explicit interpreter paths; the PowerShell sequence above has not been independently qualified. Before Windows capacity qualification, add and validate a Windows system memory/commit observer: the current native observer returns unavailable system headroom outside macOS/Linux. A conservative summed-RSS ceiling does not replace that qualification. Evaluate a Windows transport adapter separately if stdio is insufficient; preserve common contracts and multilingual compatibility.
See [local installation](https://weaveport.dev/docs/internal-distribution.md), [execution boundaries](https://weaveport.dev/docs/local-execution.md) and [platform comparison results (historical) — pre-public record](https://weaveport.dev/docs/history.md).
---
## Packages
Source: https://weaveport.dev/docs/packages.md
# Packages and support
Install the runtime in your .NET application and the author SDK in each C# plugin project. The current public NuGet release is **0.3.1**, licensed under MIT. Use the same exact version across the four core packages.
| Package | Use it for |
|---|---|
| [WeavePort.Abstractions](https://www.nuget.org/packages/WeavePort.Abstractions/0.3.1) | Shared host, session and execution contracts |
| [WeavePort.Hosting](https://www.nuget.org/packages/WeavePort.Hosting/0.3.1) | Binding, execution profiles, callbacks, admission and worker lifecycle |
| [WeavePort.Sdk](https://www.nuget.org/packages/WeavePort.Sdk/0.3.1) | Authoring C# plugin functions and streams |
| [WeavePort.Sdk.Client](https://www.nuget.org/packages/WeavePort.Sdk.Client/0.3.1) | Typed application calls over an authorized local session |
In the application project:
```sh
dotnet add package WeavePort.Hosting --version 0.3.1
dotnet add package WeavePort.Sdk.Client --version 0.3.1
```
In a C# plugin project:
```sh
dotnet add package WeavePort.Sdk --version 0.3.1
```
Package installation supplies libraries. The application still composes a host, selects installed artifacts and binds authorized contexts. The [first example](https://weaveport.dev/docs/getting-started.md) shows the complete wiring.
## Language and deployment scope
| Area | Current boundary |
|---|---|
| C# | Public NuGet author SDK; .NET 10 |
| Python | Repository-built `weaveport-sdk` wheel; no PyPI publication |
| TypeScript | Repository-packed `@weaveport/sdk` archive; no npm publication |
| Windows, Linux and macOS | Supported targets for trusted stdio execution with .NET 10 and required plugin runtimes |
| Release validation | macOS arm64 validated; Windows and Linux release validation pending |
| Optional Unix-socket transport | Linux and macOS only; unavailable on Windows |
| Example scripts / offline bundle | Bash scripts assume Unix paths; the historical offline bundle is macOS arm64-specific |
| Container deployment | Separate execution profile; historical experiments do not qualify every topology |
| Optional Gateway, Composition, Testing | Outside the four-package public release |
| NativeAOT / remote production | Not qualified by this release |
See [platform support and validation](https://weaveport.dev/docs/platform-qualification.md) for the distinction between supported execution paths and tested releases.
The API is pre-1.0 and evolving. The host API, wire protocol, package version and plugin artifact version are separate identities. Read [exact compatibility](https://weaveport.dev/docs/package-compatibility.md), [release procedure](https://weaveport.dev/docs/releases.md) and [current status](https://weaveport.dev/docs/status.md) before choosing a deployment.
## MCP support is included in Hosting
`WeavePort.Hosting` 0.3.1 includes optional local MCP tools with no additional MCP runtime dependency. Use the low-level session contract for `tools/list` and `tools/call`; `WeavePort.Sdk.Client` remains the native typed/streaming client. Deploy the trusted server and its language dependencies separately. [Complete MCP guide](https://weaveport.dev/docs/mcp-plugins.md).
---
## Status
Source: https://weaveport.dev/docs/status.md
# Product status
Public NuGet version: **0.3.1**, under MIT, with four core packages: Abstractions, Hosting, Sdk and Sdk.Client. Windows, Linux and macOS are supported targets for trusted stdio execution. Current release validation covers macOS arm64; Windows and Linux release validation is pending. See [platform support and validation](https://weaveport.dev/docs/platform-qualification.md). This pre-1.0 API remains subject to evolution. Python/TypeScript registry publication and a new offline distribution are outside this release. The historical internal distribution remains **0.1.0-internal.2**.
The [0.3.0 release evidence](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.3.0/README.md) records 1,088 assertion executions, exact tested package/symbol provenance, successful Trusted Publishing and measurements of the released Hosting assembly. Earlier [0.2.1 evidence](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.2.1/README.md) remains available as historical release data.
Implemented and checked: immutable installed-artifact selection, exact compatibility/API gates, shared coordinator template, guarded native recovery, optional safe diagnostics and standalone offline installation. The [candidate evidence](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.1.0-internal.2/candidate/report.md) records 398 assertion executions; the [distribution evidence](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.1.0-internal.2/distribution/report.md) records 144 application assertions and six offline template builds. These records identify their exact source and artifacts.
Current measurement methodology and results are in [benchmarking](https://weaveport.dev/docs/benchmarking.md). The full historical comparison collection is described in [historical evidence](https://weaveport.dev/docs/history.md), not a competing current status summary.
## Runtime optimization and soak verification
The repository now includes allocation reductions for SDK size checks and gateway serialization, incremental frame scanning, safe admission diagnostics and a supervised k6 soak runner. These source changes do not replace or republish the frozen **0.1.0-internal.2** delivery. [Optimization evidence](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/optimization/runtime-and-soak/README.md) records measured large-result caller allocation reductions of about 40% locally and 20% through the gateway; small-operation latency varies.
The [four-hour completion report](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/optimization/runtime-and-soak/four-hour-completion.md) records 7,852,212 operations across 24 tenants, zero unexpected errors, all thresholds passing and verified process/workspace cleanup. Actual k6 duration was 14,400.81021 seconds; global p99 was 173 ms and peak summed RSS including k6 was 1,916 MiB. Regression evidence includes 311 hosting assertions in each of the project-reference and packed consumers, 382 packed multilingual SDK checks and 10 supervisor/report tests. The optimization and cleanup/admission changes are completed and archived; their monitoring loop is paused after success.
This qualifies the recorded native macOS arm64 profile. Individual latency reached 4,845 ms, and k6 memory grew separately from the gateway; longer-duration load-generator behavior remains a measurement consideration. Library startup admission remains eight slots by default; the 24-tenant soak explicitly configures 24. Security boundaries and failure acceptance were preserved. See [soak operation](https://weaveport.dev/docs/soak-testing.md) for reproduction and limits.
## Open work
The remaining platform change is [qualify-native-capacity-and-platform-comparison](https://raw.githubusercontent.com/yesbert/WeavePort/main/openspec/changes/qualify-native-capacity-and-platform-comparison/tasks.md): Windows capacity/performance qualification remains outstanding. Native source adapter checks now pass in [Windows/Linux CI](https://weaveport.dev/docs/continuous-integration.md), including 38 Windows stdio assertions and 38/39 Linux stdio/socket assertions. Those source checks do not replace current public-package installation qualification. See [platform requirements](https://weaveport.dev/docs/platform-qualification.md).
HiveWeaver, TreeWeaver and NextPA integration remains separate application work. Signing/notarization, stronger sandboxing and automatic deployment/migration are separate release decisions, not hidden tasks needed to run the current internal examples.
The [repository cleanup qualification](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/verification/current/README.md) adds a maintained-link check (399 assertion executions), moved adapter checks and a packaging regression. It does not replace the exact current release evidence above.
## MCP support
The 0.3.0 release adds [optional local MCP tools](https://weaveport.dev/docs/mcp-plugins.md) alongside the native protocol, with explicit 2025-11-25/2026-07-28 selection. Included in the 0.3.0 package line. The guide and [measurement report](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/mcp/local-stdio/README.md) identify the tested subset and platform limits.
Version 0.3.1 adds public `McpMethods.ListTools` and `McpMethods.CallTool` constants used by the consumer examples. The MCP wire protocol and supported subset remain unchanged.
---
## Integration contract
Source: https://weaveport.dev/docs/v1-integration-contract.md
# V1 integration agreement
**Status: integration contract for public packages 0.3.1, reviewed on 2026-09-14.** This guide defines how our applications should integrate WeavePort. It introduces no new runtime API or released compatibility promise. Existing [baseline specifications](https://github.com/yesbert/WeavePort/tree/main/openspec/specs) define verified behavior; the [current status](https://weaveport.dev/docs/status.md) separates remaining work from that behavior. Packages use version `0.3.1`; API evolution remains subject to the exact compatibility matrix.
## Product boundary
WeavePort is an embedded backend plugin platform. Each consuming application owns its coordinator configuration and domain services; installing it does not introduce a mandatory central service. The first release serves owner-controlled applications running owner-controlled plugins. A plugin process can fail independently, but trusted native execution shares the operating-system user and is not a hostile-code sandbox.
The three examples are permanent product assets and integration templates. HiveWeaver, TreeWeaver and NextPA remain requirements sources until separately authorized integration work begins. No common application base class, event store, database, workflow engine or sibling framework is required.
## Responsibility agreement
| Concern | WeavePort supplies today | Consuming application supplies |
|---|---|---|
| Domain contracts | JSON invocation and typed SDK calls/streams | Operation names, request/result schemas, semantic validation and compatibility policy |
| Authority | Immutable `PluginContext`, explicit callback grants, binding checks | Authenticated tenant/profile, permitted plugin selection, callback argument/object validation |
| Execution | Binding, invocation, cancellation, worker restart/disposal, bounded admission | One intentional coordinator budget per application/node deployment; deadlines and overload response |
| Artifacts | Startup version check and configured execution profiles | Approved artifact resolution, stable executable/runtime bytes, installation and activation policy |
| State | Worker-local state for the lifetime of a binding/worker | Durable state, checkpoints, commits, schema migration and recovery |
| Effects | Dispatch status and possible-execution indication | Idempotent request identity, atomic effect/outcome storage or provider reconciliation |
| Data transfer | Bounded frames, SDK calls/streams, optional composition primitives | Resource leases, per-document/operation quotas, staged completion and retention |
| Operations | Lifecycle diagnostics, observable execution results | Correlation with business operations, redaction, shutdown/drain and deployment runbook |
Callback grants authorize names, not every object referenced by their payloads. Use the bound context to look up data and validate each requested object, range or exact action. Changing principal, profile configuration, credentials or grants requires a new binding; mutable request data is not a substitute for that change. See [execution requirements](https://weaveport.dev/openspec/specs/plugin-execution/spec.md) and [worker lifecycle](https://weaveport.dev/docs/worker-lifecycle.md).
## Supported surface to carry into V1
| Surface | Intended use | Current source |
|---|---|---|
| `WeavePort.Abstractions` | `PluginContext`, `IPluginSession`, `InvocationResult`, `IHostCallbacks` | [Contracts](https://raw.githubusercontent.com/yesbert/WeavePort/main/src/WeavePort.Abstractions/Contracts.cs) |
| `WeavePort.Hosting` | Coordinator and selected execution profile | [Lifecycle](https://weaveport.dev/docs/worker-lifecycle.md), [native execution](https://weaveport.dev/docs/local-execution.md) |
| `WeavePort.Sdk.Client` | Typed local functions/streams over a session | [Client contract](https://raw.githubusercontent.com/yesbert/WeavePort/main/src/WeavePort.Sdk.Client/IPluginClient.cs), [implementation](https://raw.githubusercontent.com/yesbert/WeavePort/main/src/WeavePort.Sdk.Client/LocalPluginClient.cs) |
| C#/Python/TypeScript author SDKs | Author functions, streams and host callbacks | [SDK guide](https://weaveport.dev/docs/plugin-sdk.md) |
| Optional Composition | Bounded application-controlled large-result composition | [Composition guide](https://weaveport.dev/docs/bulk-composition.md) |
The [local compatibility policy](https://weaveport.dev/docs/package-compatibility.md) now records the exact core package set and reviewed .NET API baseline. This is an internal review boundary, not a published stability guarantee for every experimental package. Gateway/remote deployment and Docker have separate PoC evidence; the three product reference applications currently qualify native local macOS execution. C#/Python behavior is exercised by Decision Room; Document Workshop and Appointment Desk use C#. TypeScript startup/version checks are separate SDK evidence, not a TypeScript implementation of all three examples. Windows qualification remains open in the existing capacity/platform change.
## Integration sequence
1. **Define the domain boundary.** Create an application-owned contract module with bounded requests/results and explicit terminal states. Decide whether a call computes, stages data or performs an effect. Select the matching reference pattern below.
2. **Resolve an approved installation.** Choose a concrete plugin release, entry point and runtime from trusted deployment configuration. Preserve that selection for the operation's recovery lifetime. Do not rebuild files underneath a live binding. A version label alone does not authenticate file contents.
3. **Create the coordinator budget.** Reuse one `PluginHost` for the intended budget boundary. Independent hosts have independent counters; a host per incoming request does not impose aggregate node limits. Appointment Desk uses the [shared coordinator template](https://weaveport.dev/docs/embedded-coordinator.md) for operation admission and owned shutdown. Example budgets are not a service-host sizing prescription.
4. **Bind the operation authority.** Construct `PluginContext` from authenticated application state, add only the needed callback names and choose the execution profile with explicit required protections. Bind with application-owned callbacks. A binding is single-flight; multiple independent operations need explicit scheduling/bindings within the common budget.
5. **Execute and validate.** Pass cancellation and deadlines. Validate domain output before committing application state. For large results use bounded transfer steps and leases; do not infer that transport streaming makes a whole operation transactionally complete.
6. **Recover by effect semantics.** Preserve the selected release, authoritative inputs and the operation's commit boundary. Apply the pattern below. Version, schema or identity mismatch must be surfaced rather than silently switching to a different release or restarting a different action.
7. **Release owned resources.** Dispose the client/binding and application leases when the logical operation ends. Dispose the coordinator after its owned operations settle. Observe cleanup uncertainty rather than assuming a disposed client proves every external effect or descendant process stopped.
For executable integration code, start with [Decision Room](https://weaveport.dev/docs/examples/DecisionRoom.md), [Document Workshop](https://weaveport.dev/docs/examples/DocumentWorkshop.md) or [Appointment Desk](https://weaveport.dev/docs/examples/AppointmentDesk.md). These use packaged WeavePort libraries and only reference their own domain contracts directly.
## Recovery patterns proven by the examples
| Pattern | Commit boundary | Recovery rule | Demonstrated evidence |
|---|---|---|---|
| Calculation — Decision Room | Host-validated evaluation and transition appended to the journal | Replay committed events into a fresh worker; recompute only uncommitted deterministic work; retain pinned release | [Guide and verification entry point](https://weaveport.dev/docs/examples/DecisionRoom.md) |
| Import — Document Workshop | Validated complete extraction moved from staging into the document store | Discard handled incomplete attempts; restart extraction from captured/approved input as a new import attempt | [41 assertions (historical) — pre-public record](https://weaveport.dev/docs/history.md) |
| Action — Appointment Desk | Approved command persisted before dispatch; booking and outcome saved together | Reconcile/repeat the exact scoped command; return the original terminal outcome | [30 assertions and separate-process recovery (historical) — pre-public record](https://weaveport.dev/docs/history.md) |
These are distinct application semantics. Document Workshop does not resume a partially decoded document after coordinator failure. Decision Room replay does not make external actions exactly-once. Appointment Desk proves a local single-coordinator transaction; a remote provider needs its own idempotency/reconciliation mechanism.
## Failure interpretation
`InvocationResult.Status` describes runtime execution, not domain success. An `ok` response still requires semantic validation. Domain refusal, conflict and unavailable results belong in the application contract.
`InvocationResult.MayHaveExecuted` and `PluginCallException.MayHaveExecuted` express dispatch uncertainty. `false` means that attempted dispatch did not execute; it says nothing about earlier attempts under the same application request. `true` requires effect-aware reconciliation. The typed local client turns runtime cancellation into `OperationCanceledException`, which does not carry that flag. Conservatively retain action identity on cancellation rather than assuming no effect occurred. Appointment Desk demonstrates this behavior.
A `busy` result is an admission outcome, not permission for unbounded retries. The application must bound queueing, retry time and concurrency. A worker replacement can reconstruct execution capacity but cannot reconstruct application state by itself. Callback completion can outlive caller cancellation; idempotency and durable results remain application/provider responsibilities.
## Versions and installation gaps
Keep four identities distinct: host/SDK package version, plugin artifact release, domain contract/schema version and transport protocol version. The required installation compatibility declaration now checks host API/protocol and package/SDK identities separately. Domain contracts still require exact equality rather than range negotiation; content pins and the startup release check remain independent guards.
All three examples now consume the [shared installed-plugin resolver](https://weaveport.dev/docs/installed-plugins.md), with manifest/content validation and retained release identity. Decision Room and Appointment Desk re-resolve persisted pins; Document Workshop records a pin per complete import. This requires stable deployment bytes and trusted metadata; it is not an enforcing immutable filesystem or a general package manager. Current support limits and outstanding qualification are tracked in the [current status](https://weaveport.dev/docs/status.md).
## Consumer acceptance evidence
Before an application integration is accepted, its own domain tests should show: a successful packaged call; alternate implementation where relevant; denied/foreign callback authority; worker loss at the commit boundary; cancellation with honest effect status; two scopes active while one fails; and preserved release/schema identity on recovery. Add capacity and cleanup tests for the application's actual operating envelope. Passing an example does not qualify a different deployment automatically.
Historical example assertions are development evidence, not a new combined release run: Decision Room 33, Document Workshop 41, Appointment Desk 30, plus 12 multilingual SDK version checks. The [qualified internal candidate (historical) — pre-public record](https://weaveport.dev/docs/history.md) now records a combined 234-assertion run against one fixed package/artifact set.
The [native operations runbook](https://weaveport.dev/docs/native-operations.md) qualifies guarded manual recovery for Appointment Desk. Other integrations must adopt equivalent run ownership and restart gates; automatic descendant cleanup and power-loss durability are not implied.
---
## MCP plugins
Source: https://weaveport.dev/docs/mcp-plugins.md
# Optional local MCP plugins
Reuse local MCP tools from your .NET application while keeping native plugins for application-specific contracts. Hosting 0.3.1 supports MCP tools alongside the default WeavePort protocol. No extra runtime package dependency is required by Hosting.
A local MCP server is a child process offering functions over stdin/stdout. One process can offer many tools. It needs neither a network listener nor an AI model. Existing native plugins remain native. Consuming MCP servers is separate from exposing WeavePort functions through an external MCP gateway; this implementation only consumes local servers.
[Run the complete C# example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/mcp/README.md) to discover and call the same server using both supported revisions.
## Bind and call
The snippet uses the public `McpMethods` constants available in Hosting 0.3.1.
Use an absolute runtime executable and server entry-point path selected by the trusted application. Deploy dependencies beforehand: the host does not download servers or run package managers.
```csharp
using System.Text.Json;
using WeavePort.Abstractions;
using WeavePort.Hosting;
await using var host = new PluginHost();
var profile = new ProcessProfile(
"/absolute/path/to/node",
["/absolute/path/to/server.mjs"],
trustedCode: true,
timeout: TimeSpan.FromSeconds(5))
{
Protocol = ProcessProtocol.Mcp20260728
};
var context = new PluginContext("department-a", "document-tools", "1",
"local-mcp", JsonSerializer.SerializeToElement(new { }));
await using var session = await host.BindAsync(
context, profile, new NoCallbacks(), []);
InvocationResult discovery = await session.InvokeAsync(
McpMethods.ListTools, JsonSerializer.SerializeToElement(new { }));
InvocationResult result = await session.InvokeAsync(
McpMethods.CallTool, JsonSerializer.SerializeToElement(new
{
name = "normalize",
arguments = new { text = " hello world " }
}));
if (result.Status != "ok")
throw new InvalidOperationException($"Host exchange failed: {result.Status}");
if (result.Value.TryGetProperty("isError", out var error) && error.GetBoolean())
throw new InvalidOperationException("The tool reported an application error.");
Console.WriteLine(result.Value.GetProperty("structuredContent"));
sealed class NoCallbacks : IHostCallbacks
{
public ValueTask InvokeAsync(HostCall call, CancellationToken token)
=> throw new NotSupportedException("This binding has no callbacks.");
}
```
The [official-SDK fixture](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/mcp/server.mjs) implements normalize and echo as ordinary text functions. [Fixture instructions](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/mcp/README.md) include an executable interoperability check.
`InvokeAsync` is the low-level host contract. MCP bindings accept only `tools/list` and `tools/call`. The native author SDK and `LocalPluginClient` operations/streaming are a different protocol and are not transparently translated.
## Versions and results
| Selection | Startup | Scope |
| --- | --- | --- |
| `Native` (default) | Native ready frame | Existing WeavePort protocol |
| `Mcp20251125` | initialize, exact revision check, initialized notification | MCP 2025-11-25 tools subset |
| `Mcp20260728` | server/discover, supported revision check | MCP 2026-07-28 tools subset, metadata on every request |
There is no automatic fallback, sibling probe process, or Unix-socket MCP mode. Unknown enum values and MCP/socket combinations are rejected before startup. The configured plugin artifact version remains a host deployment identity. MCP revision and server-reported implementation metadata do not attest the plugin artifact's integrity or establish equality with that version.
Discovery returns one page. If present, pass `nextCursor` as `{ cursor = value }` in a subsequent tools/list call; the application bounds its own pagination. A tools/call payload contains a nonempty `name` and optional object `arguments`. Other parameters, including caller-supplied protocol `_meta`, are rejected.
The complete result object is preserved, including content, structuredContent and isError. Host status `ok` means the MCP exchange completed, not that the tool succeeded. A valid isError result keeps the worker alive. A JSON-RPC error becomes host status `failed`; malformed or unsupported traffic becomes `protocol-error`. These failures remove the worker. No call is automatically replayed. `MayHaveExecuted` remains conservative: an unsuccessful call can already have caused effects.
## Lifecycle and trust
The existing host owns every process launch and reservation. Global/tenant admission, pristine assignment, state retention, idle release, explicit restart and quarantine accounting apply to MCP as to native workers. A used process is never reassigned to another tenant. Multiple bindings can create multiple instances of the same server.
The host sends neither bound tenant/configuration data nor native callback grants implicitly. MCP bindings reject nonempty native callback grants before registration. The application authorizes which server and tools it calls; discovery names, descriptions, annotations and output are untrusted data, not authority. Content is not executed, and resource links are not fetched automatically.
Local execution still requires trusted code. The cleared environment, private cooperative workspace and separate process do not enforce filesystem/network confinement, hard memory ceilings or containment of escaped descendants. See [local execution](https://weaveport.dev/docs/local-execution.md) and [worker lifecycle](https://weaveport.dev/docs/worker-lifecycle.md). Requiring unavailable OS protection still rejects binding.
Messages reuse the host's 1 MiB frame limit and depth-32 reader; MCP serialization also limits depth to 32. Oversized output is rejected before sending any part of the message. Response IDs and duplicate envelope fields are checked. At most 32 recognized notifications or legacy keepalive requests are handled per exchange; legacy ping requests receive empty acknowledgements, and other server requests are rejected; the total deadline does not reset. stderr is drained without retaining plugin-controlled text.
Cancellation after a complete request write attempts a cancellation notification for at most 100 ms, then existing cleanup terminates the worker. An interrupted partial write does not append a notification. Legacy initialization is not cancelled with a protocol notification. MCP shutdown first closes stdin and allows up to 100 ms for exit, then uses existing forced termination and cleanup accounting. Cancellation does not roll back external actions.
## Supported boundary and evidence
Resources, prompts, sampling, roots, elicitation, tasks, subscriptions, remote HTTP and multi-round-trip host interactions are not implemented. Unsolicited server requests cannot invoke callbacks. Servers requiring these features need a separate integration change. The tools subset has been exercised against the official TypeScript SDK 2.0.0 and protocol/failure fixtures on macOS; other SDKs and operating systems are not qualified by that result.
[Host regressions](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/README.md) cover malformed JSON/UTF-8, size/depth limits, duplicate IDs, wrong correlation, notification flooding, authority, admission, failure recovery and state retention. These are bounded protocol/lifecycle checks, not a penetration-test certification or an OS sandbox qualification. [Benchmark guidance](https://weaveport.dev/docs/benchmarking.md) distinguishes native regression timing from MCP SDK comparisons.
---
## Author SDKs
Source: https://weaveport.dev/docs/plugin-sdk.md
# Authoring plugins with WeavePort
Write a plugin as ordinary asynchronous functions and result streams in C#, Python or TypeScript. Your application defines the contract; the SDK takes care of communicating with the host. WeavePort supplies dispatch, JSON conversion, local transport selection, callback framing, stream batching and lifecycle. The same provider artifact runs directly under a product's PluginHost or under the separate worker-host gateway. The gateway is one shared ASP.NET Core process, not a server inside every plugin.
## C#
Reference the public `WeavePort.Sdk` NuGet package at version 0.3.1, or the matching locally packed package when working from source. Register ordinary async handlers; the delegate return uses ValueTask, so an async lambda needs no wrapper. Asynchronous iterators use normal `IAsyncEnumerable` and cancellation tokens.
```csharp
var plugin = new PluginApplication();
plugin.Function("search", async (request, context, token) =>
{
// Application logic, including approved context.CallHostAsync capabilities.
return await SearchAsync(request, token);
});
plugin.Stream("results", GetResultsAsync);
await plugin.RunAsync();
```
The executable [C# example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/sdk/csharp/Program.cs) includes echo, authorized callbacks, a lazy record generator and explicit test diagnostics. Optional serializer options allow supplying generated JSON metadata; NativeAOT is not qualified. The default uses web JSON property conventions. There is no dependency on ASP.NET Core or gRPC in the author SDK.
## Python
Install the local `weaveport-sdk` wheel; runtime dependencies are Python's standard library.
```python
app = PluginApplication()
@app.function("search")
async def search(request, context):
return await search_backend(request)
@app.stream("results")
async def results(request, context):
async for item in search_pages(request):
yield item
app.run()
```
See the [runnable Python example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/sdk/python/plugin.py). Use ordinary async cancellation/finalization patterns. The SDK owns its protocol reader and callback sequencing.
## TypeScript
Install the packed `@weaveport/sdk` npm archive. The SDK includes JavaScript and type declarations, with no third-party runtime dependency.
```typescript
const plugin = new PluginApplication();
plugin.function('search', async (request, context, signal) =>
searchBackend(request, signal));
plugin.stream('results', async function* (request: SearchRequest, context, signal) {
for await (const item of searchPages(request, signal)) yield item;
});
await plugin.run();
```
See the [runnable TypeScript example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/sdk/typescript/plugin.ts). Context properties are readonly; `callHost` provides typed callback results. The ordinary AbortSignal is used for SDK lifecycle cancellation.
## Artifact version
Declare the plugin's artifact version independently of protocol version. Existing callers default to `"1"`:
```csharp
var plugin = new PluginApplication { PluginVersion = "2" };
```
```python
app = PluginApplication(plugin_version="2")
```
```typescript
const plugin = new PluginApplication('2');
```
The declaration is sent in the startup handshake. The host's expected `PluginContext.Version` must match; a mismatch is rejected before calling a function. Empty/whitespace declarations are refused. The wire protocol remains version 1. Authors set this from their build/release metadata, not from caller arguments or host request data. This identifies an artifact; it is not package signing or a compatibility negotiation scheme.
Run `./scripts/sdk-versions.sh` for packed C#/Python/TypeScript startup and call checks. The [Decision Room version walkthrough](https://weaveport.dev/docs/examples/DecisionRoom.md#parallel-plugin-versions) demonstrates application-owned version selection and journals.
## Product integration
Use `WeavePort.Sdk.Client` over an already authorized `IPluginSession`:
```csharp
IPluginClient plugin = new LocalPluginClient(session);
SearchResult result = await plugin.CallAsync("search", request, token);
await foreach (SearchHit hit in plugin.StreamAsync("results", request, token))
await DisplayAsync(hit, token);
```
For a worker host, the trusted application registers that same local client in `GatewayRegistry`, adds gRPC services and maps `GatewayService`. Registration returns a random credential that authorizes only that preconfigured binding. The caller constructs `RemotePluginClient(endpoint, credential)` and uses the same IPluginClient methods. The binding client owns a reusable channel and up to eight binding-scoped duplex sessions to avoid a demonstrated Kestrel stream-reuse defect without per-call TCP churn; see [the cause and compatibility correction (historical) — pre-public record](https://weaveport.dev/docs/history.md). No provider edit or gRPC import is necessary. RPC requests cannot register executable paths, select tenant identity or assign grants.
The optional `WeavePort.Sdk.Gateway` NuGet contains both gateway hosting and its .NET client and requires the ASP.NET Core shared framework. Splitting client-only deployment dependencies is a possible later packaging refinement. The [worker-host sample](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/WeavePort.WorkerHost/Program.cs) binds loopback and configures 1-MiB gRPC limits. Its stdin bootstrap and snapshot commands belong to the test launcher, not to plugin authors or the public remote protocol. Deployment registration, credential distribution/rotation and remote TLS termination belong to the trusted application. HTTPS is required by the client for non-loopback endpoints; real remote deployment is not qualified by the current release.
Callbacks execute **where PluginHost is hosted**. Supply the application's `IHostCallbacks` implementation there. The sample uses identical application callback code in both locations. This first gateway does not serialize or forward arbitrary closures from the calling product process. For a remote node, that callback implementation needs access to the appropriate application services. The plugin API remains `context.CallHostAsync`, `context.call_host` or `context.callHost`.
## Ownership, limits and cancellation
- A function returns one bounded value; a stream yields individual records. The SDK batches records internally (up to 16 records/256 KiB). One lookahead item is permitted; no whole-list accumulation is required in the SDK. An individual serialized item is limited to 128 KiB and a complete stream to 64 MiB. Unary client input/output is limited to 512 KiB; the underlying frame/message ceiling is 1 MiB. JSON encoding can expand values, so limits concern representation rather than string character counts. Oversized items fail explicitly; arbitrary giant records or binary-file streams are not automatically split by this first API.
- One client binding is single-flight for the entire enumeration. A second concurrent call fails busy. Multiple independent bindings provide parallelism; products orchestrate serial or fan-out/fan-in work. Used workers never move between tenants.
- A local SDK client owns its supplied IPluginSession. Disposing it cancels and disposes that binding. A remote client cancels its outstanding calls on disposal, and disposes its retained sessions/channel; the trusted gateway application owns binding registration and revocation. Revoke credentials/dispose the registry to terminate server-side bindings.
- Early local iterator disposal attempts graceful generator closure. Active cancellation or cleanup uncertainty stops/restarts the owned worker through the existing host; native protocol v1 does not deliver a separate soft-cancel frame. Python/TypeScript/C# cleanup code is therefore not guaranteed to run after forced process termination. Remote early disposal cancels the stream and waits for a binding-scoped cleanup acknowledgement; it cannot cancel a different stream ID.
- Streams have a default 30-second overall local client deadline and existing per-invocation host deadlines. Remote calls and streams also have a configurable 30-second client timeout covering connection/response waits, including an unresponsive gateway; uncertain stream cleanup adds at most five seconds. The gateway uses the same local client and policies. Keep host idle eviction disabled (the default) or longer than the stream lifetime: the current pull protocol does not pin a worker between batches. Cancellation/producer errors after some records mean partial output, not transactional success; products decide what to do with already consumed records. Do not retry external effects without application idempotency semantics.
- Callback IDs and grants remain host-owned. Invocation scopes reject late detached callbacks, and SDKs serialize callback exchanges. The host's callback budget applies per internal invocation/batch; a generator doing many callbacks must respect the configured host policy. SDK context identity is information, not permission to access arbitrary customers.
- Normal console logging is redirected to stderr after the SDK runtime starts. Do not write raw protocol streams or emit stdout before runtime initialization. Logging, custom schemas, discovery/manifests and stronger sandbox adapters need further productization; ordinary provider functions never select sockets, gRPC or batch sizes.
The [compatibility policy](https://weaveport.dev/docs/package-compatibility.md) defines the exact core package surface; optional Gateway deployment remains separate. Native SDK workers remain explicitly trusted same-user processes. Windows/Linux and remote production deployment still require qualification. Build and verification instructions are in [the SDK harness guide](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/README.md); earlier measurements remain in [the SDK result report (historical) — pre-public record](https://weaveport.dev/docs/history.md).
The gateway packages must be updated together: the unreleased wire protocol now uses duplex exchanges. Session lease waits count against the operation timeout. An incomplete exchange is discarded, not returned to the session pool; every exchange rechecks the binding credential. Idle transport sessions remain until client disposal.
See [current performance evidence](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/benchmarks/current/README.md) for the current delivered core and optional loopback Gateway measurements.
---
## Coordinator
Source: https://weaveport.dev/docs/embedded-coordinator.md
# Embedded coordinator template
Use one coordinator to share worker and operation budgets across your application. Appointment Desk demonstrates this with one `EmbeddedCoordinator` at its composition root. All its admitted booking operations share that coordinator's `PluginHost`, worker limits and tenant admission. The copyable [consumer source](https://raw.githubusercontent.com/yesbert/WeavePort/main/samples/Shared/EmbeddedCoordinator.cs) is linked into the host project; it adds no public NuGet API or service dependency. [Desk](https://raw.githubusercontent.com/yesbert/WeavePort/main/samples/AppointmentDesk/Host/Desk.cs) demonstrates passing the shared host into operation code and disposing only the operation's client/session.
## Compose an application
```csharp
var coordinator = new EmbeddedCoordinator(
maximumOperations: 8,
options: new WorkerPoolOptions(
MaximumWorkers: 8,
MemoryBudgetMiB: 2048,
MaximumPristineWorkers: 0,
MaximumConcurrentStarts: 4,
MaximumWorkersPerTenant: 2,
MemoryBudgetPerTenantMiB: 512));
// Use this same instance for every incoming operation in the intended budget.
var result = await coordinator.RunAsync(async (host, token) =>
{
await using var session = await host.BindAsync(
context, executionProfile, callbacks, grants, token);
return await session.InvokeAsync(operationName, payload, token);
}, requestCancellation);
// First close ingress, then stop the coordinator before disposing callback services.
var stopped = await coordinator.StopAsync(
grace: TimeSpan.FromSeconds(5),
observation: TimeSpan.FromSeconds(5));
if (!stopped.Clean)
{
// Report Snapshot; keep callback dependencies alive while work remains.
// Completion observes coordinator tasks, not necessarily detached callbacks.
// Apply the application's explicit escalation policy; never silently replay effects.
}
```
Copy/link the source into the consuming application and adapt the composition settings. The variables in the invocation example are supplied by that application's authenticated request and approved installation resolution. Limits above illustrate configuration, not node sizing. Multiple coordinators still have independent budgets. A native memory reservation is an admission estimate, not an OS memory ceiling. Keep worker/runtime files stable for the operation and any recovery lifetime.
The delegate must await all its work, dispose its sessions before returning, and never dispose or retain the injected host. Fire-and-forget work escapes application operation accounting. Callback services and stores outlive every callback using them. The optional internal disposal delegate exists only for deterministic failure verification; normal composition uses the owned host's disposal.
## Admission and outcomes
Operation admission is immediate: there is no internal queue and no implicit retry. At the operation limit, `CoordinatorRejectedException.Status` is `busy`; after shutdown starts it is `stopping`. Neither refusal runs the delegate, creates a binding or changes domain state. Pre-cancelled requests do not run. Concurrent admission reserves a slot atomically. Accepted work retains its slot through its entire delegate, including awaited session disposal, even if cancellation was requested.
The underlying shared host can independently refuse worker/start/memory/tenant admission with runtime `busy`. In Appointment Desk this can happen before proposing a slot and creates no intent. A failure during execution of an already persisted command stays `uncertain` under the application's existing reconciliation rules. Do not translate all overload, cancellation or cleanup exceptions into a definite failed effect.
`Snapshot` includes active operation count, returned/failed delegate counters, acceptance state, shutdown/cancellation state, cleanup error types and the existing `WorkerPoolSnapshot`. `Completed` counts delegates that returned, including a domain `uncertain` result; it does not count successful business effects. `Failed` counts exceptions from accepted delegates; refused admission is excluded. Correlate outcomes with the application's request identity without logging plugin payloads or secrets.
## Shutdown and ownership
The first `StopAsync` call closes admission atomically and fixes the grace interval. Accepted operations may finish normally during grace. At grace expiry the coordinator requests cancellation and begins host disposal, tracking cancellation callbacks and cleanup separately. No cancellation callback is allowed to delay the start of host disposal. Each call waits at most its supplied grace plus observation intervals under the supplied `TimeProvider`, subject to runtime scheduling; this bounds observation rather than promising OS termination at that instant. Use zero grace on subsequent observation calls if no additional grace-sized wait is desired. The original lifecycle is never restarted.
A wait timeout returns the current snapshot and preserves the live `Completion` task and active count. `Completion` means coordinator shutdown tasks finished; inspect a fresh `Snapshot.Clean` as well. An invocation callback that ignores cancellation may outlive its worker/session and keep `Runtime.Tenants` nonzero even after `Completion`. `Clean` additionally requires zero active operations, workers, bindings and tenant records, with no recorded cleanup or maintenance failure. Cleanup errors remain diagnostic even if resource counters later reach zero. Simulated cleanup failure is tested; this slice does not newly qualify OS-level deletion failures.
`DisposeAsync` uses five seconds grace plus five seconds observation and throws if shutdown is not clean. For a service host, use explicit `StopAsync` and inspect the result before releasing dependent services. Simply catching a disposal exception and disposing callback dependencies can race outstanding work. Uncooperative code needs an application/deployment escalation decision; the template cannot safely force arbitrary managed callbacks to stop. It never reports cancellation as proof that an external action did not occur.
The [native operations runbook](https://weaveport.dev/docs/native-operations.md) now adds a persistent run guard to normal Appointment Desk execution and requires supervised recovery after a crash. Escaped descendants, automatic orphan cleanup, power-loss durability and distributed admission remain unqualified.
## Verify
```sh
./scripts/appointment-desk.sh --build --verify
./scripts/verify-compatibility.sh
```
The second command assumes the other reference applications and SDK artifacts have already been built as documented in [package compatibility](https://weaveport.dev/docs/package-compatibility.md). The Appointment Desk suite uses packed NuGet dependencies and actual installed native workers for shared quotas, independent customers, worker loss, graceful drain and forced shutdown after booking. Additional consumer checks exercise concurrent admission, uncooperative delegates and simulated cleanup failure. See [retained evidence (historical) — pre-public record](https://weaveport.dev/docs/history.md).
---
## Installed plugins
Source: https://weaveport.dev/docs/installed-plugins.md
# Installed plugin resolution
Choose a known plugin artifact and keep its identity stable throughout an operation. `WeavePort.Hosting` provides `InstalledPluginCatalog`, `InstalledPlugin` and `InstallationIdentity` for that selection. All three reference applications consume this API through packed NuGet artifacts. This is local integrity validation for owner-controlled deployments; it is not a downloader, signature verifier or hostile-code sandbox.
## Host integration
Construct a catalog with a trusted releases directory and a mapping of runtime aliases to approved local files. Resolve a concrete plugin ID, release and application contract ID. `Resolve` validates the manifest and returns verified entry points plus a persistable identity. On recovery, supply that same identity as `pinned`. A mismatch is refused; the resolver never chooses a fallback release.
`ReadSelection` reads a default only for a new logical operation. `Activate` validates a selected installation before atomically replacing the default selector. Existing pins do not reference that selector. The application owns when a logical operation begins and where its pin is committed.
These APIs do not launch a worker. Use the returned entry point with the approved runtime in a `ProcessProfile`, and use the resolved artifact release in `PluginContext.Version`. The existing startup guard independently rejects a worker that advertises another version. See [the API source](https://raw.githubusercontent.com/yesbert/WeavePort/main/src/WeavePort.Hosting/InstalledPluginCatalog.cs) and [packed consumer checks](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/installations/Program.cs).
## Manifest and identities
Each release directory contains `installation.json` with case-sensitive fields:
| Field | Meaning |
|---|---|
| `Schema` | Manifest format, currently 1 |
| `Plugin`, `Version` | Expected plugin installation ID and exact artifact release |
| `Contract` | Application contract identifier, independent of artifact release |
| `EntryPoints` | Trusted aliases mapped to declared relative bundle files |
| `Files` | Complete bundle file inventory with uppercase SHA-256 hashes, excluding the manifest itself |
| `RuntimeFiles` | Expected runtime aliases and file hashes; host supplies the corresponding local paths |
| `Compatibility` | Required exact host API/protocol/core packages and entry-specific SDK declarations; see [compatibility policy](https://weaveport.dev/docs/package-compatibility.md) |
An `InstallationIdentity` contains plugin, version, contract and SHA-256 of the exact manifest bytes. Even a manifest-only change invalidates an old pin. A directory may be relocated with unchanged content and approved equivalent runtime files; absolute paths are not the identity. Missing/extra bundle files, links, path traversal, duplicate JSON fields, unknown schema, mismatched contract/release and changed hashes are refused. The manifest is limited to 1 MiB, 4096 files and 32 entry points; traversal is bounded to 8192 directory entries.
The [offline sealing tool](https://raw.githubusercontent.com/yesbert/WeavePort/main/scripts/seal-installation.py) generates manifests after building. It removes generated Python bundle bytecode caches; Decision Room launches Python with `-B` so its release directory remains unchanged. Build scripts require Python 3.11+ for sealing. C#/Python SDK files included in the bundle are hashed; Decision Room also declares its external Python SDK source modules. Runtime executable hashes are recorded through host-supplied aliases.
## Stable deployment precondition
The manifest is trusted installation metadata. Someone able to replace both metadata and files can describe a different installation for a new operation. Persisted pins still detect changed metadata, but this does not authenticate a publisher. Keep release directories, selectors and durable application state under the appropriate deployment/application authority.
Files must remain unchanged from verification through execution and any automatic worker replacement. Hashing before a call does not prevent a time-of-check/time-of-use race. No read-only mount, kernel enforcement or code snapshot is introduced. OS/.NET shared framework/Python standard library and environment dependencies outside the declared file set remain deployment-owned and must also stay fixed. Runtime executable hashing does not attest their full dependency closure.
Build/sealing are offline development actions and may replace release files. Activation of already-built installations is the supported live action. Do not rebuild, reseal or modify a release/runtime while a reference application is active. Changing shared libraries can invalidate earlier application state; retain the original build if that state must be recovered.
## Reference application behavior
| Application | Pin owner | Activation/recovery behavior |
|---|---|---|
| Decision Room | Journal configuration and artifact dictionary containing the shared manifest digest | Existing release selection remains; resume and worker replacement retain the selected release. Old development journals lacking the new identity are refused unchanged. |
| Document Workshop | One import attempt and its completed NDJSON header (`installation`) | `--version` selects an explicit release; `--activate` changes future imports. A live import retains its release, including fallback readers. Incomplete imports still have no coordinator-resume contract. |
| Appointment Desk | Installation identity in each persisted intent, calendar schema 2 | Existing requests resolve their stored installation regardless of the active default. Conflicting explicit versions fail. Schema-1 calendars are refused unchanged because their original code identity cannot be reconstructed safely. |
Document Workshop and Appointment Desk now build real release-1 and release-2 workers. Both currently implement the same v1 domain contract; the worker startup declarations differ. A new artifact release does not imply a different domain schema.
```sh
./scripts/document-workshop.sh --activate 2
./scripts/document-workshop.sh --version 1
./scripts/appointment-desk.sh --activate 2
./scripts/appointment-desk.sh --request new-v2 --store artifacts/appointment-desk/calendar-v2
```
For existing Appointment Desk development data, keep the old store and start a fresh path as shown; do not reset it in place. Decision Room similarly requires a new journal for this build unless its recorded installation identity matches. Existing Document Workshop output remains readable.
## Verification
Build the three examples with their respective `--build --verify` commands, then run `./scripts/verify-installations.sh`. The latter uses fresh package extraction, validates metadata/content guards and a real startup mismatch, and launches separate sample coordinator processes to check pinned-state preservation on refusal. All destructive fault cases operate on isolated artifact copies. See the [retained report (historical) — pre-public record](https://weaveport.dev/docs/history.md) for measured scope and results.
---
## Compatibility
Source: https://weaveport.dev/docs/package-compatibility.md
# Local package and contract compatibility
Keep the host, SDKs and plugin artifacts on a known-compatible combination. This guide defines the exact identities checked during installation and startup.
**Public package policy for 0.3.1, reviewed 2026-09-14.** The [machine-readable matrix](https://raw.githubusercontent.com/yesbert/WeavePort/main/compatibility/local-v1.json) defines one exact combination. It is embedded in `WeavePort.Hosting` and consumed by the offline installation sealer. The public NuGet package set uses this exact matrix; no general SemVer range is accepted.
## Separate compatibility identities
| Identity | Current value | Checked by |
|---|---|---|
| Local host API level | `1` | Installation compatibility declaration against the embedded matrix |
| Transport protocol | `1` | Compatibility declaration and existing worker startup protocol checks |
| Core host packages | Abstractions, Hosting, Sdk.Client, each `0.3.1` | Exact declaration plus actual packed/loaded metadata checks |
| C# author SDK (`dotnet`) | `WeavePort.Sdk` `0.3.1` | Entry-specific declaration, packed metadata and native startup/call checks |
| Python author SDK (`python`) | `weaveport-sdk` `0.1.0` | Entry-specific declaration, wheel/installed metadata and native startup/call checks |
| TypeScript author SDK (`node`) | `@weaveport/sdk` `0.1.0` | Entry-specific declaration, npm/installed metadata and native startup/call checks |
| Plugin artifact release | Exact chosen installation, e.g. `1` or `2` | Manifest identity/content pin and worker's advertised release |
| Application domain contract | Exact host-requested ID | Resolver equality, followed by application-owned payload validation |
The example contract IDs are `decision-room/v1`, `document-workshop/v1` and `appointment-desk/v1`. Release 2 of a plugin can implement the same v1 domain contract with the same SDK. None of these versions should be inferred from another. The resolver does not implement domain-schema migration or compatibility ranges.
## Mandatory installation declaration
Every `installation.json` now contains `Compatibility` with `HostApi`, `Protocol`, `HostPackages` and `AuthorSdks`. `HostPackages` must exactly equal the three core host package IDs/versions above. Each entry alias requires its corresponding SDK package/version under `AuthorSdks`; absent, extra, null or unknown SDK entries are rejected. No implicit default is substituted for a missing declaration.
The sealer generates this block from the reviewed matrix; plugins do not choose runtime authority through it. Resolution and activation validate it before returning an installation. Domain-contract mismatch is a separate refusal. A refused activation keeps its prior selector; failed recovery leaves application state unchanged.
The metadata is a trusted deployment declaration, not runtime package attestation. The gate inspects real packed package metadata and loaded assembly versions; the installation resolver validates declarations and file hashes. It does not interrogate every transitive runtime dependency inside a running worker. Same development version labels across different development builds do not prove identical bytes or behavior. Keep one coherent tested deployment and its pinned content; stable-file requirements in [installed-plugin resolution](https://weaveport.dev/docs/installed-plugins.md) still apply.
Old manifests without `Compatibility` fail closed. Rebuild/reseal only offline. This changes manifest identity, so existing pins require the original deployment or new application state; recovery never upgrades a pin automatically. Manifest schema is 1 for the first public release. Future format evolution requires an explicit migration/format decision.
## Reviewed package/API surface
The [API baseline](https://weaveport.dev/compatibility/public-api.txt) records exported types and public/protected signatures across the four core .NET packages. It includes parameter names and optional defaults, inheritance/interfaces and enum values. The [packed consumer](https://raw.githubusercontent.com/yesbert/WeavePort/main/tests/compatibility/Program.cs) detects drift without rewriting the baseline. All four packages target `net10.0` in this candidate.
| Package | Consumer surface |
|---|---|
| Abstractions | `PluginContext`, `InvocationResult`, `HostCall`, `IPluginSession`, `IHostCallbacks` |
| Hosting | `PluginHost`, execution profiles/protection, worker budget/snapshot, installed catalog/result/identity and transport profile types |
| Sdk.Client | `IPluginClient`, typed extensions, `LocalPluginClient`, `PluginCallException` |
| Sdk | `PluginApplication`, `PluginCallContext` |
The snapshot includes Docker/socket profile signatures because they are exported by Hosting; that does not qualify their deployment here. The tested product baseline remains native local macOS, .NET 10, with actual C#/Python/TypeScript SDK calls. Gateway, Composition and Testing packages remain separate optional/experimental surfaces outside this exact core package/API gate. Their existing evidence is retained, not silently promoted to this local support matrix.
A signature snapshot does not prove behavioral, binary or nullable-annotation compatibility. The current snapshot does not encode every custom modifier/attribute; code review and package-consuming runtime scenarios remain necessary. For Python/TypeScript, this milestone records package identity and tests the author/startup contract, not a complete language-level exported-symbol snapshot.
## Change and release rules
1. Classify a change by source, binary, behavior, wire and domain impact. Review signatures, parameter names/defaults, serialization, failure interpretation and recovery data independently.
2. For a supported surface change, inspect the generated `artifacts/compatibility/api-actual.txt`, update the baseline explicitly in the scoped change and add meaningful consumer evidence. The verifier never accepts the new surface automatically.
3. Changing package/API/protocol support requires a reviewed matrix and supported/unsupported combination tests. Do not add a range because version numbers look compatible.
4. Changing domain semantics/schema requires a new application contract identity or explicit compatibility/migration evidence. Changing artifact behavior alone may preserve the contract; active operations still retain their exact artifact identity.
5. Keep package publication, final version allocation and a clean-environment release candidate as separate release actions. The existing development version is not a stable compatibility promise.
The distinction between source, behavior and binary changes follows [Microsoft's library guidance](https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/breaking-changes).
## Verify
From the repository root:
```sh
./scripts/decision-room.sh --build --verify
./scripts/document-workshop.sh --build --verify
./scripts/appointment-desk.sh --build --verify
./scripts/sdk-versions.sh
./scripts/verify-compatibility.sh
```
The final script checks actual NuGet identity/dependency closure/target libraries, installed and packed author SDK metadata, loaded versions, embedded policy, the API baseline and installation compatibility/refusal cases. Negative checks use copies to prove that real package dependency drift and an API mismatch fail. Separate sample processes verify state preservation. Historical internal-candidate evidence is in the [retained report](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.1.0-internal.2/candidate/report.md).
---
## Lifecycle
Source: https://weaveport.dev/docs/worker-lifecycle.md
# Shared worker lifecycle
Control how workers start, stay available and get cleaned up through one `PluginHost`. The hosting package provides one shared, bounded pristine reserve per host. Use one coordinator for each intended node budget. Several hosts have independent budgets; this is not a distributed allocator or an automatic machine-wide singleton.
```csharp
await using var host = new PluginHost(
maximumCallsPerTenant: 4,
options: new WorkerPoolOptions(
MaximumWorkers: 32,
MemoryBudgetMiB: 8192,
MaximumPristineWorkers: 4,
MaximumConcurrentStarts: 4,
MaximumWorkersPerTenant: 4,
MemoryBudgetPerTenantMiB: 1024));
var profile = new DockerProfile(
"weaveport-poc-python:1",
IdleTimeout: TimeSpan.FromMinutes(2));
await host.PrewarmAsync(profile, version: "1", count: 2);
await using IPluginSession session = await host.BindAsync(
context, profile, callbacks, grants);
InvocationResult result = await session.InvokeAsync("echo", payload);
```
The consumer supplies `PluginContext`, `IHostCallbacks`, granted operations and a `JsonElement` payload. Use `WeavePort.Abstractions` and `WeavePort.Hosting`. Omit `IdleTimeout` for stateful process-affine usage; enabling it means the application can tolerate loss of worker-local state and reconstruct required state on the next invocation.
## Capacity and pool behavior
Defaults are 64 workers, 16,384 MiB of summed configured worker ceilings, eight concurrent starts, at most four pristine workers, eight assigned workers and 2,048 MiB per tenant. Maintenance runs every second; unused pristine workers expire after 30 seconds. No warm target is configured automatically, so the default does not speculatively launch workers. Limits are coordinator policy values, not machine sizing recommendations.
`PrewarmAsync` sets a persistent target by resolved image digest, plugin version, Docker context and sandbox resource profile. Targets share the global pristine ceiling; they are not multiplied by customer count. Zero removes a target. Initial fill and later replenishment obey the same budgets as real work. Read `Snapshot.Pristine` to see achieved readiness when resource pressure prevents a full target. Failed configuration attempts restore the prior target. Under capacity pressure, actual demand can reclaim unused pristine workers for another image; used or quarantined workers are never reclaimed for assignment.
Ready workers have received no customer context, credentials or callback authority. Each checkout is exclusive and sets its tenant owner once. Its immutable session supplies the same context and grants throughout that binding. Warm, used instances stay with their binding; they never return to a customer-shared reserve. A configuration, principal, grant or secret change requires disposal and a new binding. A changed image tag does not silently change an existing binding's resolved digest.
Optional host logging identifies admission refusals with event 1006 and fixed reasons: `concurrent-starts`, `pool-reservations`, `tenant-reservations`, `session-call` or `tenant-calls`. No payload or caller-supplied reason is logged.
Admission counts starting, assigned, pristine and cleanup-uncertain workers globally, and assigned/starting/cleanup-uncertain workers against their tenant. Reserved memory sums configured container ceilings; it is not measured Docker residency or RSS. Exceeding worker, memory, tenant or concurrent-start admission returns `busy` without dispatch. Hosts still need sizing headroom and application-level overload handling; caps do not eliminate shared CPU/engine interference or ensure fairness across an unlimited number of tenants.
## Release, callbacks and diagnostics
`IPluginSession.Instance` is the last assigned identifier, not a liveness probe; it can name an already removed environment until the next invocation.
Idle maintenance only stops opted-in sessions after their call gate is free. Their binding stays valid; a later call acquires a fresh environment. Default bindings preserve local state until explicit restart/disposal. An injected `TimeProvider` controls idle age and maintenance scheduling. `MaintainAsync` can trigger a sweep explicitly.
Disposal removes the host's session registration. Shared tenant admission records remain while any binding or detached callback references them. Nested calls from a completed or cancelled invocation scope are denied, and callback arguments retain their original immutable authority. Callbacks that ignore cancellation may still finish external actions: the consumer must handle uncertain outcomes and idempotency.
Worker removal attempts `docker rm --force` and confirms absence if Docker reports failure. Unconfirmed removal leaves the reservation quarantined, even after the client process is stopped. Maintenance retries cleanup; `Snapshot.Quarantined` exposes the retained count, including destruction in progress. `Snapshot.OldestQuarantineSeconds` reports the oldest pending removal age from first quarantine entry, retaining age across retries and reporting zero when none remain. `MaintenanceFailure` retains the last background failure type. Explicit maintenance/disposal surfaces failures. No quarantined worker is eligible for checkout. Container deletion removes its private writable layer/tmpfs; immutable images may remain cached.
## Verification and limits
`./scripts/verify.sh` includes packed API scenarios for simultaneous customers, private markers, secret/callback identity, quotas, automatic replenishment, idle/default state, active-call protection, expiry, version failures, registration churn, late callbacks and simulated cleanup failure. Focused transport checks exercise split/multiple frames, UTF-8, byte/depth limits, ownership, cancellation and atomic output rejection.
`./scripts/lifecycle.sh` records a separate 128-customer resource experiment. `PristineStartBenchmarks` measures first-call latency with/without a ready reserve; reserve construction is outside that timed call and has a real CPU/memory cost. See [benchmark boundaries](https://weaveport.dev/docs/benchmarking.md), [capacity testing (historical) — pre-public record](https://weaveport.dev/docs/history.md) and the [original design exploration](https://weaveport.dev/docs/architecture.md).
The current runtime does not implement predictive pool sizing, distributed placement/fencing, checkpoint storage or safe cross-tenant reuse of a used process. The default stdio transport retains one Docker CLI process per running worker; the opt-in [Linux socket transport (historical) — pre-public record](https://weaveport.dev/docs/history.md) uses short-lived CLI commands for lifecycle operations. Container isolation does not establish protection against kernel/engine failure or zero latency interference from another customer.
The [trusted local adapter](https://weaveport.dev/docs/local-execution.md) shares these lifecycle rules. Its memory reservations are admission estimates, not OS-enforced ceilings; root-process cleanup does not attest termination of escaped descendants. Docker-specific enforcement statements above apply only to Docker profiles.
### Adapter executable and endpoint ownership
`DockerProfile.DockerExecutable` selects an absolute path to a trusted Docker CLI. When omitted, the adapter checks conventional system installation locations (`/usr/bin/docker`, `/usr/local/bin/docker`, the macOS Docker application bundle, or the Windows Program Files Docker installation). It never searches `PATH`; custom installations must set this property. Image resolution retains the selected executable for worker startup and cleanup.
Native Unix socket endpoints use an exclusively allocated temporary directory with owner-only permissions. Configure the deployment temporary directory to keep the complete socket path within the operating system's Unix socket path limit. Disposal also removes a directory allocated for an endpoint that never started listening.
Host, session, worker-pool and local-client shutdown release their owned cancellation sources after cancellation and dependent cleanup, including failure paths. A pool drains admitted startups before final worker removal. A local client can finish shutdown while a consumer is paused between stream items; resuming that iterator observes cancellation without dispatching another operation. Repeated disposal observes the same completion or failure.
### Protection and cancellation arguments
Use `ExecutionProtections` to combine required restrictions. `BindAsync` and `PrewarmAsync` take optional `requiredProtection` before their final optional `cancellationToken`. Prefer named arguments when supplying either option, for example `requiredProtection: ExecutionProtections.DisabledNetwork, cancellationToken: token`. Consumers of the earlier development API must rename `ExecutionProtection` references and update positional cancellation arguments; no legacy overloads are retained.
### Optional MCP workers
The source MCP integration shares these local lifecycle policies, with explicit protocol selection and no additional SDK-owned process launcher. [MCP plugins](https://weaveport.dev/docs/mcp-plugins.md) documents cancellation, result semantics and the tools-only boundary. Available in the 0.3.1 package line.
---
## Operations
Source: https://weaveport.dev/docs/native-operations.md
# Native deployment and recovery runbook
Use this runbook to start, stop and recover the native Appointment Desk deployment while preserving evidence about interrupted work. Its qualified scope is a **guarded, manually supervised local macOS reference deployment**. Automatic recovery of arbitrary native descendants and power-loss durability are not qualified. The [run guard](https://raw.githubusercontent.com/yesbert/WeavePort/main/samples/Shared/NativeRunGuard.cs) is application-owned source; the core runtime has no persistent orphan registry. Other applications must adopt an equivalent deployment gate before inheriting this procedure.
## Deployment acceptance
| Boundary | Required decision / verified behavior |
|---|---|
| Code and runtime | Owner-controlled cooperative plugins, approved installation manifests and stable runtime/worker bytes; no daemonized descendants in the qualified fixture |
| Coordinator ownership | One intentional coordinator per budget; one guarded store/runtime root per deployment instance. Different roots still create independent budgets |
| Filesystem | Trusted private local directory, enough free space for state and workspaces; no concurrent operator mutation, network-filesystem or power-loss guarantee |
| Supervision | Before enabling automatic restart, independently qualify ownership and termination of the complete process boundary. This slice installs no service supervisor and leaves automatic restart gated |
| Existing installations | Stop and inspect old unguarded processes/workspaces before first adoption. A missing new marker does not prove an old deployment was clean |
| State and versions | Preserve exact request identity and pinned installation; never rebuild, patch or remove files needed by live or recoverable operations |
Use [the coordinator template](https://weaveport.dev/docs/embedded-coordinator.md) for admission limits and shutdown wiring. The reference CLI owns one coordinator for its run; it is not a continuously serving daemon. Native reservations are estimates and do not enforce hard memory, CPU or filesystem ceilings. An operator must supply capacity monitoring and a qualified service boundary before production rollout.
## Normal start and stop
Normal Appointment Desk commands acquire the local calendar owner and create `/runtime/run.json` exclusively before creating any worker. The marker records schema 1 and a random generation, with no credentials or process-kill authority. Worker workspace roots use `/runtime/workers/`. Empty, malformed or existing markers block execution without replacing their contents.
A normal completed invocation drains the shared coordinator. Only a clean snapshot permits removal of an empty generation directory and the marker. Unexpected remaining generation files keep the marker in place. Disposing a file handle or merely observing the coordinator process exit does not mark a run clean. Failure to remove the marker also keeps restart blocked.
For an embedded service: stop accepting requests, call `StopAsync`, inspect the returned snapshot and keep callback dependencies alive while outstanding work remains. Use the existing request identity to reconcile uncertain outcomes. The CLI uses five seconds grace plus five seconds observation after its operation, and exits with an explicit diagnostic when cleanup is incomplete; its retained marker blocks the next execution. Ctrl+C and the existing 60-second outer timeout cancel CLI work. Forced termination and supervisor deadlines must leave time for normal drain; no fixed deadline guarantees arbitrary managed callbacks stopped.
## After an unclean stop
1. **Keep ingress and automatic restart disabled.** A `Native startup blocked` diagnostic is an intentional gate. Repeated launches, a different store path or deleting `run.json` are not recovery mechanisms.
2. **Establish termination of the complete old deployment.** Use independently qualified supervisor ownership, not saved PIDs, `Instance` suffixes, process names, EOF or elapsed time. If termination cannot be established, keep restart blocked. Do not use broad process-name kills against a shared desktop account. A full machine restart ends old processes, but does not establish that persisted application state is valid or power-loss durable.
3. **Preserve evidence before changing files.** Retain `runtime/run.json`, its referenced generation directory, the original `calendar.json`, relevant diagnostics and the exact pinned installation/runtime artifacts. Keep access restricted: workspace/state files may contain application data. Preserve an untouched copy outside the active root; do not edit booking IDs, requests, installation pins or schema values.
4. **Archive the old run under operator control.** Only after step 2, move the old generation directory and `run.json` to a private quarantine directory. Do not merge the generation into a new workspace or recursively delete unrelated directories. Marker content is diagnostic input, not a trusted arbitrary filesystem path. For schema 1 the generation is a 32-character hexadecimal identifier under that deployment's known `runtime/workers` directory. A partial/invalid marker requires inspection of the entire known deployment root.
5. **Reopen using the original installation and exact request.** The application validates the retained calendar and installation pin. On malformed state or unavailable/changed pinned artifacts, stop and restore the matching approved deployment/validated backup through the application's recovery process. Do not reset history or silently choose the active default version.
6. **Inspect the domain result and cleanup.** A previously committed booking returns its original identity. An intent without a terminal outcome can execute only when explicitly resubmitted under the same key. The application does not scan and replay pending intents automatically. Confirm a clean run removes its marker; re-enable ingress only after deployment checks pass.
The marker records potential unclean execution, not a durable transaction or a complete list of worker processes. The guard flushes file buffers before launch; it does not synchronize calendar state and directory entries into a power-loss transaction. Filesystem corruption, full disks, OS crashes and restoration from backups require separate qualification. Windows native qualification remains open.
## Diagnostics and retention
| Evidence | Interpretation and retention |
|---|---|
| `CoordinatorSnapshot.Active`, `ShutdownFinished`, `Clean` | An observation deadline is not work completion. Inspect `Clean` even after the lifecycle task finishes |
| Runtime workers, bindings, tenants, quarantine and maintenance failure | Outstanding callbacks and unconfirmed cleanup remain visible within a live coordinator; those counters do not survive root death |
| `runtime/run.json` and generation directories | Retain after unclean stop until supervised investigation/archive. Clean runs remove only their empty generation root; no reuse of abandoned files |
| Calendar command/outcome and installation pin | Keep for the application's recovery/idempotency lifetime. The sample has 1000 intents / 2 MiB capacity and no automatic eviction or migration |
| Installed releases and runtime bytes | Keep every exact installation needed by retained state; activation does not authorize deletion of old releases |
| Quarantine, reports and logs | Apply the owner's retention/access policy after investigation. No automatic quarantine deletion is implemented. Avoid payloads, secrets and sensitive calendar content in routine logs |
Do not infer a booking failed from exit code 1, cancellation or a cleanup diagnostic. Check the retained command/outcome under the original key. A run that returned no response may already have committed its effect. Real external providers need their own idempotency or reconciliation contract.
## Reproduce the crash scenario
```sh
./scripts/appointment-desk.sh --build --verify
./scripts/verify-recovery.sh
./scripts/verify-compatibility.sh
```
The crash verifier requires macOS and launches only isolated test state. It creates a new POSIX session, waits for a post-booking barrier, sends SIGKILL to the coordinator root, confirms startup refusal, then terminates its own test process group and archives the run evidence before explicit recovery. Its process-group authority comes from that launch, not from a stored PID. The cooperative fixture does not daemonize; this test cannot prove containment of arbitrary native children.
`--hold-after-booking PATH` is a test-only Appointment Desk fault option that creates a new barrier file after commit and waits until cancellation. Use it only with isolated stores and the crash driver; it is not a plugin operation or recovery command. The driver records whether the fixture worker was still running immediately after the crash and preserves leftover workspace evidence. See the [retained report (historical) — pre-public record](https://weaveport.dev/docs/history.md).
---
## Diagnostics
Source: https://weaveport.dev/docs/runtime-diagnostics.md
# Runtime diagnostics
Observe worker startup, invocation, callback and cleanup failures through your application’s existing logging. Diagnostic events expose lifecycle context while excluding plugin payloads and secrets.
Pass an application-owned `ILogger` to `new PluginHost(logger, options: limits)`. The existing constructor uses a null logger; the library does not configure global logging or own the logger's lifetime. Hosting references Microsoft.Extensions.Logging.Abstractions 10.0.12 (MIT), whose net10.0 dependency is Microsoft.Extensions.DependencyInjection.Abstractions 10.0.12 (MIT). The internal offline feed includes both original packages with license metadata.
| Event ID | Level | Meaning | Structured fields |
|---|---|---|---|
| 1001 | Warning | Worker startup failed | WorkerInstance, ErrorType |
| 1002 | Warning | Application callback failed | WorkerInstance, CorrelationId, ErrorType |
| 1003 | Warning | Invocation failed | WorkerInstance, CorrelationId, Stage, ErrorType |
| 1004 | Error | Cleanup failed | WorkerInstance, ErrorType |
| 1005 | Error | Background maintenance failed | ErrorType |
| 1006 | Warning | Host admission rejected before dispatch | Reason |
IDs belong to WeavePort.Hosting. Correlation IDs are generated for invocations. `prepare` includes deadline, diagnostic setup and worker startup; `exchange` begins when dispatch may have happened. Capacity refusals and cooperative cancellation are not ordinary plugin failure events. Cancellation callback failures during disposal are cleanup events.
No exception object or message, stack trace, payload, configuration, credential, operation name or raw worker stderr is passed to these events. Worker stderr remains drained to avoid blocking the process. Plugin-side generic SDK errors remain generic; these events do not promise plugin stack traces. Treat any custom log provider and its access/retention policy as application infrastructure.
Existing activities expose transport measurements; `PluginHost.Snapshot` exposes reservations, registrations, retained callback admission, quarantine and the last maintenance failure type. A cleanup event does not establish that an external effect failed. Follow the [native recovery runbook](https://weaveport.dev/docs/native-operations.md) for uncertain application outcomes.
Admission reasons are fixed codes (`concurrent-starts`, `pool-reservations`, `tenant-reservations`, `session-call`, `tenant-calls`). These identify host gates; the SDK client has its own serialization gate. Limits and busy rejection semantics are unchanged.
---
## Architecture
Source: https://weaveport.dev/docs/architecture.md
# Architecture and decisions
WeavePort adds plugin execution to the application you already own. It is a library embedded in each application, with domain contracts, authorization and durable state supplied by that application. One `PluginHost` owns one explicit shared worker budget; creating multiple hosts creates independent budgets. It is not a distributed scheduler or a machine-wide singleton.
## Ownership
- Applications authenticate callers, select immutable tenant/plugin/profile identity and grant callback operations. Plugin payloads cannot establish authority.
- Applications own business schemas, workflow state, journals, idempotency and reconciliation. Domain concepts stay out of the platform.
- Hosting owns single-flight sessions, per-tenant admission, deadlines, pristine workers, idle release and cleanup accounting. A used worker is never reassigned to another customer.
- Author SDKs own protocol details; the client SDK owns bounded unary/stream calls. A gateway selects a preconfigured binding through a credential and cannot register executables remotely.
## Package boundaries
`WeavePort.Abstractions` defines the shared contracts. Hosting depends on abstractions and caller-owned logging abstractions. The author SDK has no hosting dependency. `WeavePort.Sdk.Client` adapts host sessions. Optional Composition and Gateway packages implement separate concerns; applications choose them explicitly. Testing helpers belong to verification and are not application prerequisites.
All current core packages target .NET 10. The [compatibility matrix](https://weaveport.dev/docs/package-compatibility.md) identifies exact versions; API/protocol version 1 does not establish equality of artifact bytes.
## Execution boundary
Native `ProcessProfile` launches explicitly trusted same-user code with private cooperative workspaces and stdio or opt-in Unix sockets. Admission memory reservations are not hard resource limits. Native processes cannot contain malicious code or escaped descendants.
`DockerProfile` requests container resource and operating-system restrictions. Effective protection depends on the actual engine/kernel/deployment. Its regression fixtures remain available; historical container measurements do not qualify the current native release for a new platform.
## Lifecycle decisions
Keep stateful workers by default; idle release and prewarming are opt-in. Bound both tenant and shared capacity. Cleanup-uncertain workers remain reserved and unavailable. Disposed sessions release registration, while outstanding callbacks retain their own admission until actual completion.
Cancellation means that the caller stopped waiting, not that an external action failed. Complete independent cleanup attempts even when cancellation callbacks throw, report failures and retain uncertain business outcomes. See [worker lifecycle](https://weaveport.dev/docs/worker-lifecycle.md) and the [recovery runbook](https://weaveport.dev/docs/native-operations.md).
## Deferred work
The four core packages are publicly available at 0.3.1. Windows qualification, stronger native containment, distributed scheduling, application signing/notarization and automatic updates/migrations remain separate work. Integrations with the owner's applications follow their own development schedule.
The [historical evidence guide](https://weaveport.dev/docs/history.md) explains where earlier design alternatives, measurements and rejected experiments are retained, including the limits of public access to pre-baseline history. This guide retains the decisions that still govern current code.
## Optional MCP protocol
Current source also supports explicitly selected local MCP tools through the same process lifecycle; native remains the default. See [MCP plugins](https://weaveport.dev/docs/mcp-plugins.md) for exact revisions, result semantics and support limits. MCP does not introduce AI concepts or implicit host authority into native plugins.
---
## Internal distribution
Source: https://weaveport.dev/docs/internal-distribution.md
# Internal distribution 0.1.0-internal.2
This versioned delivery contains the qualified owner-controlled plugin platform and three reference applications for macOS arm64. The bundle version is distinct from component versions: four core NuGet packages are `0.1.0-internal.2`, the Python wheel and TypeScript npm package remain `0.1.0`. Their exact bytes come from the retained internal candidate qualification; packaging does not rebuild or relabel them.
## Prerequisites
The qualified environment is macOS 26.6.2 arm64, .NET shared framework **10.0.12** and Python **3.14.7**. The installer checks the qualified .NET and Python executable hashes in `distribution.json`. Only .NET 10.0.12 may be installed within the 10.0 runtime family for this delivery. Other major runtime families may coexist. Building the source templates also requires .NET SDK **10.0.401**. The optional TypeScript package was qualified with Node **26.8.2**; Node is not required to run these three applications.
Prerequisites must already be installed. Installation uses the bundled Python wheel with `--no-index --no-deps`; it downloads no packages. This is a framework-dependent internal delivery, not a clean-OS installer or a signed/notarized release. Do not disable operating-system protections to run it. Checksums detect changes against trusted metadata; they do not authenticate a hostile replacement or provide a process sandbox. Stable files and owner-controlled plugins remain required.
## Install and run
Verify the archive checksum against the separately supplied trusted checksum, extract it, then run from the extracted bundle directory:
```sh
shasum -a 256 -c WeavePort-0.1.0-internal.2-osx-arm64.tar.gz.sha256
tar -xzf WeavePort-0.1.0-internal.2-osx-arm64.tar.gz
cd WeavePort-0.1.0-internal.2-osx-arm64
python3 -B weaveport.py install "$HOME/Applications/WeavePort/0.1.0-internal.2"
```
Use `--dotnet /absolute/path/to/dotnet --python /absolute/path/to/python3` if needed. A mismatch is refused before creating the destination. Existing destinations, even empty ones or incomplete installs, are never replaced.
The installed commands work from any working directory:
```sh
python3 -B "$HOME/Applications/WeavePort/0.1.0-internal.2/weaveport.py" doctor
python3 -B "$HOME/Applications/WeavePort/0.1.0-internal.2/weaveport.py" run decision-room -- --verify
python3 -B "$HOME/Applications/WeavePort/0.1.0-internal.2/weaveport.py" run document-workshop -- --verify
python3 -B "$HOME/Applications/WeavePort/0.1.0-internal.2/weaveport.py" run appointment-desk -- --verify
```
Omit `--verify` for a normal example run. Decision Room demonstrates shared C#/Python decision strategies and journal replay; Document Workshop demonstrates interchangeable document readers; Appointment Desk demonstrates booking strategies and recovery of uncertain effects. Application options after `--` are passed through. Supply absolute paths for custom files, configuration and stores: the launcher uses the bundled template directory for default fixtures.
## Installed layout and state
- `payload/packages/nuget`: four exact core packages plus the two reviewed Microsoft logging dependencies, usable as an offline local NuGet feed.
- `payload/packages/python` and `payload/packages/typescript`: the qualified author SDK packages.
- `payload/templates`: copyable source trees for all three applications and shared coordinator/restart templates, root build settings and a self-contained local feed.
- `payload/evidence` and `payload/distribution.json`: retained qualification and delivery checksums.
- `var/`: executable copies, selectors and generated journals, documents, calendar data, verification evidence and worker state.
- `installation.json`: completion receipt and local runtime paths. It is written only after successful installation.
Diagnostics check shipped content, executable copies and required runtimes without resetting state. The `var/` application data is deliberately excluded from the shipped-content inventory. Back up the whole `var/` directory before manual maintenance. Appointment Desk's unresolved run marker continues to block unsafe restart; see `payload/docs/native-operations.md` for recovery boundaries. Doctor passing does not mean an application has no outstanding recovery work.
Do not move an installed directory: the Python environment and receipt bind it to its destination. Install future deliveries side by side. No automatic update, migration, uninstall, service registration or global PATH changes are included. Failed setup leaves an incomplete directory for inspection, which cannot launch normally. Remove it manually only after establishing that it contains no state to retain, then retry. Retain used installations for rollback; never delete recovery evidence to force a restart.
## Use as an integration template
Copy the **entire** `payload/templates` directory to a writable directory outside the installation, keeping its relative structure and bundled `artifacts/packages` feed. Build, for example:
```sh
dotnet build samples/DecisionRoom/Host -c Release
dotnet build samples/DecisionRoom/Plugin -c Release
dotnet build samples/DocumentWorkshop/Host -c Release
dotnet build samples/DocumentWorkshop/Worker -c Release
dotnet build samples/AppointmentDesk/Host -c Release
dotnet build samples/AppointmentDesk/Worker -c Release
```
These are application sources, not a generator that requalifies changed plugins. Original sample READMEs describe repository development scripts; those scripts are not part of the copied template. For qualified execution use the installed launcher. Changes to plugin builds require new installation manifests and qualification; never silently reseal a persisted operation's pinned installation.
For an existing application's integration, add `payload/packages/nuget` as an explicit local source and use a fresh package cache. Do not mix earlier packages sharing `0.1.0-internal.2` with this feed. The three production applications remain unchanged. Optional Composition, Gateway and Testing packages are outside this delivery's package set.
## Reproduce packaging
From the WeavePort repository:
```sh
python3 -B tools/distribution/package.py /absolute/path/to/retained-candidate --output artifacts/internal-distribution
python3 -B tools/distribution/verify.py artifacts/internal-distribution/WeavePort-0.1.0-internal.2-osx-arm64.tar.gz
```
The packager verifies candidate bytes against checked-in qualification evidence, reads template sources from the qualified Git commit (including separately recorded qualification lockfile refreshes), and includes current distribution tooling and this guide. Output directories are never reused. Archive checksums identify an individual delivery; bit-identical archives across independent builds are not claimed.
---
## Releases
Source: https://weaveport.dev/docs/releases.md
# GitHub and NuGet releases
The GitHub delivery target is [yesbert/WeavePort](https://github.com/yesbert/WeavePort). CI verifies documentation and release tooling, and runs the existing frozen-candidate qualification on a standard macOS ARM runner. This is functional qualification, not a hosted performance benchmark or Windows support claim.
## Packages and version
The release allowlist in `build/release-packages.json` contains `WeavePort.Abstractions`, `WeavePort.Hosting`, `WeavePort.Sdk` and `WeavePort.Sdk.Client`. Gateway, Composition and Testing remain optional/experimental; adding them requires appropriate package-consumer evidence. Python and TypeScript author SDK publication is separate from NuGet delivery.
The current release version is `0.3.1`, licensed under [MIT](https://raw.githubusercontent.com/yesbert/WeavePort/main/LICENSE). The four core package references and exact compatibility matrix use 0.3.1; host API and wire protocol remain 1. Python/TypeScript SDK versions remain 0.1.0 without registry publication. Historical internal distribution and measurement evidence retain their original identities. Public releases require a complete clean candidate qualification; a tag override cannot substitute for updating compatibility inputs.
## Trusted Publishing setup
The workflow separates three responsibilities: verification without publication credentials, a gated publish job and a separate release announcement.
Configure these values:
| Location | Setting |
|---|---|
| GitHub Actions repository variable | `NUGET_USER=Yesbert` |
| GitHub environment | `nuget-org` |
| Environment required reviewer | `yesbert` |
| Environment deployment restriction | Tags matching `v*` |
| NuGet.org policy owner | The account owning the WeavePort packages |
| NuGet.org GitHub repository owner | `yesbert` |
| NuGet.org repository | `WeavePort` |
| NuGet.org workflow filename | `release.yml` |
| NuGet.org environment | `nuget-org` |
Create the matching policy in the authenticated NuGet.org account. Scope it to the intended WeavePort packages and permit new package IDs when creating the first release. A policy for Stratara does not authorize WeavePort. Follow [NuGet Trusted Publishing](https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing) for current account requirements and policy activation rules. There is no long-lived API-key fallback.
## Release procedure
1. Choose and review the public version and license. Update exact compatibility inputs and regenerate LLM documentation. Merge the reviewed change with green CI.
2. Create and push an annotated `v` tag at that reviewed commit. The tag must exactly match `Directory.Build.props`; internal suffixes and malformed versions are rejected.
3. The release workflow repeats clean qualification. It checks the qualified commit, package hashes, metadata, readme, source provenance and symbols, then uploads only the original tested allowlisted artifacts.
4. Review the `nuget-org` deployment. After approval, `NuGet/login` exchanges GitHub OIDC identity for a short-lived key and publishes the packages and symbols.
5. Only after successful publication does the announce job create the GitHub release; prereleases are marked accordingly. An existing release entry is preserved on rerun.
Branch pushes and pull requests never publish packages. Publication cannot be undone by deleting a Git tag: NuGet versions remain allocated. A partial publish is resumed with the same tested artifacts and `--skip-duplicate`; investigate any mismatch before rerunning. Never move a released tag to different source.
CI retains qualification logs and manifests for 14 days. Preserve release evidence durably when qualifying a public release. GitHub-hosted runner SDK/runtime identities are recorded by the candidate harness. Docker Desktop on a developer machine is not touched by these workflows.
## 0.2.0 migration
The pre-1.0 minor release includes breaking host API cleanup: rename `ExecutionProtection` to `ExecutionProtections`, and pass `requiredProtection` before the final `cancellationToken` in `BindAsync` and `PrewarmAsync` (named arguments are recommended). Rebuild consumers and regenerate installation declarations for the exact 0.2.0 core package matrix; the wire protocol and host compatibility level remain 1. Python and TypeScript author SDKs remain 0.1.0.
This release fixes cancellation-source ownership and shutdown/startup races, uses exclusive private native-socket directories, and selects Docker by an absolute trusted CLI path. Set `DockerProfile.DockerExecutable` for nonstandard CLI installations; PATH lookup is no longer used. All 37 original Sonar issues and both security hotspots were resolved before preparing this release. Platform validation limits remain documented in [platform qualification](https://weaveport.dev/docs/platform-qualification.md).
The [0.2.0 release report](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.2.0/README.md) retains publication verification and links to durable package, symbol and qualification assets.
## 0.2.1 package branding
All core packages embed the existing website logo as their NuGet icon. Release export requires the embedded image to match the repository asset byte for byte. This patch changes package branding and exact compatibility versions; runtime APIs remain unchanged from 0.2.0.
The [0.2.1 release report](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.2.1/README.md) records exact public package and gallery icon verification, with durable qualification artifacts.
## 0.3.0 optional MCP tools
Hosting adds explicitly selected local MCP 2025-11-25 and 2026-07-28 tools alongside native plugins. Discovery and calls share worker admission, tenant ownership, deadlines and cleanup. Native remains the default; there is no new MCP runtime dependency. Unsupported result continuations are rejected even if a server also supplies content. See the [MCP guide](https://weaveport.dev/docs/mcp-plugins.md) and [executable example](https://raw.githubusercontent.com/yesbert/WeavePort/main/examples/mcp/README.md).
Update all four core packages and exact installation declarations together. Native author SDKs remain 0.1.0 and are still source-built. Hosting uses Microsoft logging/DI abstractions 10.0.12; the optional gateway's build-only Grpc.Tools is 2.84.0. Remote MCP, arbitrary server SDKs and additional platform qualifications are outside this release.
The [0.3.0 release report](https://raw.githubusercontent.com/yesbert/WeavePort/main/reports/release/0.3.0/README.md) links the original qualified packages, symbols, test evidence and measurements of the released Hosting assembly.
## 0.3.1 named MCP methods
Hosting exposes `McpMethods.ListTools` and `McpMethods.CallTool` for consumer invocations. Examples and the guide use these constants. Internal MCP identifiers, SDK operations and gateway metadata are centralized without changing wire values. Update the four core packages together to match the exact 0.3.1 compatibility matrix.
---
## AI documentation
Source: https://weaveport.dev/docs/ai-documentation.md
# Use WeavePort with AI assistants
Give your coding assistant WeavePort's guides, examples and reviewed API signatures so it can help build an integration against the actual contracts.
## Start with the documentation
- [llms.txt](https://weaveport.dev/llms.txt): compact index for finding the right guide.
- [llms-full.txt](https://weaveport.dev/llms-full.txt): combined guides, verified specifications and reviewed .NET API signatures.
The index follows the [llms.txt proposal](https://llmstxt.org/). Its project heading, summary and grouped Markdown links support targeted retrieval. The full file is a companion convention, not a separately standardized schema. Each documentation page also has a Markdown version: replace `.html` with `.md`. HTML discovery links identify both the Markdown version and `/llms.txt`.
Website retrieval files and Markdown pages come from the same build. Repository copies use GitHub source URLs. Neither includes unfinished OpenSpec changes or historical reports as implemented guarantees. For installation details, read [status](https://weaveport.dev/docs/status.md), [platform support](https://weaveport.dev/docs/platform-qualification.md) and [compatibility](https://weaveport.dev/docs/package-compatibility.md) first.
Paste this into an assistant with web-fetch access:
```text
Use https://weaveport.dev/llms.txt to help me integrate WeavePort into my
.NET application. Read status, platform support and package compatibility
first, then the author SDK and coordinator guides. Use the documented API
signatures and a matching sample. Separate implemented behavior from pending
validation. Ask about my plugin contract before generating the integration.
```
These URLs are documents, not MCP endpoints. A fetch-capable client can read them without GitHub authentication. Loading documentation alone does not execute plugins.
## Connect the official GitHub MCP server
GitHub MCP lets an assistant retrieve files and search the `yesbert/WeavePort` repository. Use GitHub's hosted service; no local server installation is needed. Start with repository tools in read-only mode. Configuration and authentication depend on your MCP client. See the [official setup guide](https://github.com/github/github-mcp-server) and [remote toolset documentation](https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md).
For **VS Code**, add this to `.vscode/mcp.json` in your application workspace (merge it with any existing servers):
```json
{
"servers": {
"github-weaveport": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/x/repos/readonly"
}
}
}
```
Start the server in VS Code and complete GitHub sign-in when prompted. Use a client version supporting remote HTTP MCP and GitHub OAuth. If your client needs a personal access token, follow its secure credential-input flow; do not commit tokens. Other clients use their own configuration format with the same endpoint. Read-only mode limits available tools; it does not restrict the connection to a single repository.
Then give the assistant this task:
```text
Use GitHub MCP to inspect owner "yesbert", repository "WeavePort".
Read docs/status.md, docs/package-compatibility.md,
docs/platform-qualification.md and compatibility/public-api.txt.
For a package-based integration, use the tag matching my installed package
version (for 0.3.1: v0.3.1), and keep all source reads on that revision.
Use get_file_contents to inspect docs/plugin-sdk.md,
docs/embedded-coordinator.md and samples/DecisionRoom/README.md.
Find the corresponding host and plugin implementations before writing code.
Build a minimal integration for my application using these exact contracts.
```
Verify the connection by requesting `get_file_contents` with `owner: yesbert`, `repo: WeavePort`, `path: docs/status.md` and `ref: refs/tags/v0.3.1`. The result should contain the file from that revision. Tool prefixes vary by client. A missing tool usually means the server is not started or its repository tools are disabled; authentication failures need the client's sign-in or token setup. These setup instructions are based on GitHub's documentation; they are not a recorded authenticated client test.
GitHub MCP supplies repository context. To build or run an integration, your assistant additionally needs a local checkout, .NET and the required plugin runtimes, plus terminal access you authorize. WeavePort does not expose a plugin-execution MCP endpoint through this setup.
The separate [local MCP plugin integration](https://weaveport.dev/docs/mcp-plugins.md) lets current source consume MCP tools inside an application. It is not a documentation retrieval service or an exported MCP gateway.
## Keep the context current
Edit canonical Markdown or the reviewed API baseline, then regenerate the repository copies:
```sh
python3 scripts/generate-llms.py
python3 scripts/generate-llms.py --check
python3 scripts/build-website.py
```
CI rejects stale repository copies. Every website build generates its own index, full reference and Markdown pages from the current sources, validates local retrieval targets and includes them in the same deployment artifact. Publish the whole artifact so pages and AI context move together. The server serves that published snapshot; it does not independently pull GitHub changes, and assistants may need to refresh their own caches.
Add new consumer guides to the generator's curated `GUIDES` list; specifications are discovered under `openspec/specs/`. Regression tests cover index structure, source changes and website retrieval links. Keep the repository copies in the same commit as their source updates. For reproducible source work, pin all GitHub MCP reads to the installed release tag or commit rather than mixing `main` with a released package.
---
## Decision Room
Source: https://weaveport.dev/docs/examples/DecisionRoom.md
# Decision Room
A small executable integration template: Alice and Bob evaluate three improvement proposals. Plugins calculate evaluations and the winning proposal; the application controls the workflow, grants knowledge access and persists committed evaluations. No model, account, database, Docker engine or sibling product is required.
## Run
From the repository root, with the .NET SDK from `global.json` and Python 3.11+ with `venv`/`pip` available:
```sh
./scripts/decision-room.sh --build
```
The first build packs WeavePort libraries, restores the host and C# worker from those NuGet packages, builds/installs the Python SDK wheel into a private environment, and runs the example. Package build dependencies may require internet access. Later runs need no SDK package download:
```sh
./scripts/decision-room.sh --resume
```
The default journal is `artifacts/decision-room/runs/default.json`. A new run never overwrites an existing journal. Use `--journal artifacts/decision-room/runs/another.json` to start another one. The runner starts and stops only its own trusted native workers.
Expected decision:
| Proposal | Alice: economy | Bob: impact | Total |
|---|---:|---:|---:|
| A — Improve documentation | -6 | 9 | 3 |
| B — Automate support | -14 | 25 | 11 |
| C — Build analytics | -30 | 27 | -3 |
With version 1, the winner is **B**. Each evaluation prints the cost, benefit, retrieved risk, score and knowledge profile. Version 1 scores are `benefit × benefitWeight − cost × costWeight − risk × riskWeight`. Version 2 multiplies the risk penalty by ten and selects A for this fixture. The room sums scores and breaks ties by ordinal proposal ID. Completion requires both evaluations. There is no random source or semantic clock in this finite example.
## Change behavior through configuration
Copy `samples/DecisionRoom/config.json` to an example-owned location, edit it and pass `--config PATH --journal NEW_PATH`. Each participant selects `language` (`csharp` or `python`), a knowledge `profile` and integer priorities. With both participants using Alice's priorities, A wins; with both using Bob's priorities, C wins. Changing language alone preserves the result. Knowledge belongs to the configured tenant and profile, not to fields supplied in a callback request.
## Follow recovery
```sh
./scripts/decision-room.sh --journal artifacts/decision-room/runs/paused.json --pause-after-first
./scripts/decision-room.sh --journal artifacts/decision-room/runs/paused.json --resume
./scripts/decision-room.sh --journal artifacts/decision-room/runs/restarted.json --restart-after-first
```
The host commits an evaluation only after validating it and the resulting room transition. Resume initializes a fresh room and replays committed evaluations. A crash before commit allows this deterministic, side-effect-free evaluation to be recomputed. An exclusive lock prevents concurrent writers to one journal. A schema, configuration or selected built-artifact mismatch refuses resume. The journal records artifact hashes; do not replace native artifacts during a run. Rebuilding changed artifacts can intentionally invalidate an old journal.
This is local single-writer recovery, not power-loss durability, distributed coordination, secure package installation or an exactly-once promise for external actions.
## Observe denied knowledge access
```sh
./scripts/decision-room.sh --journal artifacts/decision-room/runs/denied.json --deny-knowledge
```
This deliberately exits nonzero: the strategy requests `knowledge.read` without its grant, the callback is not executed, and no evaluation is committed for that call. Run again with the same journal and `--resume` without the denial option to continue normally.
## Integration structure
- `Contracts`: sample-owned domain records; no WeavePort dependency.
- `Plugin`: C# SDK functions for room initialization/reduction/snapshots and evaluation. Distinct room and strategy bindings launch separate workers from the same artifact.
- `Python`: an equivalent strategy through the packaged Python SDK.
- `Host`: configuration, scoped callback, worker binding, state validation, persistence and console walkthrough.
- `Host/Verification.cs`: explicit `--verify` harness, including abrupt termination of an owned worker. Crash controls are absent from the plugin contract.
Both host and C# plugin reference packed WeavePort artifacts. Their only project reference is the sample's own contract module. No HiveWeaver, NextPA, TreeWeaver, Stratara or LoomWeaver dependency is introduced. This is an integration template inspired by HiveWeaver's extension boundaries, not a HiveWeaver adapter or parity demonstration. Application data and rules remain outside WeavePort core.
## Verify
```sh
./scripts/decision-room.sh --build --verify
```
The suite checks expected winners, both languages against the same fixtures, pause/resume, explicit restart, abrupt worker loss after commit, callback denial in both languages, concurrent customers and same-customer profiles, incompatible resume and exclusive journal ownership. Results and journals are retained in a unique directory under `artifacts/decision-room/verification/`.
Plugin release selection is described below. The current verification is native macOS on .NET 10 with C# and Python. It does not qualify Windows, Linux, Docker execution, remote workers, hostile plugins or full application migration. Native workers run trusted code under the user's OS identity; callback grants are not an OS sandbox. The existing broader PoC suites remain separate.
## Parallel plugin versions
The build creates actual release-1 and release-2 C# binaries and Python modules in separate `artifacts/decision-room/releases/` directories. The author SDK declares each release during startup, and the host checks it. Each evaluation also carries its release identity.
```sh
./scripts/decision-room.sh --build --journal artifacts/decision-room/runs/version-one.json --version 1 --pause-after-first
./scripts/decision-room.sh --activate 2
./scripts/decision-room.sh --journal artifacts/decision-room/runs/version-two.json
./scripts/decision-room.sh --journal artifacts/decision-room/runs/version-one.json --resume
```
The new run uses version 2 and selects A. The resumed run still uses version 1 and selects B. `--activate 1` returns the default for future runs to version 1. `--version 1` or `--version 2` explicitly selects a release for a new run; the JSON configuration can alternatively set `pluginVersion`. An explicit conflicting selection on resume is refused.
Activation changes only `active-version.txt`. A run resolves it once, stores its version in its journal, and uses that version for every subsequent binding and restart. Resume reads the pinned version rather than the active default. Changes to another release do not invalidate the selected release's hashes. Missing, changed or incorrectly labelled selected artifacts are refused; there is no automatic fallback.
`--verify` also holds a version-1 worker live at a committed boundary while activating version 2 and completing a second run, then replaces the original worker and checks its version-1 result. It checks both languages in both releases and uses an isolated selector and artifact copies for fault tests, leaving normal deployment files untouched.
**Development boundary:** build and activation are different actions. `--build` is an offline development rebuild and can replace artifacts/shared SDK files; stop active example runs before rebuilding. Activation of already-built releases is the supported live operation. This is not a production package installer or a live host/SDK upgrade mechanism. Native runtimes and selected artifact bytes must remain stable while executing.
**Journal schema:** this version uses schema 2. Journals from the initial development slice (schema 1) are refused without modification. Retain that original build to replay them, or start a new journal. Schema 2 prevents default activation from changing an existing run's selected release.
## Shared installation identity
This sample now uses the packaged [installed-plugin resolver](https://weaveport.dev/docs/installed-plugins.md). Builds seal release directories; resolution validates content and contract identity. Activation changes future operations only. Do not modify or rebuild executing release/runtime files. The offline build now requires Python 3.11+ for manifest sealing.
Journals created before this resolver lack its manifest digest and are refused unchanged. Use a fresh `--journal` or retain the original build for those development journals.
---
## Document Workshop
Source: https://weaveport.dev/docs/examples/DocumentWorkshop.md
# Document Workshop
An independent integration template for document readers: import a local UTF-8 file, choose an approved reader and inspect normalized sections and metadata. The application owns input capture, reader selection and committed documents. Workers own extraction. No TreeWeaver dependency, database, model service or Docker engine is required.
## Run
From the repository root, with the .NET SDK selected by `global.json`:
```sh
./scripts/document-workshop.sh --build
./scripts/document-workshop.sh --list-readers
./scripts/document-workshop.sh --file samples/DocumentWorkshop/fixtures/handbook.md --reader plain
./scripts/document-workshop.sh --file samples/DocumentWorkshop/fixtures/notes.md
```
The build packs current WeavePort NuGet libraries, restores the host and worker from those packages, and runs the default handbook import. Package restore may require internet access. Subsequent commands use the built artifacts.
The default handbook produces four sections with the Markdown reader: Handbook, Installation, Recovery and Unicode. The same file with `--reader plain` produces one logical section containing the original heading syntax. The notes fixture makes the outline reader decline, so automatic selection tries plain text. Explicit reader selection never silently substitutes another reader.
Each import prints its reader, section/fragment counts, headings and the resulting file path. Results are uniquely named NDJSON files in `artifacts/document-workshop/documents/`; a new import does not overwrite existing documents. Open that file to inspect the full normalized content.
Options: `--file PATH`, `--reader markdown|plain`, `--config PATH`, `--store PATH`, `--tenant ID`, `--profile ID`, `--list-readers` and `--verify`. The CLI has a 60-second overall deadline; Ctrl+C cancels. Tenant/profile options model trusted application context, not production authentication.
## Reader selection
`config.json` declares the installed first-party readers in preference order. The application maps only known identifiers to its built worker; configuration cannot install arbitrary executables. Both readers share a worker binary with distinct reader implementations selected by the trusted launcher. Each attempt uses a separate process/binding and verifies its description/version before extraction.
| Reader | Media types | Behavior |
|---|---|---|
| `markdown` v1 | `.md` / text/markdown | Requires an ATX heading as the first nonblank line; extracts subsequent headings outside fenced code. |
| `plain` v1 | `.txt`, `.md` | Emits one logical section and retains heading syntax as text. |
Remove a reader from the config to simulate an installation without it. An unavailable explicit reader or unsupported file type is rejected before staging. Only a declared content decline enables fallback; crashes, invalid data, quotas and cancellation fail the import.
## Source transfer and extraction
The host captures the source in its staging area, computes a SHA-256 digest and gives the plugin an opaque document ID, filename, media type and byte length. The plugin never receives a host document path.
`document.read` callbacks are bound to the import's tenant/profile and document ID. They validate byte offset/count, enforce a 32 KiB read ceiling and a cumulative transfer allowance, and stop serving bytes after lease disposal. Native workers are still trusted same-user processes; these API checks do not impose an OS filesystem sandbox.
The sample-owned `reader.open` / `reader.next` protocol consumes at most one source block per step and returns at most 32 ordered fragments. Strict incremental UTF-8 decoding preserves characters across blocks. Reader state is temporary and belongs to that worker. The host validates every page and writes it incrementally to staging; it never needs to accumulate the complete normalized document in memory.
This pull protocol is deliberate: the current SDK's automatic stream batching can gather 16 items while a single invocation permits eight callbacks. Sparse documents could exceed that budget. Explicit bounded extraction steps fit the existing runtime without widening a generic callback limit. The document protocol remains part of this example's domain contract.
## Stored format and completion
NDJSON has three record kinds:
- `document`: filename, media type, captured length/digest, reader/version and host-bound tenant/profile.
- `fragment`: global sequence, section number, part number, heading, heading level, anchor and text.
- `complete`: final section and fragment counts.
A section with a long body spans ordered parts. Join those parts to reconstruct its body. Only a validated complete extraction that consumed the captured source can be moved into the document store. A partial file is never presented there as complete. Handled failures/cancellation revoke the source lease and remove the import's staging directory. An empty source fails without committing a document.
The outline grammar is intentionally small: ATX headings with up to three leading spaces, optional ASCII `{#anchor}` suffixes, and backtick/tilde fences. Duplicate anchors are refused; otherwise generated `section-N` anchors are stable for the same input. Links remain in body text. This is not a CommonMark implementation. Both readers strip a UTF-8 BOM and normalize line endings to LF, including the last line. Invalid UTF-8 is refused, not replaced silently.
## Explicit limits
| Scope | Limit |
|---|---:|
| Captured input | 8 MiB |
| One source read | 32 KiB |
| Reads per reader attempt | 1024 |
| Cumulative returned source bytes | source length + 32 KiB |
| One input line / one body fragment | 4096 UTF-16 characters |
| One heading / anchor | 256 / 128 characters |
| One result page | 32 fragments |
| Total fragments | 8192 |
| Normalized output | 32 MiB |
Oversize input, lines, output or malformed pages fail without a truncated commit. These are application limits, not OS memory ceilings or aggregate multi-user quotas. The worker buffers one decoded input block and its bounded pending fragments; it does not materialize the complete document.
## Verify and adapt
```sh
./scripts/document-workshop.sh --build --verify
```
The checks cover reader substitution/fallback, supported headings/anchors/fences, large Unicode input, source digest, line endings, invalid encoding, source/output limits, missing grants, invalid pages, cancellation after output, actual worker termination and overlapping tenant/profile imports. Direct lease tests additionally check foreign identities/ranges, transfer budgets and post-disposal revocation. Fault hooks exist only in the host test harness, not reader operations.
`Contracts` is sample-owned. `Worker` implements the two readers through `WeavePort.Sdk`; `Host` consumes Hosting/Sdk.Client packages. Only the sample contract module is a project reference. The three original products and Decision Room remain independent.
Verified scope is native local macOS on .NET 10. No PDF/OCR, search quality, Windows/Linux, remote execution, Docker or hostile-plugin qualification is claimed. Cleanup covers handled errors and cancellation; coordinator-crash orphan recovery and power-loss durability remain future product work. Do not rebuild trusted worker artifacts while imports are running.
The [retained verification report (historical) — pre-public record](https://weaveport.dev/docs/history.md) records the 41 passing assertions and tested scope.
## Shared installation identity
This sample now uses the packaged [installed-plugin resolver](https://weaveport.dev/docs/installed-plugins.md). Builds seal release directories; resolution validates content and contract identity. Activation changes future operations only. Do not modify or rebuild executing release/runtime files. The offline build now requires Python 3.11+ for manifest sealing.
Both release 1 and release 2 implement the same domain contract. Use `--activate 2` to change the default or `--version 1` for explicit selection. The selected installation is recorded with the result or persistent intent.
---
## Appointment Desk
Source: https://weaveport.dev/docs/examples/AppointmentDesk.md
# Appointment Desk
A standalone package-consuming integration template for actions with uncertain responses. Two first-party scheduling strategies choose appointments; the application owns the calendar, approved commands and durable booking results. No NextPA integration, real calendar, network service or Docker engine is required.
## Run
From the repository root with the SDK selected by `global.json`:
```sh
./scripts/appointment-desk.sh --build
./scripts/appointment-desk.sh --list-strategies
./scripts/appointment-desk.sh --request late-demo --strategy latest
./scripts/appointment-desk.sh --request late-demo --strategy latest
```
The last two commands return the same booking ID. `earliest` v1 chooses the first available slot; `latest` v1 chooses the last. Both are installed implementations in one approved worker binary. Strategy identifiers cannot select arbitrary code. Each tenant/profile has an independent example calendar with six half-hour slots on **2030-01-14, 09:00–12:00 UTC**. Fixed future fixture dates are deliberate; no current-time scheduling is implied.
The default request ID is `demo-request`, so repeating the default command demonstrates replay. Use a new `--request` only for a genuinely new booking intention. The same scoped ID with a changed strategy, subject or time window is refused.
The build packs local WeavePort NuGet artifacts and restores/publishes this sample into its own artifact directory. Package restore may require internet access. Only the sample Contracts project is referenced directly; WeavePort libraries are package references.
## Demonstrate a lost response
```sh
./scripts/appointment-desk.sh --request recovery-demo --lose-response
# Expected exit code 2 and Status "uncertain": the actual worker process was killed after booking.
./scripts/appointment-desk.sh --request recovery-demo
```
The second command starts a new coordinator and worker, reads the retained command and returns its original booking ID. Inspect `artifacts/appointment-desk/calendar/calendar.json` between commands: the effect exists even when the first caller did not receive its result. The fault option terminates only the worker owned by that invocation. Omit it on the recovery command. Use a fresh store/request if the fixture calendar is already full.
## Options and results
| Option | Meaning |
|---|---|
| `--request ID` | Stable application request identity; maximum 128 characters |
| `--strategy earliest\|latest` | Approved selection implementation |
| `--tenant ID`, `--profile ID` | Trusted host context for a separate example calendar |
| `--subject TEXT` | Booking subject, maximum 128 characters |
| `--from ISO`, `--until ISO` | Containing window, explicit UTC offset, e.g. `2030-01-14T09:00:00Z` |
| `--store PATH` | Local store directory; defaults to `artifacts/appointment-desk/calendar` |
| `--lose-response` | Demonstrate worker termination after a committed callback |
| `--verify` | Run isolated executable verification |
`booked` includes the booking ID and selected slot. `conflict` is a retained terminal result for a slot taken after selection. `unavailable` means no slot was proposed and creates no intent. `uncertain` means dispatch did not produce a verified response; it is not evidence that the action failed. Repeat the exact request to reconcile it. A confirmed conflict requires a new request if the user wants another appointment; recovery never silently changes the selected slot.
Exit codes: 0 for a known domain result, 2 for uncertain dispatch, 130 for cancellation outside dispatch, 1 for invalid input/storage or pre-dispatch failure. Ctrl+C and a 60-second overall deadline cancel operations. These console context options are not an authentication system.
## Ownership and recovery
1. The strategy requests availability through `calendar.available` and proposes a slot.
2. The application validates the proposal and persists the exact command before execution.
3. The strategy executes through `calendar.book`, scoped to its host-bound tenant/profile and exact approved command.
4. The host checks the existing request outcome first. Otherwise it atomically decides conflict/booking within the local store mutation and records the outcome before replying.
5. The application validates the plugin's returned outcome against the stored result. An interrupted response retains the same intent for replay.
Same-key concurrent attempts converge on the first persisted command. Different requests competing for one scoped slot cannot both book it. Callback payloads do not supply tenant authority or arbitrary calendar paths. Missing grants and changed approved commands cause no callback effect. Native workers remain trusted same-user processes, without an OS sandbox.
The local store admits one coordinator through an exclusive owner handle and serializes in-process mutations. Commands and effects share one JSON snapshot, replaced from the same directory; failed writes do not publish a new in-memory booking. Reopening validates schema, scoped keys, slots and booking identities. Malformed or oversized data is refused without resetting the store. Limits are **1000 retained intents and 2 MiB**; history is never automatically evicted, and existing results can still be replayed at capacity.
This is a local transaction example. An external calendar requires an equivalent provider idempotency key or reconciliation mechanism; putting a local journal beside a non-idempotent remote API does not provide the same guarantee. Power-loss durability, distributed coordinators, network filesystems and hostile plugins are unqualified. No booking cancellation/rescheduling or retention migration is implemented. Do not rebuild trusted worker artifacts while operations are running.
## Verify and adapt
```sh
./scripts/appointment-desk.sh --build --verify
```
The suite covers strategy substitution, replay, changed input, availability, actual worker death after commit, coordinator reopen, competing bookings, overlapping customers, independent profiles, callback denial, changed command authority, cancellation before/after effect, storage write failure, ownership, corruption and capacity. See the [retained verification report (historical) — pre-public record](https://weaveport.dev/docs/history.md).
Adapt the sample-owned wish, slot and command contracts to the consuming application. Keep approval, scoped identity, conflict rules and effect reconciliation in the host/provider transaction boundary. The WeavePort runtime remains domain-independent; HiveWeaver, NextPA and TreeWeaver are unchanged.
## Shared installation identity
This sample now uses the packaged [installed-plugin resolver](https://weaveport.dev/docs/installed-plugins.md). Builds seal release directories; resolution validates content and contract identity. Activation changes future operations only. Do not modify or rebuild executing release/runtime files. The offline build now requires Python 3.11+ for manifest sealing.
Both release 1 and release 2 implement the same domain contract. Use `--activate 2` to change the default or `--version 1` for explicit selection. The selected installation is recorded with the result or persistent intent.
Calendar schema is now **2**. Older schema-1 stores are refused unchanged because their original installation identity was not recorded. Start this build with `--store artifacts/appointment-desk/calendar-v2`; use the original build to access an old store.
## Shared coordinator composition
The application now creates one shared coordinator at its composition root and injects it into every `Desk`. Concurrent requests therefore share worker and operation budgets. The reusable source, overload semantics, shutdown sequence and dependency ownership are documented in the [embedded coordinator guide](https://weaveport.dev/docs/embedded-coordinator.md). `--verify` also exercises actual concurrent workers, global capacity refusal, graceful drain, forced shutdown after commit and late callback accounting. See the [current coordinator evidence (historical) — pre-public record](https://weaveport.dev/docs/history.md).
## Guarded native restart
Normal CLI execution now creates `/runtime/run.json` before workers start and uses a fresh workspace generation. Only confirmed clean shutdown clears the marker. An existing marker blocks execution and preserves booking state. Follow the [native recovery runbook](https://weaveport.dev/docs/native-operations.md) after an unclean stop; do not delete the marker merely to bypass the gate. Initial adoption from an older unguarded build also requires inspection of old processes. `./scripts/verify-recovery.sh` exercises an actual coordinator crash and supervised exact-request recovery in isolated test state.
---
## appointment-desk
Source: https://weaveport.dev/openspec/specs/appointment-desk/spec.md
## Purpose
Provide an independent scheduling integration template that recovers local booking actions after lost responses without duplicating their effects.
## Requirements
### Requirement: Replaceable appointment strategies
The sample SHALL offer installed earliest/latest strategies over application-owned UTC slots and validate proposals before authorizing booking.
#### Scenario: Strategy substitution
- **WHEN** the same wish is evaluated by each strategy against available slots
- **THEN** the selected slot reflects that strategy without host code changes
#### Scenario: No available appointment
- **WHEN** no slot satisfies the wish
- **THEN** the application reports no availability without creating a booking
### Requirement: Persisted exact-command recovery
The application SHALL persist the approved command before dispatch and retain terminal outcomes by scoped request identity. Repetition SHALL return the original outcome; changed input for an existing identity SHALL be refused. Lost responses SHALL remain explicitly uncertain until reconciled.
#### Scenario: Worker loss after booking
- **WHEN** a worker dies after the booking commits but before its response arrives and the application reopens its store and repeats the request
- **THEN** the original booking is returned with no duplicate or changed slot
### Requirement: Scoped conflict-safe authority
Booking callbacks SHALL require granted capability and match host-bound tenant/profile and the approved command. Competing requests SHALL not book the same scoped slot twice.
#### Scenario: Concurrent conflicts and customer independence
- **WHEN** requests compete for one slot while a separate customer uses the same plugin artifact
- **THEN** at most one competing request books and the other customer's results remain independent
#### Scenario: Invalid authority
- **WHEN** a callback lacks its grant or changes scope or approved command
- **THEN** no booking is created by that callback
### Requirement: Recoverable bounded local storage
The sample SHALL refuse concurrent coordinators for one store, invalid persisted data and declared capacity violations without resetting valid bookings.
#### Scenario: Store reopen and refusal
- **WHEN** a store is reopened, already owned, malformed or full
- **THEN** valid outcomes remain available or the application refuses explicitly without silently replacing its history
---
## bulk-composition
Source: https://weaveport.dev/openspec/specs/bulk-composition/spec.md
# bulk-composition Specification
## Purpose
Enable bounded, request-owned large-result exchange and externally controlled plugin composition with explicit ownership, cancellation and verified caller delivery.
## Requirements
### Requirement: Request-owned large results
The host SHALL expose immutable request-owned result handles without exposing storage paths to plugins, enforce configured byte/object quotas and reject handles from another request scope.
#### Scenario: Foreign reference
- **WHEN** a different request scope attempts to read a result handle
- **THEN** access is denied regardless of whether tenant names match
#### Scenario: Wrong plugin binding
- **WHEN** a product attempts to map a request result through a plugin session bound to a different tenant
- **THEN** composition rejects the operation before dispatch using host-bound session identity
#### Scenario: Failed or cancelled creation
- **WHEN** result production fails, exceeds its quota or is cancelled
- **THEN** partial output is not published and its reservation is released
### Requirement: Bounded external composition
The product SHALL control step bindings and merge semantics, and the composition layer SHALL execute bounded serial and all-required parallel branches without direct plugin-to-plugin communication.
#### Scenario: Parallel failure
- **WHEN** a required branch fails
- **THEN** sibling work is cancelled and all started operations are awaited before failure is returned
#### Scenario: Large result delivery
- **WHEN** a logical result exceeds the invocation frame limit
- **THEN** the host transfers bounded chunks and can stream the complete result to the caller without materializing it in full
### Requirement: Large-result evidence
Benchmarks SHALL identify result sizes, branch topology, concurrency, complete caller delivery, correctness and resource scope separately from BenchmarkDotNet iteration statistics.
#### Scenario: Validate measured output
- **WHEN** a result-list experiment completes
- **THEN** output bytes and integrity are verified and failed or incomplete runs remain distinguishable
---
## decision-room
Source: https://weaveport.dev/openspec/specs/decision-room/spec.md
## Purpose
Provide a reproducible independent application that teaches plugin integration while the application retains domain state and orchestration.
## Requirements
### Requirement: Explainable finite decision
The example SHALL run two configured participants against three proposals, display their evaluations and knowledge inputs, and select a deterministic winner using application-owned contracts and real plugin workers.
#### Scenario: Complete decision
- **WHEN** the default example runs
- **THEN** both participants evaluate all proposals and the application displays a completed result and persists the committed evaluations
#### Scenario: Configuration changes the decision
- **WHEN** the participant priorities are changed from cost-oriented to benefit-oriented
- **THEN** the selected winner changes predictably without changing host code
### Requirement: Portable strategies
C# and Python strategies SHALL accept the same domain inputs and produce equivalent evaluations for the same bound configuration and knowledge.
#### Scenario: Language substitution
- **WHEN** only a participant's language implementation changes
- **THEN** its evaluation and the final decision remain equivalent
### Requirement: Application-owned recovery
The example SHALL resume from committed evaluations after worker replacement, reject incompatible journal configuration, and prevent simultaneous writers to the same journal.
#### Scenario: Worker stops between steps
- **WHEN** a worker is terminated after the first evaluation is committed
- **THEN** a resumed run completes with the same evaluations and winner as an uninterrupted run
#### Scenario: Incompatible resume
- **WHEN** a saved run is opened with different configuration or plugin artifacts
- **THEN** it is refused without overwriting the saved run
### Requirement: Scoped host knowledge
The example SHALL grant knowledge access explicitly and keep concurrent run/profile knowledge and journal data separate.
#### Scenario: Missing grant
- **WHEN** the strategy requests knowledge without its grant
- **THEN** the application reports an unsuccessful decision, persists no evaluation for that call and exposes no knowledge through that callback
#### Scenario: Concurrent profiles
- **WHEN** independent runs use different profiles and customers concurrently
- **THEN** each decision uses only its configured knowledge and each journal contains only its own evaluations
### Requirement: Run-owned plugin version
The example SHALL resolve a concrete installed plugin version for a new run, persist it, and retain it across subsequent calls, worker replacement and resume. Activation SHALL affect only new runs that have not explicitly selected a version.
#### Scenario: Activation while a run is live
- **WHEN** version 2 becomes the default while a version 1 run remains active and a new run starts
- **THEN** the existing run continues using version 1 and the new run uses version 2, with distinguishable version-specific results
#### Scenario: Resume after activation
- **WHEN** an unfinished version 1 journal is resumed after version 2 becomes the default
- **THEN** the remaining evaluations and replay use version 1, including after worker replacement
#### Scenario: Explicit selection and invalid release
- **WHEN** a new run explicitly selects an installed version
- **THEN** that version is used regardless of the default, and an unavailable or invalid selection is refused without falling back
#### Scenario: Pinned artifact no longer matches
- **WHEN** a selected artifact is unavailable or its recorded content has changed
- **THEN** the run is refused rather than continued with another artifact, and its committed journal is retained
#### Scenario: Independent release artifacts
- **WHEN** another release is installed or altered without changing the selected release or shared runtime
- **THEN** an existing run remains resumable using its pinned artifacts
### Requirement: Versioned multilingual equivalence
The example SHALL identify the actual release of its C# and Python workers and preserve equivalent scoring within each release.
#### Scenario: Both release implementations
- **WHEN** a run substitutes C# for Python or Python for C# within the same release
- **THEN** evaluations and final result remain equivalent and each evaluation identifies the selected release
---
## document-workshop
Source: https://weaveport.dev/openspec/specs/document-workshop/spec.md
## Purpose
Provide an independent document-reader integration template with bounded source transfer, observable reader selection and application-owned complete results.
## Requirements
### Requirement: Installed reader selection
The example SHALL list configured available readers with versions and select an appropriate reader for supported Markdown or plain-text input. Explicit selection SHALL require an installed compatible reader. Automatic fallback SHALL occur only after an explicit content decline.
#### Scenario: Reader substitution and fallback
- **WHEN** the same supported input is imported through the outline or plain reader, or outline content is declined during automatic selection
- **THEN** the selected reader and normalized structure are visible and any fallback is explained
#### Scenario: Missing reader or unsupported media
- **WHEN** the requested reader is unavailable or the media type is unsupported
- **THEN** the import is refused without committing a document
### Requirement: Bounded scoped document transfer
Workers SHALL read captured input through an import-scoped callback without receiving host paths. Requests SHALL validate bound tenant/profile authority, document identity, byte range and transfer limits. Supported input larger than one invocation frame SHALL be processed across multiple reads.
#### Scenario: Large Unicode source
- **WHEN** a supported UTF-8 document exceeds one invocation frame and a code point crosses a read boundary
- **THEN** the complete normalized result retains the decoded content while each transfer remains bounded
#### Scenario: Invalid or revoked read
- **WHEN** a callback lacks its grant, uses another scope, requests an invalid range or exceeds a limit, or follows lease disposal
- **THEN** the callback returns no source bytes
### Requirement: Complete-result ownership
The application SHALL stage extraction results and commit only validated complete output. Cancellation, worker failure, invalid encoding, malformed pages and resource limits SHALL leave no committed partial document and clean up the owned staging area.
#### Scenario: Interrupted extraction
- **WHEN** extraction fails or is cancelled after partial output
- **THEN** no complete document is visible and staging is removed
#### Scenario: Independent concurrent imports
- **WHEN** two tenant/profile imports overlap while one fails
- **THEN** the successful import contains only its own content and can commit independently
### Requirement: Document structure and declared limits
The outline reader SHALL preserve supported heading levels and explicit anchors, and readers SHALL return ordered bounded fragments with metadata identifying the reader and source. Unsupported encoding and limits SHALL fail explicitly rather than truncate successfully.
#### Scenario: Structured document
- **WHEN** a document within the documented grammar and limits completes
- **THEN** its ordered fragments retain the supported headings, anchors and text, and stored metadata identifies the selected reader and source digest
---
## embedded-coordinator
Source: https://weaveport.dev/openspec/specs/embedded-coordinator/spec.md
## Purpose
Provide an application integration template that shares a local plugin budget and exposes bounded admission and shutdown outcomes.
## Requirements
### Requirement: Application-owned bounded admission
The template SHALL share one worker budget across admitted operations, refuse excess work immediately before running its delegate, and keep each accepted operation counted until its owned work and disposal finish.
#### Scenario: Simultaneous scopes and overload
- **WHEN** two customer operations hold the configured capacity and another arrives
- **THEN** the two scopes have distinct workers within one budget and the extra operation is refused without a booking or retained intent
#### Scenario: Scoped failure
- **WHEN** one customer's worker fails after an effect while another uses the same artifact
- **THEN** the other customer can complete and the failed operation retains an uncertain outcome recoverable by its exact request
### Requirement: Observable bounded shutdown
The template SHALL close admission before draining, allow accepted operations a grace interval, request cancellation after that interval, and report whether operations and runtime cleanup actually completed within a bounded observation interval. Repeated shutdown SHALL observe the same shutdown lifecycle.
#### Scenario: Graceful completion
- **WHEN** shutdown begins with an active operation that finishes during grace
- **THEN** new work is refused and shutdown reports clean completion only after operation and worker cleanup
#### Scenario: Uncooperative work and cleanup failure
- **WHEN** accepted work ignores cancellation or cleanup cannot be confirmed
- **THEN** shutdown returns an incomplete or failed diagnostic result, preserves outstanding accounting and exposes eventual completion without declaring side effects failed
#### Scenario: Cancellation after booking
- **WHEN** shutdown cancels an invocation after its booking committed
- **THEN** the caller observes uncertainty and an identical request on a new coordinator returns the original booking
---
## installed-plugin-resolution
Source: https://weaveport.dev/openspec/specs/installed-plugin-resolution/spec.md
## Purpose
Resolve approved local plugin releases to verified content identities that applications can retain across activation and recovery.
## Requirements
### Requirement: Validated installed release
Resolution SHALL validate manifest schema, expected plugin/release/contract, declared entry points and bundle/runtime content before returning a usable installation. Missing or changed selected content SHALL fail without selecting another release.
#### Scenario: Invalid installation
- **WHEN** selected metadata is incompatible, a required file is missing or its digest differs
- **THEN** resolution is refused before plugin dispatch
### Requirement: Exact pinned re-resolution
An application SHALL be able to retain an installation identity and require exactly that identity on recovery independently of the active default.
#### Scenario: Activation during an operation
- **WHEN** a new release is activated while a prior operation exists
- **THEN** new operations can select the new release and the prior operation retains its original release and content identity
#### Scenario: Changed pinned manifest
- **WHEN** a persisted operation resolves a manifest that differs from its recorded identity
- **THEN** recovery fails without overwriting the operation's committed state
### Requirement: Explicit trust boundary
The resolver SHALL distinguish integrity against trusted metadata from executable isolation and SHALL document the requirement for stable deployment files throughout execution.
#### Scenario: Installed startup mismatch
- **WHEN** declared installation content launches a worker advertising a different release
- **THEN** startup is rejected by the existing version guard rather than silently accepting the different worker
---
## internal-distribution
Source: https://weaveport.dev/openspec/specs/internal-distribution/spec.md
## Purpose
Provide a versioned internal distribution that owners can install and exercise independently of the development checkout.
## Requirements
### Requirement: Identifiable delivery contents
The distribution SHALL identify its own version, component versions, qualified source and checksums. Packaging SHALL refuse candidate artifacts that differ from retained qualification evidence.
#### Scenario: Changed qualified artifact
- **WHEN** a required candidate file differs from its retained digest
- **THEN** packaging fails rather than presenting the changed content as qualified
### Requirement: Independent local installation
On the declared supported runtime combination, the distribution SHALL install its local packages and three examples into a new destination without a source checkout or network package download. Diagnostics SHALL check installed delivery content and required runtimes before launching examples.
#### Scenario: Fresh installation
- **WHEN** an owner installs verified delivery contents into a new destination with matching prerequisites
- **THEN** all three examples can execute their verification checks outside the development checkout and an external consumer can restore the included core packages
#### Scenario: Invalid input or existing destination
- **WHEN** delivery checksums or runtime prerequisites do not match, or the destination already exists
- **THEN** installation is refused without overwriting that destination
### Requirement: Preserved application state
The delivery SHALL separate generated application state from shipped content, refuse incomplete installations for normal launch and provide no implicit migration or clearing of existing recovery evidence.
#### Scenario: Existing state on repeated installation
- **WHEN** installation is attempted again against a used destination
- **THEN** the existing application state and recovery evidence remain unchanged
#### Scenario: Interrupted installation
- **WHEN** installation stops before completion
- **THEN** normal application launch refuses the incomplete installation
### Requirement: Resolvable delivered guidance
Relative documentation links in shipped package readmes and distribution guidance SHALL resolve within the delivered artifact. Repository-only references SHALL be identified as external context.
#### Scenario: Missing documentation target
- **WHEN** packaging or verification encounters a missing relative documentation target
- **THEN** validation fails before accepting the delivery
---
## local-package-compatibility
Source: https://weaveport.dev/openspec/specs/local-package-compatibility/spec.md
## Purpose
Make the supported internal local package, API, protocol and author SDK combinations explicit and reject undeclared compatibility before plugin execution.
## Requirements
### Requirement: Exact declared compatibility
Local installation resolution SHALL require supported host API and protocol levels, an exact host package set and a supported author SDK declaration for every entry point. These identities SHALL be independent of artifact release and application contract identity.
#### Scenario: Supported combination
- **WHEN** an installation declares a supported package/API/protocol/SDK combination and matches the requested application contract
- **THEN** either supported artifact release can resolve without treating its release number as the domain or SDK version
#### Scenario: Unsupported or incomplete combination
- **WHEN** compatibility metadata is missing or any declared API, protocol, package set, author SDK or domain contract is unsupported
- **THEN** resolution is refused before dispatch and activation does not replace the previous selector
### Requirement: Reviewable package surface
The internal package check SHALL compare actual packed metadata and a retained core .NET API baseline, and SHALL report mismatches without updating that baseline automatically.
#### Scenario: Package or surface drift
- **WHEN** packed versions/dependencies or the selected public/protected surface differ from the reviewed baseline
- **THEN** verification fails with evidence identifying the mismatch for review
### Requirement: Preserved recovery identity
Adding compatibility metadata SHALL NOT implicitly migrate existing application pins or rewrite stored effects.
#### Scenario: Incompatible pinned operation
- **WHEN** an existing operation's installation declaration becomes incompatible
- **THEN** recovery fails while its persisted application state remains unchanged
---
## mcp-plugins
Source: https://weaveport.dev/openspec/specs/mcp-plugins/spec.md
## Purpose
Allow applications to consume ordinary MCP tools through explicitly selected local plugins while retaining native contracts and host-owned lifecycle policies.
## Requirements
### Requirement: Optional explicit MCP protocol
Local process bindings SHALL retain the native protocol by default and SHALL support explicitly selected MCP 2025-11-25 or 2026-07-28 over stdio. Unsupported configuration or a mismatched server SHALL fail boundedly without fallback or additional unaccounted processes.
#### Scenario: Mixed plugin protocols
- **WHEN** a host binds a native plugin and a supported MCP plugin
- **THEN** both use their configured protocol and independent worker instance under the same host budget
#### Scenario: Incompatible server
- **WHEN** the server does not support the configured revision or tools capability
- **THEN** startup fails within the deadline and cleanup completes or remains accounted for
### Requirement: Bounded tool discovery and invocation
MCP bindings SHALL support tools/list with explicit caller-controlled pagination and tools/call with caller-supplied object arguments. Successful exchanges SHALL preserve complete MCP results, including tool-level isError, without executing content or following returned URLs. Unsupported methods or interaction continuations SHALL be refused explicitly.
#### Scenario: Multiple tools in one process
- **WHEN** a supported server advertises multiple tools and the caller invokes two of them
- **THEN** both execute in the same retained binding process and return their MCP results
#### Scenario: Tool-level failure
- **WHEN** a valid tool result reports isError
- **THEN** that flag and its content remain observable independently of host exchange success
### Requirement: MCP authority and traffic limits
MCP bindings SHALL NOT grant native callbacks, transmit bound context implicitly, or interpret tool metadata as authority. MCP messages SHALL obey a 1 MiB frame limit, depth 32, exact response correlation and unambiguous reserved fields. Notification processing SHALL be bounded per exchange; unsolicited server requests SHALL NOT execute host actions.
#### Scenario: Forged or excessive traffic
- **WHEN** a server sends repeated envelope fields, a wrong response ID, malformed UTF-8, excessive depth, oversized frames or excessive notifications
- **THEN** the invocation fails boundedly and the worker is removed or retained in cleanup accounting
#### Scenario: Attempted host interaction
- **WHEN** an MCP server asks for host sampling, roots, elicitation or native callbacks
- **THEN** no host action or secret disclosure occurs and the unsupported interaction is reported as failure
### Requirement: Shared MCP worker lifecycle
MCP workers SHALL obey existing global and tenant capacity, state retention, pristine assignment, restart, deadline and cleanup policies. Failed or cancelled calls SHALL NOT be replayed automatically. Trusted local execution SHALL NOT be described as a hostile-code sandbox.
#### Scenario: Tenant failure and recovery
- **WHEN** tenant A crashes or hangs while B uses the identical MCP artifact
- **THEN** A fails boundedly, B retains its instance and state, and a subsequent A call uses a fresh worker without replaying the failed call
#### Scenario: Capacity exhaustion
- **WHEN** an MCP binding requires a worker beyond the host or tenant allowance
- **THEN** it receives busy without dispatch and native bindings remain subject to the same shared accounting
#### Scenario: Callback grants supplied
- **WHEN** a consumer attempts to bind an MCP profile with native callback grants
- **THEN** binding fails before registration or process startup
### Requirement: Named MCP invocation methods
Hosting SHALL expose `McpMethods.ListTools` and `McpMethods.CallTool` for callers of `IPluginSession.InvokeAsync`. Their values SHALL remain `tools/list` and `tools/call`; literal-string callers SHALL remain compatible.
#### Scenario: Packed consumer discovers and calls tools
- **WHEN** a consumer uses the named methods from the packed Hosting library
- **THEN** discovery and invocation use the same wire methods and result semantics as literal-string calls
---
## operational-recovery
Source: https://weaveport.dev/openspec/specs/operational-recovery/spec.md
## Purpose
Define fail-closed restart and operator recovery for the trusted native reference deployment without claiming automatic orphan cleanup.
## Requirements
### Requirement: Unclean execution blocks restart
The guarded application SHALL persist an exclusive run marker before starting workers and remove it only after confirmed clean coordinator shutdown. An existing marker, including invalid content, SHALL block new execution without replacing the marker or altering retained booking outcomes.
#### Scenario: Coordinator dies after booking
- **WHEN** the coordinator is killed after a booking commits and before its response
- **THEN** a fresh invocation refuses execution and preserves the original booking and run marker
#### Scenario: Clean run and incomplete cleanup
- **WHEN** a run ends with clean or incomplete coordinator cleanup
- **THEN** its marker is removed only for clean cleanup and a later clean run uses a fresh workspace generation
### Requirement: Explicit supervised recovery
The deployment guide SHALL require verified termination of the old deployment process boundary before archiving an unclean marker and admitting a new run. Recovery SHALL preserve exact stored command and installation identity; old workspace state SHALL never be assigned to new execution. PID-only termination and automatic uncertain-action replay SHALL NOT be presented as safe recovery.
#### Scenario: Supervised fixture recovery
- **WHEN** the isolated test deployment is terminated, its marker is archived and the exact request is repeated
- **THEN** the original booking identity is returned without duplication and a different customer retains independent state
#### Scenario: Unqualified deployment
- **WHEN** descendant containment, filesystem durability or the old deployment's termination cannot be established
- **THEN** the runbook keeps restart gated and identifies the missing qualification instead of claiming automatic recovery
---
## performance-evidence
Source: https://weaveport.dev/openspec/specs/performance-evidence/spec.md
## Purpose
Keep current product performance measurements reproducible, tied to exact artifacts and explicit about their runtime and resource boundaries.
## Requirements
### Requirement: Identifiable current measurements
Benchmark runs SHALL identify the actual core package bytes, optional components, fixture artifacts, source revision, runtime and topology. Functional failures SHALL fail the run rather than contribute successful timing observations.
#### Scenario: Changed package bytes
- **WHEN** a benchmark consumer loads an implementation different from the declared package contents
- **THEN** qualification fails before results are accepted
### Requirement: Complete multilingual paths
The maintained suite SHALL cover embedded and gateway execution of C#, Python and TypeScript providers, including warm small and large results, authorized callbacks and cold lifecycle costs. Reports SHALL name setup and cleanup costs included or excluded.
#### Scenario: Current suite
- **WHEN** the documented complete benchmark command succeeds
- **THEN** all selected combinations have successful complete-result checks and retained timing distributions
### Requirement: Separate request and resource observations
Request-level runs SHALL retain aggregate and per-client outcomes, latency percentiles, duration, concurrency and sampled host/gateway/worker resource scope. Benchmark iteration statistics and host managed allocations SHALL NOT be represented as request tails or total worker memory.
#### Scenario: Unserved or failed client
- **WHEN** any configured client completes no requests or reports errors
- **THEN** the load run fails and retains that client's outcome
#### Scenario: Local topology
- **WHEN** local process and loopback gateway measurements are reported
- **THEN** the report identifies the tested machine and makes no distributed-capacity or hostile-code sandbox claim
---
## plugin-execution
Source: https://weaveport.dev/openspec/specs/plugin-execution/spec.md
## Purpose
Provide observable PoC evidence and contracts for plugin execution in an independent plugin platform.
## Requirements
### Requirement: Packaged multilingual contracts
A consumer SHALL invoke C#, Python and TypeScript implementations through the same packaged host contract.
#### Scenario: Provider replacement
- **WHEN** a consumer invokes the search contract against each language
- **THEN** each result satisfies the same contract without consumer code changes
### Requirement: Host-owned authority
Callbacks SHALL use immutable host-bound tenant identity and explicitly granted capabilities, with bounded calls and cancellation.
#### Scenario: Forged callback context
- **WHEN** a plugin requests another tenant or an ungranted operation
- **THEN** the host refuses unauthorized access and exposes no foreign data
### Requirement: Stable context and recovery
Bindings SHALL retain version and profile selection, while applications own resumable state and external action semantics.
#### Scenario: Restart and replay
- **WHEN** a worker restarts and an application resubmits persisted state or an idempotent action
- **THEN** state processing can continue and an uncertain action is not silently classified as a definite failure
### Requirement: Explicit local transport selection
A trusted Linux deployment SHALL be able to select a private local transport while preserving the packaged C#, Python and TypeScript invocation and callback contracts. An incompatible transport configuration or worker SHALL fail boundedly without silent fallback.
#### Scenario: Equivalent operations
- **WHEN** the same supported plugin is invoked through either configured transport
- **THEN** its successful results, bound context and authorized callbacks satisfy the same contract
#### Scenario: Invalid local endpoint
- **WHEN** the configured local transport cannot establish a compatible worker channel
- **THEN** startup fails within its deadline and owned resources are removed or remain explicitly quarantined
### Requirement: Unambiguous protocol envelopes
The host SHALL reject repeated reserved fields in worker protocol envelopes, including escaped spellings of the same name, and SHALL reject unsupported or non-integral ready versions as protocol failures. Plugin payload and result contents SHALL remain application-owned JSON.
#### Scenario: Ambiguous identity
- **WHEN** a worker repeats a reserved envelope field such as invocation identity, operation or payload
- **THEN** the host terminates that worker invocation with a protocol error before executing a callback from that envelope
#### Scenario: Malformed ready version
- **WHEN** a worker advertises a fractional, out-of-range or wrongly typed protocol version
- **THEN** startup fails as a bounded protocol error and its worker is cleaned up without disrupting another customer
#### Scenario: Opaque result contents
- **WHEN** a valid result envelope contains application-owned JSON
- **THEN** envelope validation does not interpret its nested fields as host authority
### Requirement: Explicit trusted local execution
A consumer SHALL be able to select local process execution without Docker for the supported C#, Python and TypeScript fixtures. Local execution SHALL require explicit trusted-code acknowledgement and SHALL not be advertised as a hostile-code sandbox.
#### Scenario: Docker unavailable
- **WHEN** a trusted local fixture is invoked with Docker unavailable to the consuming application
- **THEN** invocation and authorized callbacks complete without requiring Docker
#### Scenario: Required protection unavailable
- **WHEN** a consumer requires filesystem or network confinement or hard worker resource ceilings that the selected adapter does not provide
- **THEN** binding and prewarming are rejected before launching a worker, without fallback
### Requirement: Explicit native channel selection
Trusted local consumers SHALL be able to select a private Unix-socket channel for the supported native fixtures without requiring Docker. Channel selection SHALL preserve bound authority, frame limits and fresh worker ownership, and SHALL NOT add a sandbox guarantee.
#### Scenario: Equivalent native channels
- **WHEN** a supported trusted fixture runs with either native channel
- **THEN** contracts, authorized callbacks, crash/cancellation recovery and customer-local state satisfy the same binding contract
#### Scenario: Incompatible native channel
- **WHEN** the selected channel cannot establish a compatible worker connection
- **THEN** startup fails boundedly, owned endpoints are removed or remain accounted for, and no fallback occurs
---
## plugin-sdk
Source: https://weaveport.dev/openspec/specs/plugin-sdk/spec.md
# plugin-sdk Specification
## Purpose
Enable plugin authors to implement portable functions and result streams through language SDKs while the host owns transport and customer authority.
## Requirements
### Requirement: Transport-independent multilingual authoring
C#, Python and TypeScript SDKs SHALL let providers register unary functions and asynchronous result streams without writing transport or envelope code. The same built example artifact SHALL run with a local host or a separate worker-host process.
#### Scenario: Unchanged provider deployment
- **WHEN** an SDK example is invoked locally and through the worker-host gateway
- **THEN** the same plugin artifact produces equivalent complete results and authorized callbacks without provider source changes
### Requirement: Bounded result-stream lifecycle
SDK clients SHALL expose incremental results with bounded transport batches, reject oversized items and apply a total stream limit. Cancellation, early consumer exit and worker failure SHALL release stream state or stop the owned worker without reporting partial output as complete success.
#### Scenario: Early consumer exit
- **WHEN** a caller stops enumerating before completion
- **THEN** owned enumeration state is disposed and the binding can serve a subsequent call without exposing the abandoned stream
#### Scenario: Interrupted or oversized output
- **WHEN** production fails, is cancelled or exceeds a configured bound
- **THEN** the caller observes failure or cancellation, rather than successful completion of a truncated stream
#### Scenario: Unresponsive gateway
- **WHEN** a gateway accepts a connection but does not complete a call or stream
- **THEN** the remote client terminates within its configured timeout plus bounded stream cleanup rather than waiting indefinitely
#### Scenario: Repeated binding use with bounded transport retention
- **WHEN** a remote binding serves repeated and concurrent operations within its call budget
- **THEN** completed operations do not accumulate an unbounded number of retained transport sessions, replies remain associated with their caller, and cancelled queued calls are not dispatched
#### Scenario: Transport reuse after abandoned enumeration
- **WHEN** a caller abandons a result stream and invokes another operation on the same binding
- **THEN** the next operation cannot receive leftover items from the abandoned enumeration
### Requirement: Shared host authority
Both SDK deployment paths SHALL use the existing host-bound identity, callback grants and worker lifecycle. Gateway credentials SHALL select a preconfigured binding; request payloads SHALL NOT choose tenant authority or executable paths.
#### Scenario: Foreign authority attempt
- **WHEN** a plugin supplies a foreign tenant value or calls an ungranted host capability, or a gateway caller lacks a valid binding credential
- **THEN** no foreign data is returned and another customer's binding remains usable
#### Scenario: Revoked binding with an open transport
- **WHEN** the trusted host revokes a binding after its transport has been opened
- **THEN** further operations on that transport are denied and another binding remains usable
### Requirement: Complete SDK-path evidence
SDK benchmarks SHALL execute the same language artifacts and complete caller contracts in both topologies, distinguish setup from warm work and record gateway resources separately from plugin worker resources. Evidence SHALL identify tested platforms and trusted-code limitations.
#### Scenario: SDK comparison
- **WHEN** the complete SDK paths are measured
- **THEN** results include correctness, artifact identity, language, topology, payload size and resource scope without describing a loopback test as distributed or sandbox qualification
### Requirement: Author-declared artifact version
Each language SDK SHALL allow the plugin author to declare the artifact version sent at startup, retaining version 1 for existing callers that omit it. The host SHALL continue to reject mismatched artifact versions before invoking plugin functions. Protocol version SHALL remain independent of artifact version.
#### Scenario: Declared version
- **WHEN** an author declares version 2 and the host binds version 2
- **THEN** startup succeeds and ordinary calls execute through the SDK
#### Scenario: Mismatched version
- **WHEN** the declared artifact version differs from the host's expected version
- **THEN** startup fails before a domain function is dispatched
#### Scenario: Existing default and invalid declaration
- **WHEN** an author omits the version or supplies an empty declaration
- **THEN** omission preserves version 1 and an empty declaration is refused
### Requirement: Complete gateway shutdown
Gateway disposal SHALL atomically close new registration and stream admission, revoke all credentials and attempt cleanup of every owned client even when another cleanup fails. Repeated disposal SHALL observe the same completion.
#### Scenario: Multiple cleanup failures
- **WHEN** multiple registered clients fail during disposal
- **THEN** every client is attempted, all credentials are invalid and failures are aggregated
#### Scenario: Registration races shutdown
- **WHEN** registration or stream admission races disposal
- **THEN** it is either admitted before shutdown and included in cleanup or rejected
### Requirement: Safe local client shutdown
Local client disposal SHALL reject new operations, cancel outstanding work and attempt owned binding cleanup once. It SHALL release owned cancellation resources safely without requiring a suspended stream consumer to resume enumeration. Concurrent and repeated disposal SHALL observe the same cleanup outcome; late enumeration SHALL observe cancellation without dispatching further plugin work.
#### Scenario: Active local call during disposal
- **WHEN** a local call races disposal
- **THEN** it is either admitted before shutdown and cancelled or refused without dispatch, without accessing a disposed cancellation source
#### Scenario: Suspended stream consumer
- **WHEN** disposal starts while a consumer is suspended after receiving a stream item
- **THEN** owned binding cleanup can complete without consumer resumption and later enumeration observes cancellation without further dispatch
#### Scenario: Binding cleanup throws
- **WHEN** the owned binding fails during disposal
- **THEN** the failure remains observable to repeated disposal callers and independent cancellation resource release is still attempted
---
## runtime-diagnostics
Source: https://weaveport.dev/openspec/specs/runtime-diagnostics/spec.md
## Purpose
Allow application owners to diagnose runtime failures without exposing plugin data or configuring global logging from the library.
## Requirements
### Requirement: Optional safe operational events
The host SHALL accept caller-owned optional logging and emit stable event identifiers for startup, callback, invocation, maintenance and cleanup failures. Default events SHALL exclude payloads, configuration, credentials, raw stderr and exception messages.
#### Scenario: Failure with sensitive input
- **WHEN** a failure occurs with secrets in input or exception messages and logging is enabled
- **THEN** the event identifies the failure stage and type without containing those secrets
#### Scenario: Logging omitted
- **WHEN** the caller uses the existing host constructor
- **THEN** the library requires no logging configuration and retains existing invocation behavior
### Requirement: Pending cleanup age
The coordinator snapshot SHALL expose the age in seconds of the oldest still-pending worker removal, measured with the injected operational clock from first quarantine entry. Retries SHALL retain that age; confirmed removal SHALL stop contributing. No pending removal SHALL report zero age. Cleanup reservations and assignment restrictions SHALL remain unchanged.
#### Scenario: Overlapping short removals
- **WHEN** different short worker removals overlap continuously
- **THEN** the reported oldest age follows the oldest currently pending removal rather than the duration of the aggregate nonzero count
#### Scenario: Retried uncertain removal
- **WHEN** removal fails and is retried
- **THEN** its age continues from the original quarantine entry and its capacity remains reserved until confirmed removal
### Requirement: Safe host admission reasons
When caller-owned logging is enabled, host admission refusals SHALL identify the responsible gate using fixed reason codes without payloads, credentials or exception messages. Rejection SHALL retain existing pre-dispatch behavior and limits.
#### Scenario: Simultaneous start ceiling
- **WHEN** all configured worker-start slots are occupied and another cold invocation arrives
- **THEN** it is rejected before dispatch and logging identifies the concurrent-start gate
---
## tenant-isolation
Source: https://weaveport.dev/openspec/specs/tenant-isolation/spec.md
## Purpose
Define tested tenant boundaries across Docker and cooperative trusted local execution. Private endpoint mount and memory-exhaustion scenarios apply to the Docker profiles; native process execution is not a hostile-code sandbox.
## Requirements
### Requirement: Independent tenant execution
The tested Docker execution profile SHALL isolate worker state, configuration and writable files between tenants using the same artifact version. Trusted local execution SHALL preserve cooperative instance state and bound context separation, without promising hostile same-user confinement or memory-fault isolation.
#### Scenario: Failure of tenant A
- **WHEN** A crashes, exceeds memory, hangs or is deactivated in the tested Docker profile while B calls the same plugin
- **THEN** B has no induced invocation failures, instance restart or state loss
### Requirement: Bounded execution
The host SHALL bound frames, callbacks, invocation deadlines, concurrent admissions and resource reservations per execution instance. Hard worker resource ceilings SHALL depend on the selected execution profile and SHALL NOT be claimed for trusted local execution.
#### Scenario: Flood and ignored cancellation
- **WHEN** A floods admission or ignores cancellation
- **THEN** excess work is rejected or terminated without unbounded queuing and B remains callable
### Requirement: Controlled lifecycle
The host SHALL permit isolated restart and disposal and reject calls to disabled bindings.
#### Scenario: Scoped restart
- **WHEN** A restarts its binding
- **THEN** B retains its process and its state
### Requirement: No used-worker reassignment
Used execution environments SHALL be destroyed rather than returned to a customer-shared pristine reserve. Fresh cooperative state SHALL NOT be presented as a filesystem sandbox against hostile same-user native code.
#### Scenario: Customer replacement
- **WHEN** cooperative fixture A writes private markers and secrets into its instance workspace and releases it before cooperative fixture B uses the identical plugin
- **THEN** B's fresh process and instance workspace contain none of A's markers and callbacks use only B's bound authority
### Requirement: Expired callback scope
Nested plugin invocations from a completed or cancelled callback scope SHALL be denied even when the nested target has the same tenant identifier.
#### Scenario: Late nested callback
- **WHEN** a callback resumes after its originating invocation ended and invokes another binding
- **THEN** the host denies the nested invocation without dispatch
### Requirement: Private worker transport endpoints
A worker using the local transport SHALL receive access only to its own invocation endpoint, without a writable shared host directory or Docker control endpoint. Removal uncertainty SHALL retain endpoint ownership and capacity accounting.
#### Scenario: Inspect endpoint exposure
- **WHEN** two customers run the same plugin over local endpoints
- **THEN** each worker can communicate only through its assigned endpoint and cannot create files in its read-only endpoint mount or access the other worker's endpoint
#### Scenario: Fault and replacement
- **WHEN** A fails or its removal cannot be confirmed
- **THEN** B retains its channel and authority, and A's endpoint is not reused for another customer
---
## worker-lifecycle
Source: https://weaveport.dev/openspec/specs/worker-lifecycle/spec.md
## Purpose
Define verified local coordinator behavior for pristine worker assignment, bounded tenant reservations and release across Docker and trusted local profiles. Enforced resource and security boundaries depend on the selected profile; distributed scheduling and kernel/engine isolation failures are outside this tested surface.
## Requirements
### Requirement: Shared pristine reserve
A coordinator SHALL hold a bounded reserve of customer-unassigned workers keyed by resolved artifact or trusted local launch profile, version and execution reservations and SHALL assign each worker exclusively at most once. Local executable/script stability SHALL be an explicit trusted-deployment prerequisite rather than an immutable-image claim.
#### Scenario: Two customers acquire the same plugin
- **WHEN** A and B concurrently acquire workers from the shared reserve
- **THEN** they receive distinct execution environments with their own bound context and no prior customer's state
### Requirement: Accounted execution capacity
The coordinator SHALL bound reserved worker count and configured memory reservations both globally and per tenant, simultaneous launches and pristine residency; cleanup-uncertain workers SHALL remain reserved and unavailable for assignment. Whether a memory reservation is also an enforced worker ceiling SHALL be identified by the execution profile.
#### Scenario: Capacity exhausted
- **WHEN** an invocation requires a new worker but the configured capacity is reserved
- **THEN** it is rejected without dispatch and capacity is released only after confirmed worker removal
#### Scenario: One tenant exhausts its quota
- **WHEN** A reserves its tenant worker-count or memory allowance while global capacity remains
- **THEN** further A allocations are rejected without dispatch and B can still allocate within its own allowance
### Requirement: Explicit idle policy
A binding SHALL retain its process state by default and SHALL permit opt-in release of idle execution environments without revoking the binding.
#### Scenario: Idle release and reuse
- **WHEN** an opted-in binding exceeds its idle duration while no invocation is active
- **THEN** its used environment is destroyed and its next invocation obtains a fresh environment with the original immutable binding
#### Scenario: Stateful default
- **WHEN** a binding has no idle-release policy
- **THEN** maintenance does not discard its process state
### Requirement: Bounded host registration lifetime
Disposed bindings SHALL be removed from host registration, while shared callback admission SHALL remain effective until outstanding callbacks complete.
#### Scenario: Detached callback survives disposal
- **WHEN** a callback ignores cancellation and its binding is disposed
- **THEN** a new binding for the same tenant cannot bypass the existing callback limit
### Requirement: Adapter-aware local lifecycle
Trusted local workers SHALL share binding authority, admission, pristine assignment and idle/restart/disposal policies, while reports and APIs SHALL distinguish scheduling memory reservations from enforced resource ceilings. Used local workers SHALL never be assigned to another customer.
#### Scenario: Trusted replacement
- **WHEN** a cooperative local worker writes instance state and is released before another customer binds the same fixture
- **THEN** the replacement receives a fresh process and workspace with its own bound context
#### Scenario: Local cleanup limit
- **WHEN** a local worker is stopped or cleanup fails
- **THEN** root-process termination is bounded and uncertain cleanup retains its reservation, without claiming kernel-enforced containment of escaped descendants
### Requirement: Exceptional lifecycle completion
Invocation setup failures SHALL release acquired admission. Unsupported invocation deadlines SHALL be rejected before binding registration. Cancellation callback failures SHALL NOT prevent independent worker cleanup and binding deregistration; outstanding callbacks SHALL retain admission until actual completion.
#### Scenario: Setup throws before dispatch
- **WHEN** invocation setup throws after admission
- **THEN** a subsequent invocation and binding disposal can acquire admission
#### Scenario: Cancellation callback throws
- **WHEN** disposal encounters a throwing cancellation callback
- **THEN** worker cleanup and deregistration are attempted and cleanup errors are reported after those attempts
### Requirement: Safe shutdown resource release
Coordinator and binding shutdown SHALL close admission before releasing owned cancellation resources, request cancellation of admitted work and release those resources after operations using them finish. Concurrent and repeated disposal SHALL observe one shutdown outcome. Cleanup failures SHALL remain observable and SHALL NOT skip independent release attempts or erase uncertain worker reservations.
#### Scenario: Worker startup races shutdown
- **WHEN** shutdown begins while an admitted worker is starting
- **THEN** startup is cancelled and accounted for before its owned cancellation resources are released, and no worker is published for subsequent use
#### Scenario: Repeated disposal after a cleanup error
- **WHEN** concurrent disposal callers encounter a throwing cancellation callback or failed worker cleanup
- **THEN** callers observe the same completed shutdown outcome, independent release attempts still run and uncertain worker reservations remain visible
#### Scenario: Another binding remains usable
- **WHEN** tenant A disposes a binding while tenant B uses the same plugin artifact and version
- **THEN** B retains its independent execution and callback authority, and A's detached callbacks retain admission until actual completion
### Requirement: Trusted adapter setup
Native Unix sockets SHALL use exclusively created owner-only temporary directories. Docker execution SHALL use an absolute executable selected by the trusted deployment, without resolving it through the process PATH.
#### Scenario: Private socket allocation
- **WHEN** multiple native Unix endpoints are created
- **THEN** each owns a distinct private directory and releases it when disposed, including before listening
#### Scenario: Docker executable override
- **WHEN** a deployment supplies a relative Docker executable path
- **THEN** setup rejects it before executing any command
---
## Reviewed .NET public API
Source: https://weaveport.dev/compatibility/public-api.txt
```text
# Reviewed .NET core API surface: signatures, parameter names and defaults
type WeavePort.Abstractions.HostCall : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Abstractions.HostCall]
Constructor Void .ctor(WeavePort.Abstractions.PluginContext, System.String, System.String, System.Text.Json.JsonElement, System.String) [Public] (Context, InvocationId, Operation, Payload, TraceId)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Abstractions.HostCall) [Public, Final, Virtual] (other)
Method Boolean op_Equality(WeavePort.Abstractions.HostCall, WeavePort.Abstractions.HostCall) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Abstractions.HostCall, WeavePort.Abstractions.HostCall) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_InvocationId() [Public] ()
Method System.String get_Operation() [Public] ()
Method System.String get_TraceId() [Public] ()
Method System.Text.Json.JsonElement get_Payload() [Public] ()
Method Void Deconstruct(WeavePort.Abstractions.PluginContext ByRef, System.String ByRef, System.String ByRef, System.Text.Json.JsonElement ByRef, System.String ByRef) [Public] (Context, InvocationId, Operation, Payload, TraceId)
Method Void set_Context(WeavePort.Abstractions.PluginContext) [Public] (value)
Method Void set_InvocationId(System.String) [Public] (value)
Method Void set_Operation(System.String) [Public] (value)
Method Void set_Payload(System.Text.Json.JsonElement) [Public] (value)
Method Void set_TraceId(System.String) [Public] (value)
Method WeavePort.Abstractions.HostCall $() [Public] ()
Method WeavePort.Abstractions.PluginContext get_Context() [Public] ()
Property System.String InvocationId
Property System.String Operation
Property System.String TraceId
Property System.Text.Json.JsonElement Payload
Property WeavePort.Abstractions.PluginContext Context
type WeavePort.Abstractions.IHostCallbacks : [Public, ClassSemanticsMask, Abstract]
Method System.Threading.Tasks.ValueTask`1[System.Text.Json.JsonElement] InvokeAsync(WeavePort.Abstractions.HostCall, System.Threading.CancellationToken) [Public, Virtual, Abstract] (call, cancellationToken)
type WeavePort.Abstractions.IPluginSession : [Public, ClassSemanticsMask, Abstract]
implements System.IAsyncDisposable
Method System.String get_Instance() [Public, Virtual, Abstract] ()
Method System.String get_Tenant() [Public, Virtual, Abstract] ()
Method System.Threading.Tasks.Task RestartAsync(System.Threading.CancellationToken) [Public, Virtual, Abstract] (cancellationToken=null)
Method System.Threading.Tasks.Task`1[WeavePort.Abstractions.InvocationResult] InvokeAsync(System.String, System.Text.Json.JsonElement, System.Threading.CancellationToken) [Public, Virtual, Abstract] (operation, payload, cancellationToken=null)
Property System.String Instance
Property System.String Tenant
type WeavePort.Abstractions.InvocationResult : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Abstractions.InvocationResult]
Constructor Void .ctor(System.String, System.Text.Json.JsonElement, System.String, Double, Boolean) [Public] (Status, Value, Instance, ElapsedMs, MayHaveExecuted=False)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Abstractions.InvocationResult) [Public, Final, Virtual] (other)
Method Boolean get_MayHaveExecuted() [Public] ()
Method Boolean op_Equality(WeavePort.Abstractions.InvocationResult, WeavePort.Abstractions.InvocationResult) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Abstractions.InvocationResult, WeavePort.Abstractions.InvocationResult) [Public, Static] (left, right)
Method Double get_ElapsedMs() [Public] ()
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_Instance() [Public] ()
Method System.String get_Status() [Public] ()
Method System.Text.Json.JsonElement get_Value() [Public] ()
Method Void Deconstruct(System.String ByRef, System.Text.Json.JsonElement ByRef, System.String ByRef, Double ByRef, Boolean ByRef) [Public] (Status, Value, Instance, ElapsedMs, MayHaveExecuted)
Method Void set_ElapsedMs(Double) [Public] (value)
Method Void set_Instance(System.String) [Public] (value)
Method Void set_MayHaveExecuted(Boolean) [Public] (value)
Method Void set_Status(System.String) [Public] (value)
Method Void set_Value(System.Text.Json.JsonElement) [Public] (value)
Method WeavePort.Abstractions.InvocationResult $() [Public] ()
Property Boolean MayHaveExecuted
Property Double ElapsedMs
Property System.String Instance
Property System.String Status
Property System.Text.Json.JsonElement Value
type WeavePort.Abstractions.PluginContext : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Abstractions.PluginContext]
Constructor Void .ctor(System.String, System.String, System.String, System.String, System.Text.Json.JsonElement) [Public] (Tenant, Plugin, Version, Profile, Configuration)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Abstractions.PluginContext) [Public, Final, Virtual] (other)
Method Boolean op_Equality(WeavePort.Abstractions.PluginContext, WeavePort.Abstractions.PluginContext) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Abstractions.PluginContext, WeavePort.Abstractions.PluginContext) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_Plugin() [Public] ()
Method System.String get_Profile() [Public] ()
Method System.String get_Tenant() [Public] ()
Method System.String get_Version() [Public] ()
Method System.Text.Json.JsonElement get_Configuration() [Public] ()
Method Void Deconstruct(System.String ByRef, System.String ByRef, System.String ByRef, System.String ByRef, System.Text.Json.JsonElement ByRef) [Public] (Tenant, Plugin, Version, Profile, Configuration)
Method Void set_Configuration(System.Text.Json.JsonElement) [Public] (value)
Method Void set_Plugin(System.String) [Public] (value)
Method Void set_Profile(System.String) [Public] (value)
Method Void set_Tenant(System.String) [Public] (value)
Method Void set_Version(System.String) [Public] (value)
Method WeavePort.Abstractions.PluginContext $() [Public] ()
Property System.String Plugin
Property System.String Profile
Property System.String Tenant
Property System.String Version
Property System.Text.Json.JsonElement Configuration
type WeavePort.Hosting.DockerProfile : WeavePort.Hosting.ExecutionProfile [Public, Sealed]
implements System.IEquatable`1[WeavePort.Hosting.DockerProfile]
implements System.IEquatable`1[WeavePort.Hosting.ExecutionProfile]
Constructor Void .ctor(System.String, System.String, Int32, Double, System.Nullable`1[System.TimeSpan], System.Nullable`1[System.TimeSpan], WeavePort.Hosting.UnixSocketTransport) [Public] (Image, Context=null, MemoryMiB=256, CpuCount=0.5, Timeout=null, IdleTimeout=null, SocketTransport=null)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.DockerProfile) [Public, Final, Virtual] (other)
Method Boolean Equals(WeavePort.Hosting.ExecutionProfile) [Public, Final, Virtual] (other)
Method Boolean PrintMembers(System.Text.StringBuilder) [Family, Virtual] (builder)
Method Boolean op_Equality(WeavePort.Hosting.DockerProfile, WeavePort.Hosting.DockerProfile) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.DockerProfile, WeavePort.Hosting.DockerProfile) [Public, Static] (left, right)
Method Double get_CpuCount() [Public] ()
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_Context() [Public] ()
Method System.String get_DockerExecutable() [Public] ()
Method System.String get_Image() [Public] ()
Method System.Type get_EqualityContract() [Family, Virtual] ()
Method Void Deconstruct(System.String ByRef, System.String ByRef, Int32 ByRef, Double ByRef, System.Nullable`1[System.TimeSpan] ByRef, System.Nullable`1[System.TimeSpan] ByRef, WeavePort.Hosting.UnixSocketTransport ByRef) [Public] (Image, Context, MemoryMiB, CpuCount, Timeout, IdleTimeout, SocketTransport)
Method Void set_Context(System.String) [Public] (value)
Method Void set_CpuCount(Double) [Public] (value)
Method Void set_DockerExecutable(System.String) [Public] (value)
Method Void set_Image(System.String) [Public] (value)
Method Void set_SocketTransport(WeavePort.Hosting.UnixSocketTransport) [Public] (value)
Method WeavePort.Hosting.DockerProfile $() [Public, Virtual] ()
Method WeavePort.Hosting.ExecutionProtections get_Protection() [Public, Virtual] ()
Method WeavePort.Hosting.UnixSocketTransport get_SocketTransport() [Public] ()
Property Double CpuCount
Property System.String Context
Property System.String DockerExecutable
Property System.String Image
Property System.Type EqualityContract
Property WeavePort.Hosting.ExecutionProtections Protection
Property WeavePort.Hosting.UnixSocketTransport SocketTransport
type WeavePort.Hosting.ExecutionProfile : System.Object [Public, Abstract]
implements System.IEquatable`1[WeavePort.Hosting.ExecutionProfile]
Constructor Void .ctor(Int32, System.Nullable`1[System.TimeSpan], System.Nullable`1[System.TimeSpan]) [Family] (MemoryMiB, Timeout, IdleTimeout)
Constructor Void .ctor(WeavePort.Hosting.ExecutionProfile) [Family] (original)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.ExecutionProfile) [Public, Virtual] (other)
Method Boolean PrintMembers(System.Text.StringBuilder) [Family, Virtual] (builder)
Method Boolean op_Equality(WeavePort.Hosting.ExecutionProfile, WeavePort.Hosting.ExecutionProfile) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.ExecutionProfile, WeavePort.Hosting.ExecutionProfile) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method Int32 get_MemoryMiB() [Public] ()
Method System.Nullable`1[System.TimeSpan] get_IdleTimeout() [Public] ()
Method System.Nullable`1[System.TimeSpan] get_Timeout() [Public] ()
Method System.String ToString() [Public, Virtual] ()
Method System.Type get_EqualityContract() [Family, Virtual] ()
Method Void Deconstruct(Int32 ByRef, System.Nullable`1[System.TimeSpan] ByRef, System.Nullable`1[System.TimeSpan] ByRef) [Public] (MemoryMiB, Timeout, IdleTimeout)
Method Void set_IdleTimeout(System.Nullable`1[System.TimeSpan]) [Public] (value)
Method Void set_MemoryMiB(Int32) [Public] (value)
Method Void set_Timeout(System.Nullable`1[System.TimeSpan]) [Public] (value)
Method WeavePort.Hosting.ExecutionProfile $() [Public, Virtual, Abstract] ()
Method WeavePort.Hosting.ExecutionProtections get_Protection() [Public, Virtual, Abstract] ()
Property Int32 MemoryMiB
Property System.Nullable`1[System.TimeSpan] IdleTimeout
Property System.Nullable`1[System.TimeSpan] Timeout
Property System.Type EqualityContract
Property WeavePort.Hosting.ExecutionProtections Protection
type WeavePort.Hosting.ExecutionProtections : System.Enum [Public, Sealed]
implements System.IComparable
implements System.IConvertible
implements System.IFormattable
implements System.ISpanFormattable
Field Int32 value__
Field WeavePort.Hosting.ExecutionProtections DisabledNetwork=2
Field WeavePort.Hosting.ExecutionProtections HardResourceLimits=4
Field WeavePort.Hosting.ExecutionProtections None=0
Field WeavePort.Hosting.ExecutionProtections RestrictedFileSystem=1
type WeavePort.Hosting.InstallationIdentity : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Hosting.InstallationIdentity]
Constructor Void .ctor(System.String, System.String, System.String, System.String) [Public] (Plugin, Version, Contract, Digest)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.InstallationIdentity) [Public, Final, Virtual] (other)
Method Boolean op_Equality(WeavePort.Hosting.InstallationIdentity, WeavePort.Hosting.InstallationIdentity) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.InstallationIdentity, WeavePort.Hosting.InstallationIdentity) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_Contract() [Public] ()
Method System.String get_Digest() [Public] ()
Method System.String get_Plugin() [Public] ()
Method System.String get_Version() [Public] ()
Method Void Deconstruct(System.String ByRef, System.String ByRef, System.String ByRef, System.String ByRef) [Public] (Plugin, Version, Contract, Digest)
Method Void set_Contract(System.String) [Public] (value)
Method Void set_Digest(System.String) [Public] (value)
Method Void set_Plugin(System.String) [Public] (value)
Method Void set_Version(System.String) [Public] (value)
Method WeavePort.Hosting.InstallationIdentity $() [Public] ()
Property System.String Contract
Property System.String Digest
Property System.String Plugin
Property System.String Version
type WeavePort.Hosting.InstalledPlugin : System.Object [Public, Sealed]
Method System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.String] get_EntryPoints() [Public] ()
Method WeavePort.Hosting.InstallationIdentity get_Identity() [Public] ()
Property System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.String] EntryPoints
Property WeavePort.Hosting.InstallationIdentity Identity
type WeavePort.Hosting.InstalledPluginCatalog : System.Object [Public, Sealed]
Constructor Void .ctor(System.String, System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.String]) [Public] (releases, runtimeFiles)
Method System.String ReadSelection(System.String) [Public, Static] (path)
Method Void Activate(System.String, System.String, System.String, System.String) [Public] (selector, plugin, version, contract)
Method WeavePort.Hosting.InstalledPlugin Resolve(System.String, System.String, System.String, WeavePort.Hosting.InstallationIdentity) [Public] (plugin, version, contract, pinned=null)
type WeavePort.Hosting.McpMethods : System.Object [Public, Abstract, Sealed]
Field System.String CallTool="tools/call"
Field System.String ListTools="tools/list"
type WeavePort.Hosting.PluginHost : System.Object [Public, Sealed]
implements System.IAsyncDisposable
Constructor Void .ctor(Int32, WeavePort.Hosting.WorkerPoolOptions, System.TimeProvider) [Public] (maximumCallsPerTenant=4, options=null, timeProvider=null)
Constructor Void .ctor(Microsoft.Extensions.Logging.ILogger`1[WeavePort.Hosting.PluginHost], Int32, WeavePort.Hosting.WorkerPoolOptions, System.TimeProvider) [Public] (logger, maximumCallsPerTenant=4, options=null, timeProvider=null)
Method System.Threading.Tasks.Task MaintainAsync(System.Threading.CancellationToken) [Public] (cancellationToken=null)
Method System.Threading.Tasks.Task PrewarmAsync(WeavePort.Hosting.ExecutionProfile, System.String, Int32, WeavePort.Hosting.ExecutionProtections, System.Threading.CancellationToken) [Public] (profile, version, count, requiredProtection=0, cancellationToken=null)
Method System.Threading.Tasks.Task`1[WeavePort.Abstractions.IPluginSession] BindAsync(WeavePort.Abstractions.PluginContext, WeavePort.Hosting.ExecutionProfile, WeavePort.Abstractions.IHostCallbacks, System.Collections.Generic.IEnumerable`1[System.String], WeavePort.Hosting.ExecutionProtections, System.Threading.CancellationToken) [Public] (context, profile, callbacks, grants, requiredProtection=0, cancellationToken=null)
Method System.Threading.Tasks.ValueTask DisposeAsync() [Public, Final, Virtual] ()
Method WeavePort.Hosting.WorkerPoolSnapshot get_Snapshot() [Public] ()
Property WeavePort.Hosting.WorkerPoolSnapshot Snapshot
type WeavePort.Hosting.ProcessProfile : WeavePort.Hosting.ExecutionProfile [Public, Sealed]
implements System.IEquatable`1[WeavePort.Hosting.ExecutionProfile]
implements System.IEquatable`1[WeavePort.Hosting.ProcessProfile]
Constructor Void .ctor(System.String, System.Collections.Generic.IEnumerable`1[System.String], Boolean, System.String, Int32, System.Nullable`1[System.TimeSpan], System.Nullable`1[System.TimeSpan]) [Public] (executable, arguments, trustedCode=False, workspaceRoot=null, reservedMemoryMiB=256, timeout=null, idleTimeout=null)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.ExecutionProfile) [Public, Final, Virtual] (other)
Method Boolean Equals(WeavePort.Hosting.ProcessProfile) [Public, Final, Virtual] (other)
Method Boolean PrintMembers(System.Text.StringBuilder) [Family, Virtual] (builder)
Method Boolean get_TrustedCode() [Public] ()
Method Boolean get_UseUnixSocket() [Public] ()
Method Boolean op_Equality(WeavePort.Hosting.ProcessProfile, WeavePort.Hosting.ProcessProfile) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.ProcessProfile, WeavePort.Hosting.ProcessProfile) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.Nullable`1[System.Int32] get_SocketBufferBytes() [Public] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_Executable() [Public] ()
Method System.String get_WorkspaceRoot() [Public] ()
Method System.String[] get_Arguments() [Public] ()
Method System.Type get_EqualityContract() [Family, Virtual] ()
Method Void set_Executable(System.String) [Public] (value)
Method Void set_Protocol(WeavePort.Hosting.ProcessProtocol) [Public] (value)
Method Void set_SocketBufferBytes(System.Nullable`1[System.Int32]) [Public] (value)
Method Void set_TrustedCode(Boolean) [Public] (value)
Method Void set_UseUnixSocket(Boolean) [Public] (value)
Method Void set_WorkspaceRoot(System.String) [Public] (value)
Method WeavePort.Hosting.ExecutionProtections get_Protection() [Public, Virtual] ()
Method WeavePort.Hosting.ProcessProfile $() [Public, Virtual] ()
Method WeavePort.Hosting.ProcessProtocol get_Protocol() [Public] ()
Property Boolean TrustedCode
Property Boolean UseUnixSocket
Property System.Nullable`1[System.Int32] SocketBufferBytes
Property System.String Executable
Property System.String WorkspaceRoot
Property System.String[] Arguments
Property System.Type EqualityContract
Property WeavePort.Hosting.ExecutionProtections Protection
Property WeavePort.Hosting.ProcessProtocol Protocol
type WeavePort.Hosting.ProcessProtocol : System.Enum [Public, Sealed]
implements System.IComparable
implements System.IConvertible
implements System.IFormattable
implements System.ISpanFormattable
Field Int32 value__
Field WeavePort.Hosting.ProcessProtocol Mcp20251125=1
Field WeavePort.Hosting.ProcessProtocol Mcp20260728=2
Field WeavePort.Hosting.ProcessProtocol Native=0
type WeavePort.Hosting.UnixSocketTransport : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Hosting.UnixSocketTransport]
Constructor Void .ctor(System.String, System.String) [Public] (LocalDirectory, DockerDirectory)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.UnixSocketTransport) [Public, Final, Virtual] (other)
Method Boolean op_Equality(WeavePort.Hosting.UnixSocketTransport, WeavePort.Hosting.UnixSocketTransport) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.UnixSocketTransport, WeavePort.Hosting.UnixSocketTransport) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_DockerDirectory() [Public] ()
Method System.String get_LocalDirectory() [Public] ()
Method Void Deconstruct(System.String ByRef, System.String ByRef) [Public] (LocalDirectory, DockerDirectory)
Method Void set_DockerDirectory(System.String) [Public] (value)
Method Void set_LocalDirectory(System.String) [Public] (value)
Method WeavePort.Hosting.UnixSocketTransport $() [Public] ()
Property System.String DockerDirectory
Property System.String LocalDirectory
type WeavePort.Hosting.WorkerPoolOptions : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Hosting.WorkerPoolOptions]
Constructor Void .ctor(Int32, Int64, Int32, Int32, System.Nullable`1[System.TimeSpan], System.Nullable`1[System.TimeSpan], Int32, Int64) [Public] (MaximumWorkers=64, MemoryBudgetMiB=16384, MaximumPristineWorkers=4, MaximumConcurrentStarts=8, PristineLifetime=null, MaintenanceInterval=null, MaximumWorkersPerTenant=8, MemoryBudgetPerTenantMiB=2048)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.WorkerPoolOptions) [Public, Final, Virtual] (other)
Method Boolean op_Equality(WeavePort.Hosting.WorkerPoolOptions, WeavePort.Hosting.WorkerPoolOptions) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.WorkerPoolOptions, WeavePort.Hosting.WorkerPoolOptions) [Public, Static] (left, right)
Method Int32 GetHashCode() [Public, Virtual] ()
Method Int32 get_MaximumConcurrentStarts() [Public] ()
Method Int32 get_MaximumPristineWorkers() [Public] ()
Method Int32 get_MaximumWorkers() [Public] ()
Method Int32 get_MaximumWorkersPerTenant() [Public] ()
Method Int64 get_MemoryBudgetMiB() [Public] ()
Method Int64 get_MemoryBudgetPerTenantMiB() [Public] ()
Method System.Nullable`1[System.TimeSpan] get_MaintenanceInterval() [Public] ()
Method System.Nullable`1[System.TimeSpan] get_PristineLifetime() [Public] ()
Method System.String ToString() [Public, Virtual] ()
Method Void Deconstruct(Int32 ByRef, Int64 ByRef, Int32 ByRef, Int32 ByRef, System.Nullable`1[System.TimeSpan] ByRef, System.Nullable`1[System.TimeSpan] ByRef, Int32 ByRef, Int64 ByRef) [Public] (MaximumWorkers, MemoryBudgetMiB, MaximumPristineWorkers, MaximumConcurrentStarts, PristineLifetime, MaintenanceInterval, MaximumWorkersPerTenant, MemoryBudgetPerTenantMiB)
Method Void set_MaintenanceInterval(System.Nullable`1[System.TimeSpan]) [Public] (value)
Method Void set_MaximumConcurrentStarts(Int32) [Public] (value)
Method Void set_MaximumPristineWorkers(Int32) [Public] (value)
Method Void set_MaximumWorkers(Int32) [Public] (value)
Method Void set_MaximumWorkersPerTenant(Int32) [Public] (value)
Method Void set_MemoryBudgetMiB(Int64) [Public] (value)
Method Void set_MemoryBudgetPerTenantMiB(Int64) [Public] (value)
Method Void set_PristineLifetime(System.Nullable`1[System.TimeSpan]) [Public] (value)
Method WeavePort.Hosting.WorkerPoolOptions $() [Public] ()
Property Int32 MaximumConcurrentStarts
Property Int32 MaximumPristineWorkers
Property Int32 MaximumWorkers
Property Int32 MaximumWorkersPerTenant
Property Int64 MemoryBudgetMiB
Property Int64 MemoryBudgetPerTenantMiB
Property System.Nullable`1[System.TimeSpan] MaintenanceInterval
Property System.Nullable`1[System.TimeSpan] PristineLifetime
type WeavePort.Hosting.WorkerPoolSnapshot : System.Object [Public, Sealed]
implements System.IEquatable`1[WeavePort.Hosting.WorkerPoolSnapshot]
Constructor Void .ctor(Int32, Int32, Int32, Int32, Int64, Int32, Int32, System.String) [Public] (Workers, Pristine, Starting, Quarantined, ReservedMemoryMiB, Bindings, Tenants, MaintenanceFailure)
Method Boolean Equals(System.Object) [Public, Virtual] (obj)
Method Boolean Equals(WeavePort.Hosting.WorkerPoolSnapshot) [Public, Final, Virtual] (other)
Method Boolean op_Equality(WeavePort.Hosting.WorkerPoolSnapshot, WeavePort.Hosting.WorkerPoolSnapshot) [Public, Static] (left, right)
Method Boolean op_Inequality(WeavePort.Hosting.WorkerPoolSnapshot, WeavePort.Hosting.WorkerPoolSnapshot) [Public, Static] (left, right)
Method Double get_OldestQuarantineSeconds() [Public] ()
Method Int32 GetHashCode() [Public, Virtual] ()
Method Int32 get_Bindings() [Public] ()
Method Int32 get_Pristine() [Public] ()
Method Int32 get_Quarantined() [Public] ()
Method Int32 get_Starting() [Public] ()
Method Int32 get_Tenants() [Public] ()
Method Int32 get_Workers() [Public] ()
Method Int64 get_ReservedMemoryMiB() [Public] ()
Method System.String ToString() [Public, Virtual] ()
Method System.String get_MaintenanceFailure() [Public] ()
Method Void Deconstruct(Int32 ByRef, Int32 ByRef, Int32 ByRef, Int32 ByRef, Int64 ByRef, Int32 ByRef, Int32 ByRef, System.String ByRef) [Public] (Workers, Pristine, Starting, Quarantined, ReservedMemoryMiB, Bindings, Tenants, MaintenanceFailure)
Method Void set_Bindings(Int32) [Public] (value)
Method Void set_MaintenanceFailure(System.String) [Public] (value)
Method Void set_OldestQuarantineSeconds(Double) [Public] (value)
Method Void set_Pristine(Int32) [Public] (value)
Method Void set_Quarantined(Int32) [Public] (value)
Method Void set_ReservedMemoryMiB(Int64) [Public] (value)
Method Void set_Starting(Int32) [Public] (value)
Method Void set_Tenants(Int32) [Public] (value)
Method Void set_Workers(Int32) [Public] (value)
Method WeavePort.Hosting.WorkerPoolSnapshot $() [Public] ()
Property Double OldestQuarantineSeconds
Property Int32 Bindings
Property Int32 Pristine
Property Int32 Quarantined
Property Int32 Starting
Property Int32 Tenants
Property Int32 Workers
Property Int64 ReservedMemoryMiB
Property System.String MaintenanceFailure
type WeavePort.Sdk.PluginApplication : System.Object [Public, Sealed]
Constructor Void .ctor(System.Text.Json.JsonSerializerOptions) [Public] (json=null)
Method System.String get_PluginVersion() [Public] ()
Method System.Threading.Tasks.Task RunAsync(System.Threading.CancellationToken) [Public] (cancellationToken=null)
Method Void set_PluginVersion(System.String) [Public] (value)
Method WeavePort.Sdk.PluginApplication Function[TInput,TOutput](System.String, System.Func`4[TInput,WeavePort.Sdk.PluginCallContext,System.Threading.CancellationToken,System.Threading.Tasks.ValueTask`1[TOutput]]) [Public] (name, handler)
Method WeavePort.Sdk.PluginApplication Stream[TInput,TItem](System.String, System.Func`4[TInput,WeavePort.Sdk.PluginCallContext,System.Threading.CancellationToken,System.Collections.Generic.IAsyncEnumerable`1[TItem]]) [Public] (name, handler)
Property System.String PluginVersion
type WeavePort.Sdk.PluginCallContext : System.Object [Public, Sealed]
Method System.String get_Tenant() [Public] ()
Method System.Text.Json.JsonElement get_Configuration() [Public] ()
Method System.Threading.Tasks.Task`1[System.Text.Json.JsonElement] CallHostAsync(System.String, System.Text.Json.JsonElement, System.Threading.CancellationToken) [Public] (operation, input, cancellationToken=null)
Property System.String Tenant
Property System.Text.Json.JsonElement Configuration
type WeavePort.Sdk.Client.IPluginClient : [Public, ClassSemanticsMask, Abstract]
implements System.IAsyncDisposable
Method System.Collections.Generic.IAsyncEnumerable`1[System.Text.Json.JsonElement] StreamAsync(System.String, System.Text.Json.JsonElement, System.Threading.CancellationToken) [Public, Virtual, Abstract] (operation, input, cancellationToken=null)
Method System.Threading.Tasks.Task`1[System.Text.Json.JsonElement] CallAsync(System.String, System.Text.Json.JsonElement, System.Threading.CancellationToken) [Public, Virtual, Abstract] (operation, input, cancellationToken=null)
type WeavePort.Sdk.Client.LocalPluginClient : System.Object [Public, Sealed]
implements System.IAsyncDisposable
implements WeavePort.Sdk.Client.IPluginClient
Constructor Void .ctor(WeavePort.Abstractions.IPluginSession, System.Nullable`1[System.TimeSpan]) [Public] (session, streamTimeout=null)
Method System.Collections.Generic.IAsyncEnumerable`1[System.Text.Json.JsonElement] StreamAsync(System.String, System.Text.Json.JsonElement, System.Threading.CancellationToken) [Public, Final, Virtual] (operation, input, cancellationToken=null)
Method System.String get_Instance() [Public] ()
Method System.String get_Tenant() [Public] ()
Method System.Threading.Tasks.Task`1[System.Text.Json.JsonElement] CallAsync(System.String, System.Text.Json.JsonElement, System.Threading.CancellationToken) [Public, Final, Virtual] (operation, input, cancellationToken=null)
Method System.Threading.Tasks.ValueTask DisposeAsync() [Public, Final, Virtual] ()
Property System.String Instance
Property System.String Tenant
type WeavePort.Sdk.Client.PluginCallException : System.IO.IOException [Public, Sealed]
implements System.Runtime.Serialization.ISerializable
Constructor Void .ctor(System.String, Boolean) [Public] (status, mayHaveExecuted=True)
Method Boolean get_MayHaveExecuted() [Public] ()
Method System.String get_Status() [Public] ()
Property Boolean MayHaveExecuted
Property System.String Status
type WeavePort.Sdk.Client.PluginClientExtensions : System.Object [Public, Abstract, Sealed]
Method System.Collections.Generic.IAsyncEnumerable`1[TItem] StreamAsync[TInput,TItem](WeavePort.Sdk.Client.IPluginClient, System.String, TInput, System.Threading.CancellationToken) [Public, Static] (client, operation, input, cancellationToken=null)
Method System.Threading.Tasks.Task`1[TOutput] CallAsync[TInput,TOutput](WeavePort.Sdk.Client.IPluginClient, System.String, TInput, System.Threading.CancellationToken) [Public, Static] (client, operation, input, cancellationToken=null)
```