Compilation Is Not Assurance: What Agentic Rust Needs After the First Green Build
AI-assisted coding looks fastest when we stop the clock too early. A model can scaffold a crate, implement a trait, generate tests, and reach a green cargo check before a human engineer has finished tracing the existing ownership model. That is a real capability. It is also a poor measure of completed engineering work. Senior systems developers care about the rest of the path: - Is the ownership model intentional, or did the implementation clone its way out of a lifetime problem? - Is shared state necessary, and are lock scope and contention understood? - Can malformed input turn into a process-wide panic? - Does the change preserve latency and allocation budgets? - Do tests establish the intended property, or merely reproduce the new implementation? - Can another engineer reconstruct why the design was accepted? - How much review and remediation did the apparent acceleration consume? On 5 August 2026, Rust engineer Erik-Jan van de Wal described exactly this gap. His post called out agents reaching for .clone() , Arc > , unsafe trait implementations, and unwrap() when the actual task required reasoning about ownership, concurrency, and production failure. He also reported that token spend and fifteen additional hours of cleanup made his AI-assisted path roughly twice as expensive as writing the code himself. Those are his reported results, not a general industry benchmark, and the conclusions in this article are mine rather than his. Read Erik-Jan van de Wal's post. His larger point is difficult to dismiss: generated code is being counted as progress while verification, architectural repair, and operational risk remain off the productivity ledger. One way we are trying to correct that accounting in our work is the Agent Assurance Profile, or AAP. Its premise is simple: Code is not ready for operational trust merely because it compiles. It becomes reviewable when important claims are connected to evidence another process can inspect, and residual judgment is explicit. AAP does not make a model understand Rust. It does not convert a prompt into a proof, and it does not replace senior review. It changes the protocol around agentic work so that plausible output is not accepted as its own evidence. Three layers that must not be confused Before describing the mechanics, it is important to separate three layers that are often collapsed in discussions about agent assurance. The first is the DAG-TOML specification and its draft profiles. The public agent-assurance repository defines document kinds, profiles, invariants, and validators. The implementation DAG and traceability documents come from core specification, the cost record comes from cost profile, and AAP composes them for agent assurance. The second is an emitter implementation. agent-assurance-dsrs is the Rust workspace where we execute and evaluate DSPy-style programs, then emit a concrete subset of those documents as sidecars. It shows that runtime results can be mapped into validator-compatible assurance artifacts without coupling runtime types to governance schemas. The third is a team's assurance policy. Rules such as "no lock guard across an await", "no unreviewed unsafe trait implementation", or "p99 latency may not regress by more than five percent" are not automatically supplied by AAP. A team must define those claims, choose suitable evidence, protect the acceptance policy, and decide which residual risks require human approval. The specification and profiles supply a language. The emitter supplies data in that language. The policy determines what the data must establish. From instructions to claims Repository instructions still matter. An agent should be told which modules are security-sensitive, which APIs are stable, where allocation matters, and what style the project expects. But instructions exist inside a probabilistic context. A rule such as: Do not introduce Arc > without architectural justification. does not establish whether the model noticed the rule, whether the edited path was covered by it, whether the lock survives an .await , or whether contention remains acceptable under load. A model can violate the constraint, apologize, revise the patch, and declare success without leaving durable evidence that the final result complies. AAP treats the instruction as an input. Assurance begins when it becomes a precise claim with an enforcement or review path. For example: claim: no synchronous lock guard crosses an async suspension point scope: crates/runtime/src/** evidence: - clippy::await_holding_lock result - targeted async integration tests - reviewer approval for synchronization changes Even this claim needs qualification. The Clippy lint catches particular structural patterns; it is not a proof that every concurrency interaction is safe. The tests exercise recorded cases; they do not cover every schedule. The human review remains part of the evidence chain because architecture has not become a lint. That is the discipline AAP encourages: say exactly what is claimed, identify what supports it, and leave the limits visible. The assurance graph An assurance package is useful when its documents form a connected graph rather than a folder of ceremonial files. requirement | v implementation unit | v changed code | v verification command | v test, analysis, or benchmark result | v assertion | v gate decision A reviewer should be able to traverse the graph in both directions. Starting from a requirement, they can find the implementation and evidence that claim to satisfy it. Starting from a changed synchronization primitive, they can find the requirement that authorized it and the checks that exercise it. Missing edges are useful information. A critical requirement without evidence is incomplete. A test attached to no claim may be irrelevant. A changed file mapped to no authorized unit may indicate scope expansion. The implementation DAG: bounded work instead of open-ended agency Agentic coding is most dangerous when the assignment is broad enough for the model to redefine success while working. βImprove the runtime architectureβ is not an executable contract. It permits nearly unlimited reinterpretation. DAG-TOML represents implementation as a directed acyclic graph of bounded units. Each unit can carry: - an identifier; - a concrete objective; - dependency relationships; - files it may create or modify; - acceptance criteria; - required evidence; - status; - and outputs consumed by later units. For example: U01: establish provider-neutral error taxonomy ββ U02: implement retry classification ββ U03: add bounded retry wrapper ββ U04: verify retry accounting ββ U05: approve release gate The graph has several advantages over an ordinary checklist. First, it makes ordering explicit. The agent cannot credibly validate retry accounting before retry behavior exists. Second, it exposes parallel work without inventing independence. Two tasks may run concurrently only when their dependency edges permit it. Third, it creates scope boundaries. If the unit authorizes changes to the provider adapter and tests, an unsolicited rewrite of the runtime state model becomes detectable scope expansion. Fourth, it gives failure a location. A gate can fail because a particular unit lacks evidence rather than because an agent vaguely reports that βsome tests still need attention.β This does not prevent an agent from making a bad edit. It makes the edit easier to classify as unauthorized, unsupported, or incomplete. That is the profile's intended use, not a claim that every current emitter produces a rich plan. The default agent-assurance-dsrs demo emits a single completed unit with no dependency edges and an empty file scope. Separately, we use a hand-authored 34-unit implementation DAG to record and partly govern its development. The former demonstrates runtime emission; the latter demonstrates multi-unit planning. They should not be presented as the same capability. What agent-assurance-dsrs actually implements agent-assurance-dsrs is an eight-crate Rust workspace: - dsrs-core supplies typed examples, predictions, signatures, module traits, run context, callbacks, batching, parameter traversal, and state persistence. - dsrs-lm supplies the LM boundary, structured adapters, provider-neutral errors, caching, usage records, retry handling, OpenAI and Anthropic clients, reasoning modules, tools, streaming, and optional native process sandboxing. - dsrs-evaluate runs sequential evaluation and records metric results. - dsrs-optimize implements few-shot, ensemble, COPRO, MIPROv2, GEPA, and SIMBA optimization surfaces. - dsrs-retrieve provides exact cosine, LSH, ColBERT-style, and HTTP vector-store retrieval. - dsrs-datasets provides dataset loading and parsers for HotPotQA, GSM8K, and MATH. - dsrs-assurance maps evaluation data and run events into assurance sidecars. - dsrs-cli wires the pieces together for hermetic and optional live-provider demonstrations. Network, async, and native-sandbox behavior remain off by default. Dedicated CI lanes exercise them without making the ordinary workspace build depend on provider access, Tokio, or platform-specific sandbox libraries. The default demo evaluates a fixed Predict program using a deterministic EchoLm and ExactMatchMetric , uses the same run context for MIPROv2 search and LSH retrieval, parses SSE separately, and records caller-declared capability labels rather than inferring them from run events. A separate credentialed workflow tests a real OpenAI call and, when configured, an Anthropic call, then runs the live demo and validates its sidecars. The current emitter writes eight TOML documents: - implementation DAG; - traceability; - smoke validation; - evidence matrix; - adapter contract; - assertion bundle; - gate decision; and - cost record. It also writes raw evaluation and run-event JSON. The adapter contract contains declared metadata (the sandbox, network, and clock fields are not observations from the demo). Threat m
Comments
No comments yet. Start the discussion.