Configuration & exit semantics

Shipmoor Team
July 31, 2026
5 min read

Advisory by default

Blast Radius needs no configuration at all. Out of the box it reports suspects and exits 0.

A feature whose whole premise is a graph you have to build cannot start by failing the builds of every repo that has not built one yet. Adoption has to be able to start with reading the output.

A repo that wants a local failing threshold opts in:

schema_version: 1
blast:
  # How a suspect link affects the exit code.
  #   off   exit 0, and the summary line drops the warning tone
  #   warn  exit 0, the default, with the summary line advising the ratchet
  #   fail  exit 1 when this run classified at least one suspect
  # Unresolvable links never trip the threshold under any value: they are
  # disclosed unknowns, not suspects.
  suspect_threshold: warn

The one key

KeyDefaultWhat it controls
blast.suspect_thresholdwarnWhether a suspect fails the run.
ValueExit on suspectsSummary line
off0Drops the warning tone.
warn (default)0Advises the ratchet.
fail1The opt-in ratchet.

off and warn both exit 0 and differ only in the summary line’s tone. Neither hides a finding. There is no value that suppresses a suspect from the output — the choice is about the exit code and the tone, never about what you get to see.

Setting fail means a pull request that edits an obligation without touching its realizing code fails, with the suspect link as the witness.

The off spelling, and the YAML boolean trap

off is a YAML boolean. A YAML parser reads the bare word as false rather than as the string "off".

Rather than requiring you to remember to quote it, the value is normalised: you can write it bare, and the other boolean spellings of false (no, n, false, in any capitalisation) are read as off too, whichever parser is in play. The value means the same thing in every environment.

The true spellings (on, yes, true) are not thresholds and are rejected like any other unrecognised value. warn and fail are ordinary words, matched exactly, and are unaffected by any of this — so nothing here can reinterpret an opted-in ratchet.

An unrecognised value is a loud error

A typo in the threshold does not fall back to the default. It is an error.

This is the one failure mode a gate must not have. If suspect_threshold: fial silently became warn, a user would believe the local ratchet was active and would not discover the typo until a drifted obligation shipped.

By the same reasoning, a malformed config is a usage error (exit 2), not a warning — an unparseable config must never silently downgrade an opted-in ratchet. A malformed committed store is a usage error too: an unreadable store must never read as an empty graph, which would look identical to a clean one.

What never affects the exit code

Under any threshold value:

  • unresolvable links
  • gaps
  • rerun advisories

They are disclosed unknowns and disclosed absences. A run that failed on them would punish exactly the repos that have not adopted the feature yet — a repo with one stale path in its store would fail every build until someone fixed a link that has nothing to do with the change under review.

Only a classified suspect can fail a run, and only when the repo asked for that.

Configuration the verifies join depends on

The verifies join reads claim_check.runners.test, because the rung it calls binds only a check something can run.

claim_check:
  runners:
    test: "pytest {ref}"

Without a runner configured, no edges are derived and the run says so, rather than presenting an empty graph as a clean one.

Current CI boundary

Start in warn and read the output for a few weeks. The suspects a real repo produces in its first month are the fastest way to find out whether your graph says what you think it says.

shipmoor blast --diff "origin/main...HEAD" --terse .

Self-managed CI currently supports Scan only with SHIPMOOR_TOKEN; do not add shipmoor blast to a self-managed CI workflow. --terse remains useful for concise local output, and the full local report is written to .shipmoor/blast.v1.json.

When you turn the ratchet on, turn it on deliberately:

schema_version: 1
blast:
  suspect_threshold: fail

From that point a one-sided change is a failing build, and the two honest ways to clear it are to update the other side or to record an explicit re-pin that a reviewer can see.

Next

Last updated on July 31, 2026

Was this article helpful?

Your response is saved on this device.

Related Articles