Skip to content

Packaging your algorithm

A plugin is a signed, self-contained .pmplugin bundle. Its manifest declares an id, a runtime, and one or more actions; each action declares the artifact types it consumes and produces:

{
"id": "org.acme.my-miner",
"runtime": "wasm",
"actions": [
{
"id": "discover",
"inputs": { "log": "EventLog" },
"outputs": ["AcceptingPetriNet"]
}
]
}

That declaration is the whole integration. The host uses it to decide which artifacts your action can apply to, where it appears in the menu, and how to record provenance for its results. You do not register anything with a UI.

Runtime Write it in Suits
wasm Rust (or anything targeting WebAssembly) Algorithms where speed matters — miners, alignment kernels
pyodide Python Reusing an existing Python implementation unmodified
relational SQL against the relational API Work best expressed as a query, engine-independently
view TypeScript Rendering an artifact interactively

Composites are normal: several shipped plugins are relational + wasm (query in SQL, compute in Rust) or pyodide + view (compute in Python, render in TypeScript).

If you are writing Rust, keep the algorithm crate free of wasm-bindgen and browser APIs, and put the binding in a thin wrapper. That is what lets the same crate run in the page and natively on a compute engine. Several of the shipped plugins are structured exactly this way, for exactly this reason.

Your plugin does not receive the log as a value. It queries it — host.sql() for DuckDB text, or the relational API for an engine-independent contract. There is no second, more privileged interface that the built-in algorithms use; they go through the same door.

View plugins render inside a sandboxed iframe with their own CSP. A view cannot reach the host page, and it cannot exfiltrate the log.

A replication package that ships a .pmplugin bundle gives a reviewer a one-click path: install, run against the log you provide, see your figure regenerate. No environment, no dependency resolution, no version drift — and because the bundle carries its own runtime, it works the same in a year.

Add your plugin to a registry and it appears in the library alongside the built-in ones, with its versions, checksums and authorship attached.