All posts

Releases

Shipmoor 0.7.0: Claim Check gives a binding verdict on whether a change did what the author claimed

Shipmoor 0.7.0 adds Claim Check. You write an acceptance set of atomic obligations, the deterministic floor decides READY versus BLOCKED, and a bring-your-own intent fidelity judge adjudicates the judgment ACs the floor cannot check. A binding verdict and a VSA attestation, local, no source upload. The 0.7.0 release also splits the entitlement model: claim_check and code_review replace the old cli_pro and intent_scan.

Shipmoor 0.7.0: Claim Check gives a binding verdict on whether a change did what the author claimed cover image

This post describes the 0.7.0 release. Some specifics below (the judge’s sampling rate, which agents work as a bare --agent preset) changed in later releases. See Shipmoor 0.8.0 for what’s current, or the Claim Check docs for the living reference.

The Shipmoor scan catches the structural ways agent-generated code goes wrong, and 0.6.0 Code Review added an advisory reading pass for the soft questions a linter cannot answer. Both are useful, and both leave the same gap open. A coding agent can ship a diff that lints clean, type-checks, and passes the tests it wrote, while doing the wrong thing: wiring the wrong event, editing a sibling service, or handling a case by swallowing it. The reviewer’s scarcest question, the one no linter answers and no advisory read settles, is this: did this change do what its author claimed it would do?

Shipmoor 0.7.0 adds Claim Check, the binding layer on top of the scan and the review.

What Claim Check is

Claim Check is a verification tool that produces a binding verdict on whether a code change does what its author claimed it would do. The author writes an acceptance set, a YAML file of atomic binary obligations called ACs. The tool evaluates the change against that frozen intent and returns one verdict: READY, READY WITH GAPS, BLOCKED, or INCONCLUSIVE. It writes a JSON attestation summarizing the result.

The split from Code Review is the whole point. Code Review reads the diff and advises. Claim Check freezes the intent into an acceptance set, evaluates the change against it, and returns one verdict that can stand in front of a merge button. The scan still gates on structure. Claim Check gates on intent.

The deterministic floor

The floor is a model-free deny set that decides READY versus BLOCKED. It runs check adapters against deterministic ACs: a command exit check, a git ref check, a test pattern check. It refuses to use any LLM inferred result as the basis for a READY. Anything the floor cannot check mechanically is routed to cannot check, never to a silent pass.

The floor-only path is the CI gate and the Community tier. It is fast, reproducible, and uses no model and no secret. The same change, intent, and acceptance set produce the same floor verdict and the same attestation, run to run, machine to machine. That is what makes it safe to put in front of a merge button.

The intent fidelity judge

For judgment ACs the floor cannot check, a bring-your-own agent adjudicates. The agent is a subprocess the user supplies, typically claude or cursor agent, which reads a masked prompt on stdin and writes JSON on stdout. The judge is monotonic toward safety: it can only BLOCK by citing a divergence, or ABSTAIN by routing to a human. It never passes a judgment obligation. A required judgment that abstains becomes INCONCLUSIVE, never a silent pass.

Each judgment AC is sampled K times, default 5, concurrently. A BLOCK requires agreement of at least the floor, default 4 out of 5. A single sample cannot BLOCK. This is the rule that makes a confidently wrong judge unable to gate on its own: one noisy BLOCK out of five is discarded, and the AC stays open.

The judge works in two phases. First, decomposition breaks the AC statement into atomic check questions. Second, audit adjudicates each atomic check against the masked observed behavior of the change. A BLOCK is only counted if the resolving pointer the judge cites mechanically resolves in the repo, so the judge cannot BLOCK on a hallucinated location.

Fail-safe is absolute. Every failure mode of the judge collapses to one safe outcome: the AC stays open or cannot check with a reason. A broken judge can never invent an issue, and it can never fail your build, because the judge does not have that power in the first place.

The masking boundary

Only masked signals leave the process to the agent. The judge transport receives the AC statement, a masked diff, and per-file added symbols, never raw source beyond what the diff shows. The trace sidecar carries only masked signals and aggregate rationales, never raw per-sample model output. This is an invariant, not a best effort.

Shipmoor itself opens no network plane, hosts no model, and needs no API key of its own. The floor is deterministic and offline by default. The judge is your own agent running on your machine, under your own provider relationship. If you bring an offline or local judge, a full-mode claim check makes no network calls at all.

The verdict vocabulary and exit codes

The verdict is one of four states, and the exit code follows directly from it.

  • READY: the required floor ACs are satisfied and no required judgment AC blocked. Exit 0.
  • READY WITH GAPS: the required ACs are satisfied but some non-required ACs are open or cannot check. Exit 0.
  • BLOCKED: at least one required AC failed or blocked. Exit 1.
  • INCONCLUSIVE: a required judgment AC abstained and could not be resolved. Exit 1.

The remaining exit codes are operational: 2 for usage error, and 3 for engine crash.

The split between READY and READY WITH GAPS is the honest part. A change that satisfies every required AC but leaves a non-required one open is not a fail; it is a pass with disclosed gaps. The split between BLOCKED and INCONCLUSIVE is the safety part. A floor BLOCK is deterministic and falsifiable. A judge ABSTAIN on a required judgment AC is INCONCLUSIVE, which is a non-zero exit, because a required obligation that could not be resolved must not silently pass.

A real run

Here is a real BLOCKED run on a Kubernetes admission controller change. The floor routed three required judgment ACs to the judge, and the judge blocked each with 5/4 agreement. The prompt line is the whole story:

$ shipmoor claim-check --agent cursor .

Claim Check  BLOCKED
  validation coverage: 0%  ·  verified 0 · divergent 0 · judgment-open 3 · underspecified 0
  Verification axis: build green · tests green · scan green · must-fix open 0
  Validation axis: coverage 0% · divergent 0 · underspecified 0

────────────────────────────────────────────────────────
  AC-01  ·  judgment  ·  required  source: "the IsPrivileged detector inspects every container class (Containers, InitContainers, EphemeralContainers)"
    · result: open (judgment — judge adjudicates)
    ⊘ judge: BLOCK  ·  K 5  ·  agreement 5/5  ·  samples 5  ·  transport 'cursor-agent -p --trust --output-format text'
    decomposed checks:
      • Does the change add a detector named `IsPrivileged`?
      • Does the `IsPrivileged` detector inspect `pod.Spec.Containers`?
      • Does the `IsPrivileged` detector inspect `pod.Spec.InitContainers`?
      • Does the `IsPrivileged` detector inspect `pod.Spec.EphemeralContainers`?
  AC-02  ·  judgment  ·  required  source: "EnforcePrivilegedPolicy returns an error rather than calling panic"
    · result: open (judgment — judge adjudicates)
    ⊘ judge: BLOCK  ·  K 5  ·  agreement 5/5  ·  samples 5  ·  transport 'cursor-agent -p --trust --output-format text'
    decomposed checks:
      • Does the change modify the `EnforcePrivilegedPolicy` function so it returns an error?
      • Does the change remove the `panic` call from the `EnforcePrivilegedPolicy` function?
      • Does `EnforcePrivilegedPolicy` return a non-nil error when enforcement is not yet implemented (instead of crashing the process)?
  AC-03  ·  judgment  ·  required  source: "all referenced identifiers are imported and all call results are handled"
    · result: open (judgment — judge adjudicates)
    ⊘ judge: BLOCK  ·  K 5  ·  agreement 5/5  ·  samples 5  ·  transport 'cursor-agent -p --trust --output-format text'
    decomposed checks:
      • Does the change compile successfully (no missing imports or unresolved identifiers)?
      • Is every referenced identifier backed by an imported package in the changed code?
      • Is the package providing `metav1.GetOptions` imported where `metav1.GetOptions` is referenced?
      • Is the result of the `policy.Enforce` call checked rather than ignored?
      • Is the error returned from the namespace `Get` call handled rather than silently discarded?
Wrote attestation to .shipmoor/claim-check.vsa.json

Three required judgment ACs, three blocks, each with 5/4 agreement, each citing a resolving pointer that mechanically resolved in the repo. The headline reads BLOCKED, exit 1. A binding verdict, surfaced for the reviewer, with the evidence the floor required to count it.

The attestation

Every run writes a VSA, a Verification Summary Attestation, as JSON, to .shipmoor/claim-check.vsa.json. It carries the verdict, the intent hash, the acceptance hash, the policy version, per-item dispositions, and judge results. The top-level verification_result field is the SLSA literal the verdict maps to, so it slots into an existing attestation ecosystem instead of inventing a new one.

The acceptance set is frozen at author time and hashed into the intent_hash and acceptance_hash carried in the VSA. A downstream consumer can compare those hashes against the acceptance set committed with the change and detect that the intent was changed after the verdict was produced. An optional trace sidecar carries per-AC dispositions and masked judge traces for observability. It is additive: it does not change the verdict, the VSA, or the exit code.

The 0.7.0 entitlement split

This release also cleans up the entitlement model. The old cli_pro and intent_scan entitlements are gone. Dedicated entitlements claim_check and code_review now gate their respective features, matching the per-feature model already used by the harness and skills.

The legacy command surfaces are removed: intent-scan, resolve-intent, probes, and scan --intent. shipmoor scan is the pure community line-scoped scanner, with no --intent flag. resolve-intent folded into shipmoor claim-check resolve, and probes folded into shipmoor claim-check probes. If you pinned the old surface in a script, this is the upgrade that renames it.

The CLI surface

The new command is shipmoor claim-check:

shipmoor claim-check [target]                          # run the floor plus an optional judge
shipmoor claim-check init                              # scaffold a starter acceptance set
shipmoor claim-check resolve                           # resolve intent without a diff
shipmoor claim-check probes {gaps,scaffold,coverage}   # inspect the probe library

The flags that matter:

  • --agent <cmd>: bring your own judge. Built-in presets: claude, codex, cursor, aider.
  • --floor-only: the deterministic floor with no judge. This is the CI gate and the Community tier.
  • --acceptance <path>: point at an author-mode acceptance set.
  • --vsa-out <path>: write the VSA attestation to a path.
  • --trace-out <path>: write the additive trace sidecar to a path.
  • --json: machine-readable output.

Install and upgrade

curl -fsSL https://dl.shipmoor.dev/install.sh | bash
shipmoor version
# shipmoor 0.7.0

shipmoor claim-check --agent cursor .

If you pinned Shipmoor in CI, the deterministic scan gate behaves the same today as it did yesterday. The floor-only claim check is a new gate you can opt into alongside it, and the judge is opt-in and never passes a judgment obligation.

What ships and where to go next

Claim Check is part of the Shipmoor IC plan, on the claim_check entitlement. The deterministic floor-only path is available to the Community tier as the CI gate: model-free, reproducible, no secret.

The next layer is the one the reviewer is still doing by hand: reading the diff against the task, line by line, before they trust the merge. Claim Check is our answer to the first half of that. The second half is next.

  • From the shipmoor.dev Engineering Team

Contact sales

Our team can help with custom support, team rollouts, and self-hosted deployments. Or to get started now, explore our self-serve plans.