ready-set-sdk 0.1.0-alpha.1

Shared conventions and helpers for ready-set plugins.
Documentation

ready-set-sdk

ReadySet — by PulseArc.

Shared conventions and helpers for ready-set plugins.

This crate is the typed Rust mirror of the contracts under docs/contracts/ plus the library helpers that first-party plugins use to participate in the lifecycle. It is not required — any binary on PATH named ready-set-<name> can be a plugin — but using the SDK keeps plugins consistent with the dispatcher and first-party tools, and saves writing the same boilerplate across crates.

For the lifecycle grammar, plugin model, and ecosystem overview, see the workspace root README.md.

Install

[dependencies]
ready-set-sdk = "0.1.0-alpha.1"

While the SDK is in the 0.1.0-alpha.* series, pin the exact pre-release version. Cargo does not select pre-release versions for ^0.1 ranges. Once 0.1.0 ships, ready-set-sdk = "0.1" will pick up patch releases as usual.

The SDK is versioned independently of the dispatcher. Plugins pin a major version; the dispatcher does not check SDK version compatibility because there is no in-process API surface between core and plugins, only the CLI contract.

Minimal plugin shape

use ready_set_sdk::describe::{Describe, Platform, Stability};
use ready_set_sdk::prelude::*;

fn describe() -> Describe {
    Describe {
        description: "Example plugin".into(),
        version: "0.1.0".parse().unwrap(),
        stability: Stability::Experimental,
        min_dispatcher_version: "0.1.0".parse().unwrap(),
        platforms: vec![Platform::Linux, Platform::Macos, Platform::Windows],
        requires_cargo_workspace: false,
        capabilities: Vec::new(),
    }
}

fn main() -> std::process::ExitCode {
    let descr = describe();
    if let Some(code) = descr.handle_arg0_describe(std::env::args_os()) {
        return code.into();
    }
    let ctx = Context::from_env();
    let mut out = Output::for_context(&ctx, std::io::stdout());
    out.human("hello world");
    ExitCode::Ok.into()
}

A full runnable version lives at examples/minimal_plugin.rs:

cargo run --example minimal_plugin -- __describe
READY_SET_OUTPUT=human cargo run --example minimal_plugin

Adding lifecycle support

Plugins that contribute capabilities answer __ready, __set, and __go. Use parse_lifecycle_request to discriminate them:

use ready_set_sdk::{Context, ExitCode, LifecycleRequest, parse_lifecycle_request};

fn main() -> std::process::ExitCode {
    let descr = my_describe();
    if let Some(code) = descr.handle_arg0_describe(std::env::args_os()) {
        return code.into();
    }

    let request = match parse_lifecycle_request(std::env::args_os()) {
        Ok(Some(r)) => r,
        Ok(None) => return ExitCode::Ok.into(),
        Err(err) => {
            eprintln!("plugin: {err}");
            return ExitCode::UserError.into();
        }
    };

    let ctx = Context::from_env();
    match request {
        LifecycleRequest::Ready { capability } => run_ready(&ctx, capability.as_str()).into(),
        LifecycleRequest::Set   { capability, args } => run_set(&ctx, capability.as_str(), &args).into(),
        LifecycleRequest::Go    { capability, args } => run_go(&ctx, capability.as_str(), &args).into(),
    }
}

The provider responds:

  • __ready emits one JSON CapabilityReport.
  • __set and __go emit CapabilityRunReport in JSON mode (or stream human output otherwise) and record mutations through the change log.

Unsupported verbs are rejected by the dispatcher before the plugin is spawned, based on the verbs array in each CapabilityDescriptor.

What lives here

Module Purpose
context Per-invocation state ([Context]), populated from the READY_SET_* env contract.
capability Capability descriptors, reports, and run reports — typed mirror of docs/contracts/capabilities.md.
output Human/JSON output formatting (Output, OutputMode).
exit_code Documented process exit codes (ExitCode).
change_log Append-only JSONL change log + content-addressed backups for reversibility.
describe __describe subcommand support; manifest schema reused by sidecars.
manifest ready-set-<name>.toml sidecar parsing.
config .ready-set.toml v2 loader (rejects v1).
lifecycle LifecycleRequest parsing for __ready / __set / __go.
dispatch Cross-plugin dispatch via the core (forwards env contract automatically).
fs Atomic writes, hashing, content-addressed backup helpers.
logging tracing setup honoring --quiet / --verbose / color preferences.
sandbox Per-platform sandbox trait. v0.1.0 implementations are no-op stubs.
error SDK-wide [Error] / [Result] (non-exhaustive).
prelude Convenient re-exports for plugin authors.

Re-exports

use ready_set_sdk::prelude::*; brings in the most-used items:

CapabilityAction, CapabilityActionKind, CapabilityDescriptor, CapabilityId,
CapabilityRelevance, CapabilityReport, CapabilityRunReport, CapabilityState,
CapabilityVerb, NextAction, ProviderId, RunStatus,
ColorMode, Context, LogLevel,
Error, Result,
ExitCode,
LifecycleRequest, LifecycleRequestError, parse_lifecycle_request,
Output, OutputMode,

The crate root (ready_set_sdk::*) also re-exports the contract types, Context, Error, Result, ExitCode, the lifecycle helpers, and Output/OutputMode.

Reversibility helpers

Mutating providers should record each filesystem write to the project's change log so the planned ready-set undo can reverse it across providers. The SDK gives you:

  • change_log::ChangeLog — open an append-only JSONL file under .ready-set/changes/<provider>-<timestamp>-<rand>.jsonl.
  • change_log::ChangeRecord / ChangeOp — typed entries with before_sha256 / after_sha256 fields.
  • change_log::backup_file — copy pre-mutation content into .ready-set/backups/<sha256> (content-addressed).

set --dry-run must not write change logs or backups. The SDK helpers expose dry-run aware variants.

See docs/contracts/change-log.md for the authoritative format.

Cross-plugin composition

Plugins can call other plugins through the dispatcher (never directly), so PATH semantics and built-in resolution stay consistent and the env contract is forwarded:

use ready_set_sdk::dispatch;

let output = dispatch::run("scan", &["--json", "secrets"], &ctx)?;

The helper resolves the dispatcher binary via which, or via the READY_SET_BIN env var when set (useful for tests and integration scenarios).

Stability

  • The SDK's Rust API follows standard cargo semver within ready-set-sdk's own version space.
  • The contracts the SDK mirrors are tiered separately. See docs/contracts/README.md for which contracts are stable vs experimental.
  • #[non_exhaustive] enums: Error, ExitCode, DispatchOutcome, and sandbox::Capability. Match these with a wildcard arm. Other enums (CapabilityState, OutputMode, Stability, Platform, ChangeOp, …) are intentionally exhaustive — they are pinned to versioned wire contracts, so adding a variant is a contract bump.
  • The sandbox trait is stable in surface but its implementations are experimental and will gain real enforcement post-v0.1.0.

Public dependency surface

The SDK re-exports some types from its own dependencies; those deps are part of the SDK's public API and follow these rules:

  • semver::Version (from semver = 1.x) is exposed in Describe, Manifest, and Context::dispatcher_version(). This is intentional — semver::Version is the de-facto Rust representation and wrapping it would force every plugin author to learn a parallel API. Bumping the semver major requirement is a major SDK bump.
  • toml::Value (from toml = 0.8.x) currently appears in Config.plugins. This is not intentional and will be replaced before 0.1.0 stable with an opaque PluginSection wrapper so the underlying representation becomes a private implementation detail. Pre-0.1.0 SDK releases may change this without further notice.

Testing

cargo test -p ready-set-sdk

tests/contract_smoke.rs exercises the contract types end-to-end against the published examples in docs/contracts/.

See also

  • Workspace README.md — product, lifecycle, plugin authoring overview.
  • docs/contracts/ — the authoritative wire and API contracts the SDK mirrors.
  • ready-set — the dispatcher binary that exec's plugins.
  • ready-set-rust — a worked example of a real capability provider built on this SDK.

License

Licensed under either of MIT or Apache-2.0, at your option.