Outcomes: failure as a value

This page explains why an unsuccessful Run is still a successful protocol interaction.

An outcome is the structured classification of a Run, including refusals and partial execution.

Pilotage separates four channels: carrier errors, request errors, diagnostics, and outcomes. A malformed JSON-RPC message is a carrier error. An unknown run is a request error. An invalid program produces diagnostics. A Run returns an outcome.

The six reserved outcome statuses are:

Status Meaning
success The program completed.
validation_error Execution was refused after validation; no side effects occurred.
catalog_drift The pinned catalog no longer matches; no side effects occurred.
promotion_drift A promoted program's baseline no longer matches; no side effects occurred.
partial Execution began but did not complete; side effects may have occurred.
error The Run failed and no more specific status applies.

When Harborview refuses a triggered flow in immediate mode, the tool call itself is not an error. It returns:

{
  "run_id": "run_0003",
  "outcome": {
    "ok": false,
    "status": "validation_error",
    "error": "this flow declares a trigger; mode \"immediate\" would silently ignore it"
  }
}

The response also carries a bad_trigger diagnostic explaining the repair. On MCP, this result rides isError: false. That distinction keeps failure inside the convergence loop: the Client reads the status and diagnostics instead of treating the interaction as a broken transport.

One boundary matters here: “verified” is not an outcome status and not a layer of the loop. It is the conclusion the agent reaches after reading the outcome and the trace against the original goal. The protocol reports what happened; the agent decides whether the mission was achieved.

Formal rules: Part II §5.7, Outcome, Part II §8, Error model, and Part III §7, Error mapping.

Next: Drift and recovery · Validation