Skip to content

v0.35.0

Actions and services gain typed failure kinds, commands cancel on Ctrl+C, and new commands call running instances.

Released on October 25, 2026

Breaking changes

  • A goal result and a service response are always a success: end a goal with complete (the result only), fail(kind, message) or complete_cancelled(reason, …), and update any code that passed a success or error argument.
  • Refuse a goal with GoalDecision::refuse(kind, message) in place of reject(reason).
  • fire_goal and the test harness send_goal take a feedback bound such as DEFAULT_FEEDBACK_BOUND instead of the feedback QoS profile; the handle keeps every message up to that bound and cancels the goal when a consumer overflows it.
  • A failed service call surfaces as ServiceFailed (the service's Failure in Python) with a failure kind and message, replacing ServiceError and RuntimeError; a service handler returns its response or that Failure.
  • In tests, answer a service with respond_failure(kind, message) and refuse a goal with pending.refuse(kind, message), in place of respond_error and reject.

Failure kinds

  • A contract declares its own failure kinds in a failure_kinds block that each member lists, so every generated action and service exposes a typed FailureKind enum and Failure the provider and client must use.
  • The daemon refuses work that collides with other work holding a machine's stack (a stack change, node command, second repository refresh or benchmark, or a reservation) with the failure kind busy, retryable once that work ends.
  • peppy repo add, remove and exclude name the failure kind of a refusal, such as precondition_failed for an id already in use.

Cancelling commands

  • peppy stack launch, build, join, remove and benchmark, peppy node add, build and run, and peppy repo refresh cancel their work on the first Ctrl+C, follow the goal to its end, and print its failure kind and message.
  • Each of these commands exits with a status for the goal's outcome: 0 completed, 3 refused, 4 failed, 5 cancelled, and 130 after a second Ctrl+C.
  • A goal ends when the process that sent it is gone; a provider sets set_sender_grace so a client that stops and restarts keeps its goals running.
  • A worker reads why its goal was cancelled through cancel_cause (its caller, or its sender gone) and reports the reason through complete_cancelled.

Calling running instances

  • peppy node call <instance> <member> calls one service or action of a running instance from the command line, taking its message through --args, --set and --file, and prints how the call ended.
  • peppy node echo <instance> <topic> prints a topic's messages until Ctrl+C, and peppy node describe <instance> shows a running instance's interfaces and their message formats.

MCP exposures

  • An MCP tool that refuses or fails a call reports a failure kind and message in its tool error and call record, and the stack_copies join and remove tools return an empty result on success.
  • A goal that runs inside an MCP call is cancelled when the call closes or the client disconnects, while a goal run as a task keeps running until the client cancels the task.

Node documents

  • A node uses one content for each document it names; peppy node sync and peppy node add refuse a manifest that references one contract or pairing at two different sha256 values.

View all releases