The complete surface of shipmoor test-evidence in v0.8.0: a standalone top-level command, a peer to scan, review, and claim-check, never a flag on any of them. It tells you whether the tests that ran on a change actually ran and passed, whether a failing test quietly disappeared, and whether a kept test was gutted until it couldn’t fail.
usage: shipmoor test-evidence [-h] [--staged] [--diff DIFF] [--all]
[--from FROM_REF] [--to TO_REF]
[--agent AGENT] [--high-assurance]
[--attest-out ATTEST_OUT] [--json]
[--terse] [--no-color]
[target]
shipmoor test-evidence requires the test_evidence entitlement (IC tier, the same tier as claim_check today; see Plans & tiers). The one exception is the hook subcommand below: it is never entitlement-gated, on any tier, because the spool it fills has to exist before anyone can ask whether the entitlement is present.
Positional argument
| Argument | Default | Meaning |
|---|---|---|
target | . | Project directory or repo root to check. |
Selectors: what gets checked
By default, shipmoor test-evidence resolves the same change surface claim-check does: your working tree (tracked changes plus untracked files) as a diff. The flags below narrow or widen that.
| Flag | Scope | What it checks |
|---|---|---|
| (none) | change surface | Working tree: tracked changes plus untracked files. |
--staged | change surface | Staged changes only (the index). |
--diff <spec> | change surface | A raw git diff spec passed straight through to git, e.g. main...HEAD. |
--from <ref> --to <ref> | change surface | A committed range, given together as a pair. |
--all | whole tree | The whole tree, not just the change surface. Use it for a full harvest rather than a change-scoped one. |
shipmoor test-evidence . # the working tree (default)
shipmoor test-evidence . --staged # the staged index
shipmoor test-evidence . --diff main...HEAD # a raw diff spec
shipmoor test-evidence . --from origin/main --to HEAD # a committed range
shipmoor test-evidence . --all # the whole tree
--staged, --diff, and --all are mutually exclusive with each other: only one scope selector applies at a time. --from and --to must be given together, and combining that pair with --staged, --diff, or --all is rejected as an invalid combination.
The weakened-test judge: --agent
| Flag | Meaning |
|---|---|
--agent <preset-or-cmd> | A BYO agent, used only for the weakened signal. claude is the only bare preset with a built-in headless invocation; any other value is a bring-your-own-agent command, run exactly as given. |
passed and reduced are fully deterministic and never touch an agent, whether or not --agent is set. Omit it and weakened simply abstains: it discloses not judged, never a guess.
shipmoor test-evidence . --agent claude
See Signals & anti-gaming for why only weakened needs a judge at all, and BYO-Judge for the wire contract these presets share with Claim Check’s own judge.
Spot verification: --high-assurance
| Flag | Meaning |
|---|---|
--high-assurance | Spot-verify a harvested passed result by re-running a subset of it, instead of trusting the harvest alone. |
Honest limitation. The subset re-runner this flag describes is not built yet. Until it is,
--high-assurancedoes not silently trust an unverified harvest as if it had been spot-checked: it conservatively downgrades that harvest and discloses it asnot_checkedinstead. Passing the flag today gets you a more cautious disclosure, not an actual re-run. That will change once the re-runner ships.
Output flags
| Flag | Meaning |
|---|---|
--attest-out <path> | Write the in-toto TestEvidence attestation to this path, as canonical JSON (deterministically ordered, so the same result serializes to the same bytes every run). This is the exact artifact Claim Check consumes. Omit it and no attestation file is written; the run still reports in human, --json, or --terse form. |
--json | Write the machine-readable report. |
--terse | Collapse the result to a single-line status, for busy CI logs. |
--no-color | Disable terminal color in the human output. |
shipmoor test-evidence . --attest-out .shipmoor/test-evidence.attest.json --json
The hook subcommand
shipmoor test-evidence hook [-h] [--dir DIR] [--config CONFIG]
hook is a lifecycle hook, not a report. It is never entitlement-gated; it always runs, for every tier. Wire it as a Claude Code PostToolUse hook on the Bash tool (project or user level .claude/settings.json), and the harness pipes each tool-result event to its stdin:
{
"hooks": {
"PostToolUse": [
{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "shipmoor test-evidence hook" }] }
]
}
}
When the piped event looks like a real test invocation, hook records it to a local evidence spool at .shipmoor/test-evidence/spool/, bound to the working-tree hash at that moment, for a later shipmoor test-evidence run to harvest. hook always exits 0: a lifecycle hook must never interrupt an agent’s turn, so a non-test command, or a working directory that isn’t a repo, is a silent no-op, never an error.
| Flag | Meaning |
|---|---|
--dir <path> | The repo or working directory to record against. Defaults to the current directory. |
--config <path> | An explicit .shipmoor.yaml to read the test_evidence: block from, otherwise discovered the usual way. |
Config
Defaults come from a test_evidence: block in .shipmoor.yaml. Precedence is flags, then config, then built-in defaults. Every key is optional; the built-ins already cover Shipmoor’s four supported languages (Python, TypeScript, JavaScript, Go). Override any of them explicitly, for example to point at a non-standard report location:
test_evidence:
test_globs: ["**/test_*.py", "**/*_test.go", "**/*.test.ts", "**/*.spec.ts"]
report_globs: ["junit.xml", "coverage/lcov.info", ".shipmoor/test-evidence/*.xml"]
test_command_patterns: ["pytest*", "go test*", "npm test*", "jest*"]
high_assurance: false
| Key | Default | Notes |
|---|---|---|
test_evidence.test_globs | a built-in set covering the four supported languages | Which files count as tests, for the reduced set difference and for matching a changed test file against the collected test ids. |
test_evidence.report_globs | a built-in set of conventional report locations | Where to look for an on-disk report when there’s no spool entry and no CI report bound to head. |
test_evidence.test_command_patterns | a built-in set of common test-runner invocations | Which shell commands hook recognizes as a real test run, versus a silent no-op. |
test_evidence.high_assurance | false | Same as --high-assurance, settable as a project default. |
Exit codes
shipmoor test-evidence follows the same stable exit-code contract as the rest of the CLI:
| Code | When |
|---|---|
0 | passed, reduced, and weakened all come back clean, or are honestly disclosed as not checked / not judged, with nothing to flag. |
1 | reduced or weakened disclosed a finding. |
2 | Usage error: bad flags, an invalid selector combination, a git or config error, or an --agent command that can’t be launched. |
3 | Engine crash. |
A passed result of not_checked, or a weakened result of not judged, is a disclosure, not a finding: on its own it does not flip the exit code to 1. Only a disclosed reduced or weakened finding does that. See Output formats & exit codes for the same contract elsewhere in the CLI.
Example invocations
# Standalone run over the working tree, with the weakened-test judge:
shipmoor test-evidence . --agent claude --json --attest-out .shipmoor/test-evidence.attest.json
# In CI, over a committed range:
shipmoor test-evidence . --from origin/main --to HEAD --terse
Next
- Test Evidence overview: what the three signals are and why harvesting beats re-running.
- Quickstart: wire the hook and run your first harvest.
- Signals & anti-gaming: the full depth on
passed,reduced, andweakened. - Using Test Evidence with Claim Check: how these signals compose into the bigger gate.
- Claim Check CLI reference: the peer command’s full surface.