Proof receipts
SOBA proof bundles, claim explanations, verification commands, permission receipts, and release-ready evidence workflow.
SOBA's 0.6.x release line is evidence-first. The agent should not only say what it did; it should leave a proof trail that a user, reviewer, or CI job can inspect later.
Proof receipts live in .soba/evidence/*.soba-proof.json. They are local project artifacts and do not require a
provider connection to inspect.
Evidence proof receipts
Evidence proof receipts are the persisted proof files SOBA writes after an accepted finish. Use soba prove --last to
open the newest receipt, or pass a specific .soba/evidence/<id>.soba-proof.json file when reviewing an older task.
Proof claim mapping means each important finish claim should be mapped to evidence ids. A claim can point to a command,
check, changed file, file mutation, risk, or review action. soba verify checks that supported references point to known
ids instead of dangling text.
Proof claim explanations are read with soba explain-claim. Use the claim text or id, and add
--proof .soba/evidence/<id>.soba-proof.json when the claim is not in the latest receipt.
Proof permission receipts record trust level, approval kind, approval value, decision, reason, and least-privilege alternatives when SOBA can infer a safer command.
What a proof receipt contains
A proof receipt can include:
- changed files and mutation summaries;
- checks and command evidence;
- finish claims mapped to evidence ids;
- risks and unverified areas;
- permission receipts for tool calls;
- safer alternatives for risky commands when SOBA can infer them;
- run metrics with model-call and input/output/total token counts;
- a
runIddeterministically derived fromsessionId+turnId, and a content-addressedproofId; - a SHA-256 digest for the complete redacted receipt.
This makes the final answer auditable. A claim such as "tests passed" should point to the command that actually ran. A claim that has no evidence should stay visibly unverified.
When the completion gate accepts criteria without explicit evidence IDs, SOBA links them only to evidence already recorded in that turn: successful mutation, verification, and inspection entries. It does not invent evidence. If no matching record exists, the claim remains unverified.
Newly written Proof Bundle v1 receipts are sealed before persistence. SOBA recursively redacts recognizable credentials,
canonicalizes the JSON, derives proofId, and stores integrity.digest. soba prove shows the proof ID, run ID, and
digest. Re-sealing the same session/turn identity preserves its run ID, while another turn gets a different run ID.
Editing any covered field after sealing makes soba verify fail with proof_digest_mismatch.
Older pre-integrity v1 receipts remain readable, but verification reports legacy_unsealed_proof: the structure can be
inspected, but the file is not tamper-evident and is not policy-accepted as verified. Its policy outcome is
partially_verified with exit code 2.
Commands
soba prove
soba prove --last
soba prove --format markdown
soba prove --format json
soba prove .soba/evidence/<id>.soba-proof.json
soba verify
soba verify --format json
soba verify .soba/evidence/<id>.soba-proof.json
soba explain-claim "All TypeScript errors are fixed"
soba explain-claim "All TypeScript errors are fixed" --proof .soba/evidence/<id>.soba-proof.jsonThese commands read persisted proof data only. They do not start the agent runtime and do not require API credentials.
Verification outcomes and exit codes
soba verify checks schema version, IDs and references, command exit codes and output digests, mutation/verification
ordering, diff completeness, permission consistency, secret redaction, and whole-receipt integrity. A well-formed
unverified or blocked receipt is readable but does not pass policy.
Sealed receipts with changed files must include the matching diff summary. Completion criteria without evidence IDs
remain unverified; they cannot make the bundle verified merely because the producer exited successfully.
| Outcome | Stable reason | Exit code |
|---|---|---|
verified | proof_verified | 0 |
| invalid receipt | first validation issue code | 1 |
partially_verified | proof_partially_verified | 2 |
unverified | proof_unverified | 3 |
blocked | proof_blocked | 4 |
Use --format json in scripts. It includes accepted, outcome, reason, exitCode, counts, and validation issues.
Recommended finish standard
For code work, a release-ready SOBA turn should end with:
- a changed-files summary;
- checks that actually ran, including exit status;
- proof or explicit unverified status for each important claim;
- risks that remain after verification;
- permission receipts for sensitive tool calls.
When you need stronger guarantees, write the required checks into the prompt:
Fix the failing parser tests.
Before finishing, run bun test tests/parser.test.ts and bunx tsc --noEmit --pretty false.
If either check fails, do not call the task complete.Permission receipts
Permission receipts record why a tool call was allowed or denied. For dangerous commands, SOBA can also show least-privilege alternatives.
Example:
Instead of approving rm -rf dist && bun run build:
1. allow deleting only ./dist inside the repository
2. run bun run build separately
3. deny external deletion patternsThis keeps local-first delegation bounded: the agent can work quickly, but risky scope stays visible.
Security limits
Proof sealing reduces accidental credential persistence and detects later file edits. It does not prove that a command
was executed on a trusted machine, and redaction is not a universal secret scanner. Avoid putting credentials in prompts
or command arguments, keep .soba/evidence/ private, and treat legacy unsealed receipts as informational.

