Commit the previously-untracked standard directories and catalog them in the
root README alongside proof:
- aac/ — communication cargo class: portable boards + a ten-level
offline-first cascade (Apache-2.0 code / CC-BY-4.0 spec).
- map/ — geospatial cargo class: range-requestable signed tilesets +
an F0–F4 fidelity cascade (Apache-2.0 code / CC-BY-4.0 spec).
- sandbox/— isolated, metered, attested execution across the heterogeneous
compute fabric (Apache-2.0 code / CC-BY-4.0 spec).
- jouleclaw-otel-authz, jouleclaw-trust — new jouleclaw reference crates.
Root README now lists aac, map, sandbox, and proof in the catalog, the tree,
and the contribution guide.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
128 lines
6.6 KiB
Markdown
128 lines
6.6 KiB
Markdown
# The attested build loop
|
|
|
|
A coding agent does not take one action — it scaffolds, runs, tests, and fixes,
|
|
across many steps. Every other AI app-builder hands the user the resulting app
|
|
and nothing else: no record of *what the agent did, what it cost, or whether it
|
|
is safe*. This standard defines the missing artifact — a **build receipt**: a
|
|
signed, reproducible, metered account of a whole build, assembled from steps
|
|
that each ran inside the metered+attested sandbox.
|
|
|
|
## What a build is
|
|
|
|
A **build** is an ordered sequence of **steps**, each a unit run under explicit
|
|
grants (§5). Agent-generated code is untrusted, so each step minimizes to at
|
|
least **S2** (§2.3). Each step is executed via the host's run-and-seal path,
|
|
which binds the executor's tier to the grants and produces a sealed receipt, an
|
|
attestation, and a RATS EAT (§6, §7, §7.8).
|
|
|
|
## The build receipt
|
|
|
|
For each step the receipt records the content address of **exactly the unit that
|
|
ran** (`image_id`) and its grants (`grants_id`), the tier, the outcome, the
|
|
energy it cost (the JCR-1 receipt total, honestly tagged per device), the
|
|
attestation id, and the step's EAT. The builder **MUST** verify each step's
|
|
sealed receipt, attestation, and EAT before recording it — the build receipt
|
|
contains nothing unchecked.
|
|
|
|
The build's identity is content-addressed:
|
|
|
|
```
|
|
build_id = BLAKE3( intent ‖ image_id(step_1) ‖ … ‖ image_id(step_n) )
|
|
```
|
|
|
|
so an identical build is identical by address — the **lockfile for generation**
|
|
the category lacks. The receipt is then signed Ed25519 over its JCS-canonical
|
|
form (the family attestation primitive, §7.3), giving:
|
|
|
|
```
|
|
BuildReceipt {
|
|
profile: "sandbox.build/1",
|
|
build_id, intent, steps: [StepRecord],
|
|
total_energy_uj, tier_max, prev, host_id, at_unix_us
|
|
}
|
|
```
|
|
|
|
## Coding-op provenance
|
|
|
|
A step **MAY** carry the **coding op** it represents — the agent's edit: the
|
|
`path`, the content addresses of the file before and after, and the `author`
|
|
(the model or agent that produced it). The op is content-addressed (`op_id`) and
|
|
recorded in the step, so it is **signed into the build receipt**: the receipt
|
|
attests not just *what ran* but *what changed and what made it* — the code
|
|
lineage the category's "black box" lacks. The op is provenance, not execution
|
|
identity, so it does not affect `build_id` or the cache key.
|
|
|
|
## The build ledger
|
|
|
|
Build receipts chain into an append-only **build ledger**: each receipt's `prev`
|
|
is the previous build's `build_id` (the genesis id for the first). A verifier
|
|
walks the chain, checking every signature and every link — a tamper-evident
|
|
account of every build in order. The reference provides both an in-memory ledger
|
|
and a **durable, file-backed** one (`FileBuildLedger`) that persists the chain as
|
|
JSONL, re-verifies it on open, and refuses to load a tampered file;
|
|
`verify_ledger_file` (and the `sandbox-build verify` / MCP `verify_ledger`
|
|
surfaces) re-check a persisted ledger independently. This is the "verifiable
|
|
record of how the app came to be" that regulated use (and EU AI Act energy
|
|
disclosure) requires and that no incumbent produces.
|
|
|
|
## What it answers
|
|
|
|
- **Provenance** — a signed record of what ran, step by step, addressable and replayable.
|
|
- **Energy** — per-step and total joules, from the §6 receipts (SCI-aligned, consumer-side).
|
|
- **Reproducibility** — the build is pinned by content id; the same intent + steps reproduce the same `build_id`.
|
|
- **Isolation + safety** — every step ran under deny-by-default capabilities at the minimized tier; nothing executed outside the sandbox.
|
|
- **Portability** — the receipt and ledger travel with the artifact; ownership is the *account*, not just the files.
|
|
|
|
## Deterministic-first (the cascade)
|
|
|
|
A build resolves each step at the cheapest tier that closes it, and records
|
|
which tier did:
|
|
|
|
- **L0 — cache.** A step is content-addressed by `(image ‖ grants ‖ trusted)`.
|
|
Because a sandbox run is deterministic, an identical step yields an identical
|
|
result, so a prior attested result is reused with **no new execution and no
|
|
new energy** — provenance-as-cache.
|
|
- **L1 — deterministic execution.** Otherwise the step runs in the sandbox.
|
|
Execution *is* the verification; the result is attested and cached.
|
|
|
|
A frontier model is **never invoked inside the sandbox** — generation (the part
|
|
that needs a model) happens upstream in the agent surface, outside the metered
|
|
boundary. So a build's cost is compute joules, and re-running an identical build
|
|
costs **zero** new joules and makes **zero** model calls. The receipt carries
|
|
`executed_energy_uj` (joules actually spent) alongside `total_energy_uj`; the
|
|
difference is what the cache saved. This is the standard's structural answer to
|
|
the category's re-prompt / token-burn cost leak: it is recorded, signed, and
|
|
auditable, not hidden in opaque credits.
|
|
|
|
## Wasm steps and command steps
|
|
|
|
A step runs at the tier its work requires. A **wasm step** runs a unit in the
|
|
S2 sandbox (the default for agent-generated units). A **command step** runs a
|
|
real program — `cargo test`, `npm run build` — in the **S5 microVM**, for
|
|
attesting non-wasm source builds: the command is supervised as an isolated guest
|
|
(Firecracker on Linux+KVM; a process VMM elsewhere), its CPU metered, and the
|
|
run sealed at S5 (an escalation above the grant floor — the host attests it ran
|
|
in the microVM). Either way the step lands in the same signed receipt, content-
|
|
addressed (a command by `program ‖ args`), cached, and carrying its EAT — so one
|
|
build can span S2 wasm and S5 source-build steps and the receipt's tier floor is
|
|
the highest any step required.
|
|
|
|
## Speculative branching
|
|
|
|
A step **MAY** carry several candidate implementations. The build races them
|
|
**cheapest-first** and keeps the first that **verifies** (outcome `Completed`);
|
|
candidates after the winner are not run. The joules spent on losing candidates
|
|
are recorded as `speculative_energy_uj` — per step and summed on the receipt.
|
|
This is the honest posture of `jouleclaw-agent-app`: speculation trades energy
|
|
for confidence/latency, and that trade is **disclosed**, not hidden. Where the
|
|
category's tools silently burn tokens re-prompting a forgotten context, a
|
|
Sandbox build records "raced N candidates, kept the verified one, spent X µj on
|
|
the losers" — a number an auditor can see.
|
|
|
|
## Reference
|
|
|
|
`sandbox-build` implements the loop (`run_build`, `BuildReceipt`, `BuildCache`,
|
|
`BuildLedger`, `verify_build_receipt`) and ships a headless CLI. The MCP server
|
|
(`spec/mcp.md`) exposes it as the **`build`** tool, so an agent surface drives a
|
|
build and receives the signed receipt as the tool result — the backend an
|
|
editor such as agent-zed calls.
|