Skip to main content
The moment bunx smthrs up or bunx smthrs workflow run reports a failed run, it launches the post-failure system workflow in the background against that run, gathering evidence and producing a verdict (see below). It prints one line to follow along:
Read the verdict once the autopsy finishes:

What the autopsy does

Four steps run:
  1. Gather (deterministic): inspect, events, and the workflow source, plus the Smithers version.
  2. Investigate (agent, read-only tools): digs through the evidence, re-runs read-only CLI commands, reads the workflow. It never mutates anything: no retries, no rewinds, no edits.
  3. Bug gate (only when it suspects Smithers itself): an Approval pauses the run and asks you before anything is reported.
  4. Verdict: a stable output row with the failure class, root cause, confidence, suggestion, and exact commands to run next.

Failure classes

Every failure is classified as one of:

Suggestions

One suggestion per verdict, plus the exact commands implementing it:
  • retry: transient; re-run the failed task (bunx smthrs retry-task) or the whole run.
  • resume: the run can continue from where it stopped.
  • rewind: state is bad but an earlier frame is good (bunx smthrs rewind).
  • edit-workflow-and-reset: the workflow needs a fix first; the verdict names the exact edit. Never edit a script while its run is resumable (that causes RESUME_METADATA_MISMATCH); make the edit, then start a fresh run.
  • fix-environment: the exact install/auth/config fix.
  • escalate: a human must decide; the verdict says what to look at.
The autopsy only ever suggests: it never retries, rewinds, or edits the failed run itself.

Reporting Smithers bugs (approval-gated)

When the investigation concludes the failure is a bug in Smithers itself, the autopsy pauses on an Approval gate explaining what it thinks the bug is. Nothing is sent without your explicit approval: approve, and the workflow files the report with bunx smthrs bug, which POSTs to https://bug.smithers.sh/api/bugs and records the returned bug id and URL in the verdict; deny, and the verdict is kept but nothing is reported. File a report by hand at any time:
bunx smthrs bug attaches the run’s workflow name, status, error, and recent events (secrets scrubbed) along with the Smithers version and platform. See the CLI catalog for its flags.

When it fires

The autopsy only investigates a genuine, unexpected task error. When a run fails, the CLI first classifies why, reading the ledger the cause is already recorded in, and only autopsies a real error: Skipping these avoids spending agent tokens autopsying a decision whose cause is already known. When a run fails for a non-error reason the CLI prints a single line noting the skip instead of launching the autopsy. The classification is scoped to the run’s terminal cause, not its whole history. A denial on a gate whose onDeny is 'continue' or 'skip' lets the run keep going; if a later task then throws, that genuine error is the terminal cause, not the earlier denial, so the autopsy still fires.

Opting out

On by default; turn it off with any of:
  • the --no-post-failure flag on bunx smthrs up / bunx smthrs workflow run,
  • the SMITHERS_POST_FAILURE=0 environment variable, or
  • a per-workflow opt-out for workflows that fail deliberately (fault-injection suites, negative tests): pass postFailureAutopsy: false in the workflow options so a failure of that workflow never autopsies itself:
It also skips itself automatically:
  • when the failing workflow is post-failure itself or another ops workflow (triage-run, init), so autopsies never recurse; the launched autopsy runs with SMITHERS_POST_FAILURE=0 in its environment for the same reason;
  • when the terminal cause is a human deny, a cancel, or a quota park (see When it fires);
  • when the post-failure workflow is not installed, printing the manual command instead:
Run bunx smthrs init to install the workflow pack, which includes post-failure as a hidden system workflow (it does not appear in bunx smthrs workflow list without --system, but is always runnable by id).