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)orcomplete_cancelled(reason, …), and update any code that passed a success or error argument. - Refuse a goal with
GoalDecision::refuse(kind, message)in place ofreject(reason). fire_goaland the test harnesssend_goaltake a feedback bound such asDEFAULT_FEEDBACK_BOUNDinstead 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'sFailurein Python) with a failure kind and message, replacingServiceErrorandRuntimeError; a service handler returns its response or thatFailure. - In tests, answer a service with
respond_failure(kind, message)and refuse a goal withpending.refuse(kind, message), in place ofrespond_errorandreject.
Failure kinds
- A contract declares its own failure kinds in a
failure_kindsblock that each member lists, so every generated action and service exposes a typedFailureKindenum andFailurethe 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,removeandexcludename the failure kind of a refusal, such asprecondition_failedfor an id already in use.
Cancelling commands
peppy stack launch,build,join,removeandbenchmark,peppy node add,buildandrun, andpeppy repo refreshcancel 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_graceso 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 throughcomplete_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,--setand--file, and prints how the call ended.peppy node echo <instance> <topic>prints a topic's messages until Ctrl+C, andpeppy 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_copiesjoinandremovetools 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 syncandpeppy node addrefuse a manifest that references one contract or pairing at two different sha256 values.