Skip to main content
Workflow condition outcomes use new names. Conditions and routing directives now use succeeded, failed, partially_succeeded, and skipped. Retry intent is internal and no longer appears as an edge-routable outcome.To migrate:
  1. Replace outcome=success with outcome=succeeded.
  2. Replace outcome=fail with outcome=failed.
  3. Replace outcome=partial_success with outcome=partially_succeeded.
  4. Remove outcome=retry branches and use retry policies plus stage.retrying events for retry observability.

Live command output logs

Command stages used to expose output mostly through event payloads and short diagnostic tails. Fabro now records stdout and stderr as per-stage logs while the command runs, stores the finalized streams in CAS-backed storage, and renders separate live output panels in the run stage view. API clients can tail the same logs by byte offset, which makes long-running scripts easier to follow without reloading an entire run projection:
curl "$FABRO_SERVER/api/v1/runs/$RUN_ID/stages/$STAGE_ID/logs/stdout?offset=0"
The same command log data is available to edge routing and retros after the command finishes, so workflow decisions and run narratives can inspect the final output without relying on truncated event fields.

Precise stage outcomes

Fabro now separates a stage’s terminal outcome from its live execution state. Workflow routing sees four stable outcomes - succeeded, failed, partially_succeeded, and skipped - while retrying remains an internal execution state surfaced through events. This makes edge conditions, agent routing directives, status files, and API responses line up around one vocabulary:
gate -> deploy [condition="outcome=succeeded || outcome=partially_succeeded"]
gate -> fix    [condition="outcome=failed"]
gate -> skip   [condition="outcome=skipped"]

Clearer run state in the API and web app

The server now projects precise stage states to API clients, and the generated TypeScript client exposes those shapes directly. The web app uses the same model across run overview, stage sidebar, run files, settings, billing, and workflow detail views, so running, retrying, succeeded, failed, partially succeeded, and skipped stages render consistently. The OpenAPI schema also reuses canonical billing, model, provider, settings, and stage outcome types instead of parallel generated copies. Client code sees fewer accidental shape differences between API responses that represent the same product concepts.

More

  • New GET /api/v1/runs/{id}/stages/{stageId}/logs/{stream} endpoint tails command stdout or stderr with byte offsets
  • Replaced the generated StageStatus model with StageState and StageOutcome shapes
  • Tightened shared model, billing, provider, and settings schemas in the OpenAPI contract
  • Added configured to GET /models responses so clients can tell whether credential material is present before testing a model
  • Regenerated the TypeScript API client with precise run, workflow, sandbox, hook, MCP, and settings models
  • allow_partial=true now promotes exhausted retryable failures to partially_succeeded
  • Retryable failures emit retrying events while the node remains active instead of exposing retry as a final outcome
  • Command results now distinguish cancellations from timeouts
  • Docker, Daytona, local, and worktree sandboxes feed command stdout and stderr into the same streaming log pipeline
  • Run progress no longer prints successful metadata snapshot lines in the main progress stream
  • Run detail headers are less noisy after removing the repeated source and sandbox path line
  • Fixed command diagnostics being lost on early command failures
  • Fixed Daytona and worktree sandboxes losing streamed command semantics
  • Fixed retros missing command timing log references