Skip to content

API Versioning & Stability

The plugin contract is versioned so that a manifest is only ever registered against a contract it was actually validated for. Phase-1 ships a single, strict version — there is no negotiation, no runtime, and no way for a rollback or upgrade to smuggle a plugin across an incompatible contract line.

PLUGIN_API_VERSION is the string '1', declared once as the canonical contract version. SUPPORTED_PLUGIN_API_VERSIONS is the list ['1'].

Phase-1 is strict single-version support: the host never negotiates a version. A manifest whose apiVersion is not exactly the string '1' — for example the number 1 or the string '2' — is a hard reject with error code unsupported_api_version (message apiVersion must be one of: 1). There is no coercion from a numeric 1; the value must be the string '1'.

apiVersion is not only validated — it is also the registry namespace key. The registry is an apiVersion-namespaced in-memory map, so a plugin that was validated under one contract version can never appear in the namespace of another. This is what makes enable, disable, rollback, and upgrade safe: none of those operations can resurrect a plugin that was validated under an incompatible contract version, because its registration lives under a different apiVersion key entirely.

The same rule extends forward. Any future result cache is namespaced by the pair (apiVersion, plugin.version), so a contract bump or a plugin version change cannot reuse cached output produced under different assumptions.

engines.praxrr is an optional advisory host-version constraint. When present it must be a non-empty string, and it is recorded on the registered plugin — but it is not enforced in Phase-1. Despite any “semver range” phrasing, no semver parsing happens; the host reads and stores the value and takes no action on it. Treat it as documentation of intent, not a gate.

What is stable today is exactly the surface the hand-written validator accepts and the two extension points that are wired to real producers. Everything else is explicitly provisional and may change without a version bump — until it is promoted, at which point promotion itself is a version bump.

Surface Detail
Manifest contract The praxrr.plugin.json shape validated on discovery.
config.profileCompiled.observe Wired observe point, capability read:resolved-profile, snapshot fields arrType, id, name, qualities, customFormats.
sync.previewComputed.observe Wired observe point, capability read:sync-preview, snapshot fields arrType, instanceId, summary, sections.

These two points are wired to real producers, so a registered plugin would receive the projected snapshot shown above once the Phase-2 runtime lands. Nothing executes today.

  • The 7 declared-but-unwired extension points. They are part of the closed union for planning, but dispatching them throws PluginPointNotWiredError.
  • The two unwired capabilities and their provisional field allow-lists: read:custom-format (formatId, name, specifications) and read:config-validation (valid, issues, entity).
  • The host-to-guest invocation ABI. No WASM runtime exists yet, so the guest export name and its argument/return encoding are not finalized.

Adding a grantable capability — or otherwise widening the contract — is a deliberate, test-guarded change that bumps PLUGIN_API_VERSION. The version string is the signal that the projected snapshots, capability set, or extension-point surface a plugin can rely on has changed.