Skip to content

Repository files navigation

HonestBao Evidence Gate

No proof, no "done."

HonestBao is a deterministic, local-first evidence gate for AI coding agents. It does not try to decide whether every sentence an AI produces is true. It checks a narrower boundary that software can verify: whether explicit completion claims are supported by fresh evidence from the current working tree.

Chinese product name: 誠實豆沙包. CLI and package name: honestbao.

HonestBao at a glance

HonestBao verification run

P0-P4 status

The deterministic core, public-alpha surface, hardening, signed review closure, and read-only release preflight are implemented:

  • JSON Schema validation for policies, completion envelopes, and receipts
  • repository fingerprinting over HEAD, scoped Git state, file content, file mode, and policy hash
  • file_exists, git_diff, shell-free command, and human_review collectors
  • deterministic VERIFIED / BLOCKED / CONTRADICTED / NEEDS_HUMAN / ERROR evaluation
  • stale-evidence detection after repository, policy, or collector changes
  • zero-write verification by default: policy and envelope may live in an external sidecar, and no .honestbao directory is created
  • opt-in append-only .honestbao/ledger.jsonl with receipt hash chaining
  • self-contained receipt semantics: each evidence item records its failure mode and reason, and receipt validation recomputes the verdict
  • CLI text and JSON projections of the same receipt
  • bounded command time/output, executable and environment allowlists, secret redaction, path-containment checks, and source-change race detection
  • read-only loopback viewer with English and Traditional Chinese projections
  • macOS and Linux CI definitions for Node.js 20 and 22
  • a reusable agent completion contract and consumer GitHub Actions example
  • automatic fail-closed command isolation: every command uses macOS sandbox-exec or Linux bubblewrap with denied network, a read-only filesystem, and isolated temporary storage
  • two-party repository-write consent: both policy writablePaths and the runtime --allow-repository-writes flag are required
  • detached Ed25519 receipt attestations; private keys stay outside the repository and never enter receipts or the ledger
  • signed Ed25519 human-review decisions bound to one unresolved receipt, task, check, claim, source fingerprint, policy, and collector specification
  • deterministic instruction packets for Codex and Claude Code; adapters map registered claim IDs and argv but never decide the verdict
  • honestbao doctor checks Node, repository scope, policy paths, command availability, Git requirements, sandbox enforcement, review keys, and ledger integrity without executing policy commands or creating runtime state

Requirements

  • Node.js 20 or newer
  • Git when repository identity or git_diff evidence is required
  • macOS with /usr/bin/sandbox-exec, or Linux with bubblewrap, for every policy containing a command check

Install from source

npm ci
npm test
npm pack

Install the resulting tarball in a target project without waiting for a public registry release:

npm install --save-dev /absolute/path/to/honestbao/honestbao-0.7.0.tgz
npx honestbao --version

The test suite uses temporary Git repositories and covers current proof, missing files, failed commands, timeouts, output limits, path traversal, disallowed executables, source mutation during collection, policy drift, secret redaction, immutable freshness assessment, CLI exit codes, and ledger mutation. It also executes filesystem and loopback-network isolation tests, detached signature tampering tests, and both supported agent instruction adapters. Signed-review tests also cover approval, rejection, source and policy drift, wrong or malformed trust keys, forged ledger references, and receipt v2 compatibility. Doctor tests cover invalid policies, path escape, missing allowlisting, sandbox enforcement, review trust, ledger corruption, and read-only CLI behavior.

Zero-write default

honestbao doctor and honestbao verify do not create, modify, rename, or delete anything in the target repository by default. Internal Git inspection uses no-optional-lock mode and disables fsmonitor and untracked-cache updates, so it does not refresh .git/index. Every policy command is placed in an OS sandbox with network denied and the host filesystem read-only, including when the policy omits a sandbox object.

For a zero-footprint integration, keep policy and envelope files outside the target repository and pass their absolute paths:

npx honestbao doctor \
  --root /path/to/project \
  --policy "$HOME/.config/honestbao/my-project/policy.json"

npx honestbao verify \
  --root /path/to/project \
  --policy "$HOME/.config/honestbao/my-project/policy.json" \
  --envelope "$HOME/.config/honestbao/my-project/completion.json" \
  --json

Only these explicit operations write target-repository state:

Operation Explicit consent Target write
Initialize an in-repository policy honestbao init honestbao.config.json
Persist a receipt verify --ledger .honestbao/ledger.jsonl
Persist a signed review review sign --write Policy-configured review JSON
Persist an attestation attest sign --output <path> Requested attestation JSON
Let a collector write Policy writablePaths and --allow-repository-writes Only pre-existing declared subpaths

Package installation is performed by the user's package manager and is outside HonestBao's runtime write boundary.

Quick start

init is an explicit convenience command for users who want the policy checked into the target repository:

npx honestbao init --root /path/to/project

Edit /path/to/project/honestbao.config.json so its task, claims, paths, and structured command specifications describe that project. Before running any evidence command, preflight the local setup:

npx honestbao doctor --root /path/to/project
npx honestbao doctor --root /path/to/project --json

The policy may instead stay in an external sidecar as shown above. doctor exits 0 when no blocking setup fault exists and 5 when a required runtime, path, command, sandbox, key, or ledger check fails. An empty ledger and a supported non-Git setup are warnings, not false failures. The command does not execute policy commands, append a receipt, create .honestbao, or make a network request.

Then create a completion envelope such as:

{
  "contractVersion": "1",
  "taskId": "checkout-timeout",
  "claims": [
    "implementation-exists",
    "regression-test-passes",
    "user-facing-behavior-reviewed"
  ],
  "summary": "Checkout timeout recovery is ready for verification."
}

Run the gate from any directory:

npx honestbao verify \
  --root /path/to/project \
  --envelope completion.json

This prints the receipt and does not persist it. Every command check is isolated automatically. A policy only needs a sandbox object when it requests a narrow writable subpath:

{
  "sandbox": {
    "network": "deny",
    "filesystem": "read_only",
    "writablePaths": ["scratch"]
  }
}

Every writablePaths entry must already exist and resolve inside the repository. The repository root, .git, and .honestbao cannot be made writable. The command still fails with REPOSITORY_WRITE_NOT_AUTHORIZED unless the same run also includes the explicit runtime capability:

npx honestbao verify \
  --root /path/to/project \
  --envelope completion.json \
  --allow-repository-writes

Machine-readable output:

npx honestbao verify \
  --root /path/to/project \
  --envelope completion.json \
  --json

Persist a receipt only when local history is wanted:

npx honestbao verify \
  --root /path/to/project \
  --envelope completion.json \
  --ledger

Inspect the latest receipt against the current repository without rewriting the historical receipt:

npx honestbao inspect --root /path/to/project

Validate every ledger line and hash-chain link:

npx honestbao ledger verify --root /path/to/project

Open the read-only local viewer:

npx honestbao view --root /path/to/project

Generate a deterministic completion packet for an agent:

npx honestbao instructions --root /path/to/project --task checkout-timeout --agent codex
npx honestbao instructions --root /path/to/project --task checkout-timeout --agent claude-code --json

Sign the latest ledger receipt with a private key stored outside the repository, then verify it with the corresponding public key:

npx honestbao attest sign \
  --root /path/to/project \
  --private-key "$HOME/.config/honestbao/signing-key.pem" \
  --output .honestbao/latest.attestation.json

npx honestbao attest verify \
  --root /path/to/project \
  --public-key /path/to/signing-key.pub.pem \
  --attestation .honestbao/latest.attestation.json

The signature authenticates exact receipt bytes. It does not say that an older receipt is still fresh; use honestbao inspect for current freshness.

To let an authorized reviewer close a human_review check, bind the check to a repository-owned public key and a runtime decision path:

{
  "id": "user-review",
  "claimId": "user-facing-behavior-reviewed",
  "type": "human_review",
  "required": true,
  "paths": ["src"],
  "invalidation": "repository_fingerprint",
  "review": {
    "decisionPath": ".honestbao/reviews/user-review.json",
    "trustedPublicKeyPath": "honestbao-reviewer.pub.pem"
  }
}

The first verification explicitly records unresolved review evidence. An authorized human then signs that exact ledger receipt with an external private key; HonestBao writes only the policy-configured decision file after --write is supplied:

npx honestbao verify --root /path/to/project --envelope completion.json --ledger

npx honestbao review sign \
  --root /path/to/project \
  --check user-review \
  --decision approved \
  --private-key "$HOME/.config/honestbao/reviewer.pem" \
  --write \
  --note "Reviewed the current user flow."

npx honestbao verify --root /path/to/project --envelope completion.json

A current approval can close the gate. A rejection contradicts the claim. Any source, policy, or collector drift makes the decision stale. Invalid keys, signatures, or ledger references fail closed. Legacy human_review checks with no review contract continue to return NEEDS_HUMAN.

Agent instructions are available in examples/agent-completion-instructions.md. Projects that install HonestBao as a locked development dependency can start from examples/github-actions/honestbao.yml. HonestBao's own cross-platform workflow also runs npm run self:verify. That command completes the full test suite first, then uses HonestBao to verify the compiled CLI and package dry-run without writing a ledger.

Stable exit codes

Code Result Meaning
0 VERIFIED Every claimed check has current supporting evidence
2 BLOCKED Evidence is missing, stale, failed, timed out, or too large
3 CONTRADICTED Current evidence conflicts with a claim whose policy says so
4 NEEDS_HUMAN Automatic evidence passed, but review is still required
5 ERROR Policy, envelope, ledger, path, or collector could not be evaluated safely

An agent may say "verified complete" only after exit code 0. It should report the returned reason and next action for every other code.

For honestbao doctor, exit code 0 means the local setup is ready to run the gate; it is not a verification receipt. Exit code 5 means preflight found a blocking setup fault.

Security boundary

  • Commands are an executable plus an argument array. HonestBao never invokes a shell and rejects shell executables even if a policy attempts to allow one.
  • Command execution inherits only environment names explicitly allowlisted by the policy.
  • Configured secret values are replaced before stdout or stderr reaches a receipt.
  • Secrets must be supplied through allowlisted environment variables, never as command arguments or literal policy values.
  • Paths must resolve inside the repository, including through symlinks.
  • .honestbao, .git, node_modules, and coverage output are excluded from source fingerprints. Source-bound checks cannot target those excluded paths.
  • A repository mutation during collection produces ERROR; it cannot become a green result.
  • If a Git working tree is present, failures while reading HEAD or scoped status fail closed as COLLECTOR_ERROR; they are never treated as a clean repository. Git inspection disables optional locks, fsmonitor, and untracked-cache updates. Non-Git directories remain valid for non-Git checks.
  • Every command is sandboxed and never falls back to ordinary execution. Missing or unusable OS isolation produces SANDBOX_UNAVAILABLE or SANDBOX_SETUP_FAILED.
  • Repository writes require both an existing policy-declared writable subpath and explicit runtime authorization. Neither consent alone is enough.
  • Detached attestations use Ed25519 and identify the public key by its SPKI SHA-256 hash. HonestBao does not generate, upload, or assign trust to keys.
  • Signed review closure trusts the repository-bound public key and whoever controls its matching private key. The private key must remain outside the repository and inaccessible to the agent being reviewed.

HonestBao itself makes no network request. Every command receives enforceable network denial and read-only filesystem isolation.

honestbao doctor may perform a bounded local Git inspection and an OS sandbox isolation probe. It never executes a command from the policy and never writes repository or ledger state.

Protected Not protected
Zero-write doctor and default verify Explicit init, --ledger, --write, --output, or double-authorized writable paths
Shell-free argv execution A malicious sandbox backend or compromised operating system
Automatic network and filesystem write isolation Read confidentiality: allowed executables can read host files visible to the OS sandbox
Executable and environment allowlists Malicious behavior inside an explicitly allowed executable beyond this boundary
Repository path and symlink containment A malicious repository or machine owner
Runtime and output bounds Compromised operating systems
Secret redaction before receipt persistence Secrets placed directly in argv or policy text
Source, policy, and collector freshness Requirements absent from the policy
Receipt hash-chain integrity and detached Ed25519 signatures Signer identity, key custody, or remote attestation
Signed human decisions bound to unresolved ledger evidence A dishonest reviewer or compromised review private key

Project map

The package also exposes its typed library API from honestbao; consumers do not need to import internal dist/ paths.

Receipt contract v2 remains readable and keeps verdict semantics self-contained. Receipt v3 adds signed human-review metadata; it deliberately does not accept the earlier experimental v1 shape.

Explicit limits

HonestBao does not eliminate hallucinations. It does not prove product quality, business correctness, security, or user satisfaction unless the policy captures suitable evidence. The local hash chain detects accidental drift and ledger mutation. A detached signature authenticates receipt bytes to a supplied public key, but neither mechanism defends against a malicious machine owner, compromised operating system, stolen signing key, or intentionally dishonest policy author. A signed review proves that the matching key approved or rejected one bound receipt; it does not prove reviewer identity, competence, or honesty.

About

Deterministic, local-first evidence gate for AI coding agents. No proof, no done.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages