Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Capability evidence ledger

SRB records system capability claims in docs/data/capabilities.toml. The ledger is deliberately conservative: source code proves only that a capability is present. Higher claims require current execution evidence.

Promotion ladder

Every lane uses the same contiguous ladder:

  1. present
  2. unit_verified
  3. simulator_verified
  4. real_data_verified
  5. hardware_verified

A lane cannot skip a level. An unearned level carries a reason, owner, requested evidence, and expiry date. Expired blockers remain visible and do not become evidence.

The ledger has twelve lanes. All twelve are currently present, and none has reached its target. Historical reports are useful context, but they do not promote the current tree.

Evidence identity

All source records include the SHA-256 digest of a repository-relative file. Changing or removing that file invalidates the record.

Execution and benchmark records bind to two identities:

  • code_sha identifies the repository commit.
  • scope plus source_sha256 identifies the exact owner-defined input set, including relevant configuration, submodules, data, or dirty-tree state.

The orchestrator computes each current scope digest and passes it to the evaluator. This keeps Git, CI, simulator, data, and hardware orchestration outside the ledger module while preventing results from being combined across different inputs.

Benchmarks additionally record the command, exit code, environment, configuration and artifact digests, failure class, and resource metrics.

Local producer policy

Executable authority is separate from capability status:

  • docs/data/capabilities.toml owns lane metadata, target levels, blockers, and non-executable producer IDs.
  • docs/data/capability_producers.toml owns exact argv, working directory, evidence kind, source roots, benchmark configuration roots, timeout, and maximum evidence age.

The collector accepts a producer ID, not a caller-selected command, level, scope, source list, or exit code. It derives the checked-out Git HEAD, hashes the policy-declared scope, executes argv without a shell, captures the real result and logs, then re-hashes the scope. A source mutation, launch failure, timeout, nonzero exit, policy mismatch, future date, or expired record cannot promote a lane.

Producer kind is required and digest-bound. Execution producers cannot declare benchmark configuration inputs. Benchmark producers must declare a sorted, unique configuration-source subset of their source scope, and external record kind must exactly match that policy.

Each record binds the selected producer digest and the complete policy-file digest. Each report binds those digests again alongside the ledger digest. Every retained execution record has the exact attestation local-unattested. Its digests detect mutation and identity mismatch; they do not authenticate who ran it or authorize CI, merge, release, or readiness acceptance.

Local evidence runs

The executable scripts/capability_gates/run_local.bash runner invokes the three approved local end-to-end producers: python-unit-build, terrain-minimal, and python-packaging. It keeps each lane’s logs and record, runs later lanes after an earlier lane fails, and generates one report from the records that exist. A nonzero gate or report result makes the runner nonzero. Each producer retains its behavior gate and then:

  1. loads its local producer policy and computes the declared source scope;
  2. executes the exact gate argv and captures stdout, stderr, timing, and the actual return code;
  3. writes a content-addressed, local-unattested unit_verified execution record even when the gate fails;
  4. re-hashes that scope and evaluates the canonical ledger with the record;
  5. requires the lane to reach unit_verified;
  6. retains logs, evidence, and the report locally before propagating gate or report failure.

The Python record covers its audit, strict typing, unit, terrain-unit, and ownership gates. The terrain-minimal record covers the explicit no-SciPy assertion and core-only face-budget bake. The packaging record covers uv build --offline --no-python-downloads --wheel --sdist --python <selected-host-python>, producing the wheel and source-distribution gate without sync or download. SRB_PYTHON, when set, selects that interpreter; otherwise the gate resolves python3. The explicit build interpreter prevents implicit selection of an inaccessible project .venv, and the same host interpreter creates the disposable validation venv. Artifacts are written beside the evidence under ignored outputs/ storage, never dist/. The record carries a canonical environment string, a configuration digest over pyproject.toml, uv.lock, and the packaging gate, and an artifact digest over a sorted path/size/SHA-256 manifest. It also records finite, nonnegative wall seconds and artifact bytes. After requiring exactly one wheel and one sdist, the gate creates a trap-cleaned disposable venv outside the artifact directory, installs that wheel with offline/no-dependency controls and an explicit venv interpreter, then verifies the installed srb distribution metadata and import srb. The venv is never part of the artifact manifest. Their evidence is retained per lane, then evaluated together by the local report; local records cannot promote another lane or any higher level.

A nominally successful packaging command with missing, empty, unreadable, or non-regular artifacts is retained as a failed benchmark with stable exit code 87 and an artifact-specific failure class. Command failures, timeouts, and source changes also retain schema-valid benchmark records without promotion. A passing schema-v3, local-unattested packaging benchmark has been retained after the interpreter-selection repair. It is scoped local evidence only: the aggregate evaluator still enforces source freshness and every higher-level blocker. A passing standalone report can promote only this local capability; it is not P2, CI, merge, release, or readiness acceptance by itself.

If a scoped source is mutated during a gate, the record uses exit code 86. If a source is deleted or becomes unreadable before the post-run scope can be recomputed, the collector still writes the schema-valid pre-run record with source_changed_during_gate, exit code 86, and concise scope-error metadata. Pre-run scope failures remain fail-closed and produce no evidence record.

The checked-in ledger remains conservative without that external record. Local records cannot promote a different commit or changed source scope. They remain unattested and cannot represent hosted acceptance. GitHub, scheduled, self-hosted, Rust/ROS, network, Isaac/GPU, SPICE, selected-real-data, and hardware attestation is deferred until the repository is public and an authenticated producer contract is approved.

Evaluation seam

srb.core.capability_ledger.evaluate_capability_ledger is the only public evaluation seam:

from srb.core.capability_ledger import evaluate_capability_ledger

report = evaluate_capability_ledger(
    current_code_sha=commit_sha,
    current_source_digests={
        "python-ci": python_ci_scope_sha256,
        "terrain-data": terrain_data_scope_sha256,
    },
    evidence_paths=[python_ci_evidence_path],
)

The evaluator performs no tests or benchmarks. It validates the ledger, checks source hashes, rejects stale or expired execution evidence, enforces contiguous promotion, and returns frozen dataclasses.

Each report carries:

  • the exact ledger SHA-256 digest;
  • the local producer-policy path and SHA-256 digest;
  • the exact local-unattested attestation;
  • the current commit and sorted source-scope digests;
  • the canonical digests of all external evidence records;
  • the exact required capability levels asserted by the report producer;
  • per-lane effective levels, blockers, and machine-readable issues;
  • a deterministic report_sha256 over the complete report payload.

Persist the JSON from report.to_json() as local engineering evidence. Its checksum provides integrity, not authentication. A report with zero issues is not CI, merge, release, or readiness acceptance, and it cannot by itself authorize any of those decisions.