Claim Check checks whether a change did what the task asked, then reports one of four verdicts. This page covers what happens next: shipmoor claim-check gates every run, unconditionally. The exit code follows the verdict with nothing in between: READY and READY_WITH_GAPS exit 0; BLOCKED and INCONCLUSIVE exit 1. There is no flag, no config key, and no policy setting that changes this mapping. If you run the command in CI and fail a step on a nonzero exit code, a BLOCKED or INCONCLUSIVE verdict fails that step. That is the entire gating model.
If you used an earlier release of Claim Check: you may remember a
--verdict-policyflag, a--would-blockpreview mode, and agating.enabledconfig key that had to be switched on before aBLOCKEDverdict could fail a build. None of that exists in 0.8.0. Gating used to be something you opted into. Now it is simply what the exit code means, and there is nothing left to turn on.
The four verdicts, and what they exit
The exit code is not a separate decision layered on top of the verdict under some policy. It is the verdict, expressed as a number.
| Verdict | What it means | Exit code |
|---|---|---|
READY | The deterministic floor is green, nothing is blocked, and nothing required is left underspecified. | 0 |
READY_WITH_GAPS | The floor is green and nothing is blocked, but something non-required is still open or unresolved. | 0 |
BLOCKED | A deterministic-floor check came back red, or the floor is green but a judge block was confirmed. | 1 |
INCONCLUSIVE | The floor is green and nothing is blocked, but a required item could not be resolved and routes to a human. | 1 |
The remaining exit codes are operational, not verdicts: 2 for a usage error, 3 for an engine crash. See CLI reference.
How the verdict is fused
Underneath, the verdict is decided by a fixed priority order, checked in this sequence:
- Any deterministic-floor check comes back red. That alone is
BLOCKED. Nothing else matters once this is true; it always wins, regardless of anything else in the run. - The floor is green, and the judge confirmed a block. Also
BLOCKED. A judge block only counts once it has survived actually re-running its own cited test or command, hermetically, at the reviewed head. See BYO-Judge. - The floor is green, nothing is blocked, and a required item is abstained or otherwise undecided.
INCONCLUSIVE. This routes to a human instead of guessing in either direction. - The floor is green, nothing is blocked, and nothing required is left underspecified.
READY. - The floor is green, nothing is blocked, and something non-required is still open.
READY_WITH_GAPS.
Notice what’s missing from this list: there is no step where the judge, on its own, produces a passing verdict. The judge can only BLOCK (rule 2) or push a required item toward INCONCLUSIVE by abstaining (rule 3). It never independently passes an obligation. A green verdict always rides the deterministic floor, never the judge alone. See What is Claim Check for the three layers this priority order sits on top of.
An unapproved acceptance set is never a pass
The acceptance set feeds this fusion order too, and its approval state matters as much as its content. Three files are involved:
.shipmoor/acceptance.yaml: the human-authored, editable acceptance set. This is what--acceptancepoints to, and what you edit by hand..shipmoor/acceptance.yaml.draft: an auto-derived, unapproved draft, written when noacceptance.yamlis committed at that path. Every draft is disclosed as unapproved..shipmoor/acceptance.json: a frozen, hashed, committed pin used for tamper detection once a set is approved.
If no acceptance.yaml is committed, the gate can auto-derive one from the frozen intent instead of simply failing. How much that draft leans on a model is controlled by claim_check.authoring_mode:
| Mode | What happens |
|---|---|
author (default) | Hand-authored only. No model runs. You write .shipmoor/acceptance.yaml yourself, typically starting from shipmoor claim-check init. |
auto | LLM extraction derives a draft acceptance set from the frozen intent. |
hybrid | The same auto-derived draft, plus a human-confirm step before it counts as approved. |
Approval means committing the file. There is no --yes flag and no config key that marks a draft approved from the command line. A run over an unapproved or draft acceptance set that would otherwise have come back READY is downgraded to INCONCLUSIVE instead. A draft is never an approved pass, no matter how clean the underlying change is.
What this means in CI
Wire the exit code into a required check and you get exactly the table above: BLOCKED and INCONCLUSIVE fail the step, every run, unconditionally. No config key turns a BLOCKED verdict into a passing build.
shipmoor claim-check . --floor-only --from origin/main --to HEAD
# exit 1 on BLOCKED or INCONCLUSIVE, no exceptions
If a team wants Claim Check as a required, blocking check, this is already the entire wiring: install the binary, run the command, let the step’s own exit code decide the job. No policy file is needed to make it block; it already does.
Keeping a step informational instead
If you want Claim Check to report without blocking the build, for a rollout period or for a check you are not ready to require yet, do it at the CI level, not the command level. There is no first-party advisory-mode flag that makes a single invocation exit 0 on a bad verdict. Two patterns work instead:
Run it as a separate, non-blocking step. Guard the step so its own exit code cannot fail the job, and still capture the result as an artifact:
- name: Shipmoor Claim Check (informational for now)
run: |
shipmoor claim-check . --from origin/main --to HEAD \
--json --output claim-check.json || true
- uses: actions/upload-artifact@v4
with:
name: claim-check-result
path: claim-check.json
Or, only fail the job on a different, separate condition you already control, such as your structural shipmoor scan --fail-on gate, and treat the claim-check step as a report to read rather than a required check.
Both patterns leave the command’s own exit-code behavior untouched. What changes is whether the surrounding job treats that exit code as load-bearing.
What you can actually tune: the floor policy file
The exit-code mapping itself has no dial. What does have one is a narrower, separate mechanism: the floor policy file, set with claim_check.policy_path in .shipmoor.yaml and defaulting to a shipped floor_policy.yaml (policy_version: "1.1.0").
# .shipmoor.yaml
claim_check:
policy_path: ".shipmoor/floor_policy.yaml"
Copy the shipped file into your repo and point policy_path at your copy to adjust it. Its scope is deliberately narrow. It can toggle a couple of optional, cross-cutting requirements on or off, among them a scan-severity threshold and whether artifact or build validation is required for a given run.
It cannot touch the core of the floor. Every one of the following is enforced unconditionally, regardless of what the policy file says:
- an open must-fix finding from the scan,
- a required test transition,
- a confirmed judge block,
- a required acceptance item,
- test integrity,
- a green build,
- green tests.
None of those are policy-configurable, in either direction. Treat the floor policy file as a narrow dial on a couple of optional extras, not as a general opt-in or opt-out system for the gate itself.
Next
- What is Claim Check: the three layers the verdict is built from.
- CLI reference: the full flag surface and the exit-code table.
- Reading the verdict: the four verdicts and the VSA in detail.
- BYO-Judge: sampling, the confidence threshold, and the pointer-must-resolve rule behind a confirmed block.
- Providing intent: where intent comes from and how it reaches the acceptance set.
- CI integration: wiring the floor into a GitHub Actions job and publishing the VSA.
- Attestation artifacts: where a gating decision is recorded for later audit.
- Test Evidence: attesting that tests actually ran, as a separate producer this gate can consume.