open-standards/jcp/jcp-rs/crates/jcp-orchestrate/MAPPING.md
Transaction Science c3b94b236b jcp-orchestrate: seal budget denials instead of pre-filtering them away
The joule ceiling is JCP's flagship enforcement, and the spec's contract is that
every decision is sealed, allow and deny alike. dispatch() did not honour that.
route() pre-filtered out any harness whose remaining budget could not cover the
task's quote, so an over-budget harness never reached runtime.decide() -- the
ceiling fired, the loop failed over, and no receipt recorded that it had. The
enforcement happened; the audit of it did not.

Replace route() with candidates(), which filters on capability only. dispatch()
now offers the task to each granted harness in turn, letting the runtime make and
seal the decision -- so a harness that cannot pay is denied on the record before
the loop fails over to one that can. Denied dispatches are still not debited
(Runtime::decide only debits on allow), so per-harness joule totals are unchanged.

One refusal deliberately seals nothing: a task whose kind no registered harness
holds. There is no grant to decide against, and JCP seals decisions about a
grant, not the absence of one. It is recorded denied in the RunReport instead.
Module doc and MAPPING.md now state both cases precisely rather than claiming a
blanket allow-and-deny seal.

Two regression tests: budget_denials_are_sealed_not_silently_skipped (the deny
lands in the ledger, verifies under the steward key, and is not debited) and
ungranted_kind_seals_nothing. All six pre-existing tests pass unchanged. The
background_agents example now shows 7 sealed decisions, up from 6 -- the seventh
being the budget denial that used to disappear.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-12 14:31:31 -04:00

9.1 KiB
Raw Permalink Blame History

The background-agent orchestrator pattern → jcp-orchestrate

jcp-orchestrate does not invent an orchestration shape. It ingests the one the agent-work ecosystem converged on — a background-agent orchestrator that runs coding agents in the cloud — and supplies the three things every deployed instance of that pattern lacks: a capability gate, a joule budget, and a sealed audit.

This document maps the pattern — as built by the production background-agent orchestrators — onto (1) this crate's reconcile loop, (2) the Sandbox S0–S7 isolation ladder its container model sits low on, (3) the Joule Table seams its UX surfaces never carried, and (4) the JCP grant its credential model stops short of — then scopes the frontier the whole category leaves empty.

0. Why map a commodity pattern

The background-agent orchestrator is a well-worn shape: a tracker of work items; each item run by a coding agent in an isolated container on its own repo copy, auto-branched, checkpointed to a forge as machine-authored commits and pull requests; a CLI for local handoff that doubles as an MCP server; bring-your-own subscription or API keys; recurring and event-triggered automations; chat and forge @-mention bindings. Several products shipped exactly this. The shape is not in dispute and not a moat — it is commodity.

What none of them produced is the durable artifact: a signed, energy-accounted, verifiable receipt of what ran, under whose authority, for how many joules. Everyone can build the orchestrator; the accountability is the open lane. This crate keeps the loop and makes each dispatch a JCP decision made outside the agent.

1. The reconcile loop → Orchestrator (ingest, not compete)

The pattern's control plane is a tracker → route → dispatch → retry loop over a heterogeneous fleet, where a worker is one coding-agent backend on one item and a different backend on the next. Orchestrator keeps that loop and gates every dispatch.

Background-agent orchestrator concept jcp-orchestrate symbol What TX adds
Work tracker, one branch per task Task { id, kind, payload } + the sealed decision ledger (receipts()) The run is an auditable ledger of sealed decisions, not just a branch list
A coding-agent backend (any CLI/framework) Harness — any backend that quotes a joule cost and reports an outcome The orchestrator is blind to what runs inside; backends are registered, not hardcoded
Assign a task to a backend dispatch decided against a grant, outside the backend (route → gate) Who-runs-what is a runtime authorization, never the agent's own choice
Retry on failure bounded retry + failover through a sealed denial to a backend still under budget An exhausted backend is denied on the record, then fails over; a flaky one retries to max_attempts
Bring-your-own subscription / API key Capability (task kinds) + budget_uj per backend Authority, not just authentication — see §4
Unbounded agent loop (the documented cost failure) joule budget debited + enforced before the side effect A hard, pre-side-effect energy ceiling per grant
Machine-authored commit / PR as the record JCR-1 receipt sealed per decision, allow and deny The non-repudiable audit a git history cannot be

Net: the pattern is what the loop looks like in production; Orchestrator is the same loop with the gate, the budget, and the sealed audit the meta-harness leaves to the platform. The background_agents example drives it end to end.

What is and isn't sealed. Every decision made against a grant is sealed — the allow, and the deny when a backend is out of budget or out of scope. Budget enforcement in particular must leave an artifact: a joule ceiling that fires silently is an enforcement nobody can audit, so a backend that cannot pay is denied through the runtime and that denial is on the record before the loop fails over to the next. The one refusal that seals nothing is a task whose kind no registered backend holds: there is no grant to decide against, and JCP seals decisions about a grant, not the absence of one. Such an item is recorded denied in the RunReport and never reaches a backend.

2. Container isolation → Sandbox S0–S7 (attested execution)

The pattern isolates each task in a container with its own repo copy. On the Sandbox ladder that is roughly S2–S3: namespace/cgroup isolation, no attested boot, no measured execution, no energy-counter provenance. The container keeps tasks from colliding; it proves nothing to a third party about what ran.

Pattern isolation Sandbox rung The step up
Container, own repo copy ~S2/S3 (namespace isolation) Integrity asserted by the host, attested to no one
— S5 — microVM (proven on real bare-metal KVM + RAPL) A hardware-isolation domain with a measured boot; a receipt can name the image that ran
— S6 — TEE attestation (sandbox-tee::energy) An EnergyStatement bound into a TEE report's report_data; the honest IntegrityAttested vs PhysicallyRooted trust ladder

The move is not a better container. It is running the same task inside an S5 microVM under an attested boot, and binding the energy reading's provenance into the receipt. The pattern's isolation stops at "tasks don't collide"; the ladder continues to "a third party can verify what ran and what it cost."

3. The UX surfaces → Joule Table seams (gate / meter / receipt)

The surfaces the pattern converged on are the right surfaces — they are simply unmetered, ungated, and unsealed. Each rebinds through an existing binding, and each gains the three seams the bare orchestrator never had.

Pattern surface Joule Table binding The three seams it gains
Local-handoff CLI + MCP task server Joule Hook (editor/host binding) gate = grant on task creation; meter = joules per task; receipt = MCP receipt server
Chat / forge @-mention kicks off a task Joule Desk (teammate binding) signed-grant authority for the mention; a per-receipt-verifiable ledger of what the teammate did
Recurring + event-triggered automations Durable agent execution (Sandbox + JCP) durable resumable runs, env-manifest identity, standing grants with a joule ceiling, mid-run steering
Browser streaming / notifications mid-run steering over an attested run monitoring becomes attested control

The pattern proved the surfaces convert. It never made any of those actions accountable. The seams are exactly that missing accountability.

4. Credentials → JCP grant (authentication → authority)

Bring-your-own subscription answers who is paying — an identity with a quota at a vendor. A JCP grant answers what this principal may do, for how many joules, decided where the model can't reach: a capability and an energy budget are the same signed, bounded, debited object. A vendor key lets an agent run until the bill stops it; a grant denies the action itself — an out-of-scope task kind, or one over the joule ceiling — before the side effect, and seals both the allow and the deny. Auth says "the card works"; the grant says "this action, this budget, this receipt."

5. The frontier the pattern leaves open

The background-agent orchestrators shipped every convenience and none of the trust layer. The empty lane is the one no instance of the pattern occupies: a per-run, per-task, energy-accounted, attested, third-party-verifiable receipt of agentic work — efficiency/1 rolled up from JCR-1 decisions, with the energy counter's provenance attested through sandbox-tee. No competitor issues it; regulation mandates nothing per-task; the category publishes rates, not outcome-anchored receipts.

6. A conformant flow (the profile in one paragraph)

Register each coding-agent backend as a Harness with a capability (the task kinds it may handle) and a joule budget. Track work items as the pattern does; run the reconcile loop, but make every dispatch a JCP decision against that grant, sealed as JCR-1 before the task runs. Run the task inside a Sandbox S5 microVM under an attested boot, with the energy reading's provenance bound via sandbox-tee::energy. Roll the per-task receipts up with aggregate() into an efficiency/1 figure (uj_per_accepted_token, waste share, outcome anchor). Rebind the surfaces — local-handoff/MCP through Joule Hook, chat/forge through Joule Desk, automations through Durable agent execution — each carrying gate / meter / receipt. The result is the pattern's exact UX, with the one thing it structurally could not produce: a signed, energy-accounted, verifiable record of every action.

Status

  • Reconcile loop + capability/budget gate + sealed ledger — shipped (src/lib.rs).
  • End-to-end demonstration — shipped (examples/background_agents.rs).
  • Sandbox rung integration (run the harness inside an S5 microVM) and the efficiency/1 roll-up — the composition this document scopes; the primitives (sandbox-tee::energy, jcp-efficiency::aggregate) are already shipped in their own crates.