Skip to content

mentra v0.10.0 — agentic-core hardening

Choose a tag to compare

@WendellXY WendellXY released this 16 Jul 10:21
· 385 commits to main since this release
Immutable release. Only release title and notes can be modified.

mentra v0.10.0 / mentra-provider v0.4.0

Mentra 0.10 hardens the agentic core while preserving its architectural
contract: Mentra remains the sole owner of the model/tool loop, new host seams
stay generic, and default behavior changes only where explicitly documented
below.

This combined release covers the five hardening workstreams and the Proposed
coding-tools,
reasoning-preservation,
and host-orchestration
design records.

Highlights

Runtime hygiene and shell validation

  • Remove the orphaned 5,924-line provider source tree. The live adapters remain
    in mentra/src/provider.rs and continue to delegate to mentra-provider.
  • Add opt-in ShellValidationMode::{Off, Warn, Enforce} classification for
    builtin foreground and background shell execution.
  • Validation enriches authorization previews and reuses the existing
    allow/prompt/deny vocabulary and hooks. Off remains the default.
  • Shell classification is defense-in-depth and permission UX, not a security
    boundary; runtime roots, environment isolation, and process controls remain
    the enforcement boundary.

Universal tool-result limits

  • Apply one output boundary to successful and error results from builtin,
    custom, and MCP tools, including parallel batches.
  • Defaults are 2,000 lines and 50 KiB per result. Truncation retains complete
    lines and appends an actionable notice; under-limit output is byte-identical.
  • Oversized structured JSON is never sliced. When spill succeeds, it is written
    whole and replaced by text pointing to the artifact; otherwise the text
    notice explains why the full output was not saved.
  • Volatile stores suppress disk spill to preserve their no-durable-trace
    contract. The existing shell stream-capture cap remains separate and applies
    before this result boundary.

Model-conventional coding tools

  • Add opt-in read, ls, grep, glob, write, and edit tools over the
    existing transactional WorkspaceEditor.
  • FileToolProfile::{Batched, Split, Both} controls the advertised surface;
    Batched remains the default. Read operations use the parallel lane, while
    write and edit use exclusive local mutation.
  • Grep gains file filters, literal and case-insensitive modes, context,
    multiline regex, and a Unicode-safe 500-character cap per rendered physical
    line.
  • Split edit validates all matches against the original content, rejects
    ambiguity, overlaps, and no-ops, preserves BOM/CRLF, and supports an
    NFKC/smart-punctuation fallback.
  • Diffs, patches, and first_changed_line remain local ToolOutput::details;
    providers receive only a short summary.
  • Recursive list, search, and glob traversal now reject descendant symlinks
    that escape configured read roots. This is an intentional default-path
    policy fix.

move and delete remain batched-only. Historical files.replace keeps its
exact-match semantics and does not gain fuzzy editing.

Thinking and reasoning continuity

  • Add externally tagged ContentBlock::Thinking plus streaming start/delta
    variants and persistence/replay support.
  • Capture and replay Anthropic signed/redacted thinking and OpenAI Responses
    reasoning items, summaries, IDs, and encrypted content.
  • Emit reasoning text separately as AgentEvent::ReasoningDelta and
    SessionEvent::AssistantReasoningDelta; signatures and ciphertext never
    enter host text deltas.
  • Replay opaque reasoning only when registered provider, requested model, and
    provenance format match exactly. Missing/empty metadata and cross-model or
    cross-provider history downgrade to ordinary text instead of being dropped
    or rejected.
  • Responses requests with reasoning enabled include
    reasoning.encrypted_content; Azure-compatible late ciphertext is backfilled
    from terminal output.
  • Thinking is persisted and may contain sensitive provider material. Local
    compaction summarizer inputs explicitly exclude it.

Gemini thought/signature fidelity remains incomplete because signatures can
also attach to tool-use and text parts; that phase is deferred.

Steering and host orchestration

  • Add agent-scoped in-memory steer and would-stop follow-up queues with
    QueueMode::{OneAtATime, All}. Enqueueing never auto-starts an idle agent;
    hosts call Agent::run_queued explicitly.
  • Steering wins over a user RoundStrategy at a boundary without consuming
    the strategy slot. Next-request context order is stable:
    steering, then team inbox, then background notifications.
  • Drained steering is inflight-tracked and requeued on runner or finalization
    errors.
  • Add typed Runtime::task_board and Agent::task_board façades over the
    existing access, transition, and DAG-validation path.
  • Add object-safe TaskStore::mutate. SQLite, Volatile, and Hybrid stores
    serialize mutations transactionally; custom stores retain a source-compatible
    load/replace fallback.
  • Add Agent::run_to_output<T> through an owner-scoped terminal tool and exact
    tool_use_id detail extraction. Provider-native response_format remains
    out of scope.
  • Add owned, generation-aware wait helpers for snapshots, idle completion, and
    teammate replies. See examples/host_orchestration.rs for the end-to-end
    host-scripted flow.
  • Make opaque team-protocol request IDs collision-resistant across
    cross-second request interleavings.

Nous migration — read before upgrading

Upgrade both direct dependencies together:

[dependencies]
mentra = "0.10"
mentra-provider = "0.4"

Nous imports provider-core types directly. Retaining mentra-provider 0.3
allows two provider-core versions into the graph and creates incompatible
types against Mentra's ContentBlock and tool-result surface.

Nous should also opt out of the generic result cap until its observation
protocol becomes truncation-aware:

use mentra::{Runtime, RuntimePolicy};

let policy = RuntimePolicy::default()
    .with_max_tool_result_bytes(usize::MAX)
    .with_max_tool_result_lines(usize::MAX)
    .spill_full_tool_output(false);

let builder = Runtime::empty_builder().with_policy(policy);

Why this is required today:

  • Nous serializes each ToolObservation as one physical JSON line.
  • Above 50 KiB, no complete line fits, so Mentra replaces the observation with
    a truncation notice.
  • Nous cannot deserialize that notice and excludes the observation from its
    reconstructed evidence.
  • Nous uses VolatileRuntimeStore, which correctly suppresses disk artifacts,
    so there is no spill file to recover.
  • Disabling spill alone is insufficient; both result limits must also be
    raised. Add a regression using serialized output larger than 51,200 bytes.

Additional integration guidance:

  • Treat Responses tool_use_id values as opaque. Reasoning-bearing turns may
    use local call_id|function_item_id IDs; provider outputs still project the
    raw call ID. Exact-equality pairing remains correct.
  • Existing wildcard AgentEvent and ContentBlock matches continue to
    compile. Handle ReasoningDelta explicitly only if live reasoning should be
    surfaced.
  • Replay-only Responses mode benefits from preserved reasoning. A
    gather-to-synthesis model switch safely downgrades incompatible opaque
    reasoning to text.
  • Run a live Responses/xipe smoke after upgrading because reasoning-enabled
    requests now ask providers for encrypted reasoning content.

Compatibility and source notes

  • Old persisted transcripts, agent memory, and snapshots deserialize
    unchanged. New optional fields are serde-defaulted and omitted when absent.
  • Under-limit tool results remain byte-identical. Oversized text intentionally
    changes, and oversized structured results become textual truncation notices
    that include an artifact pointer only when spill succeeds.
  • Exhaustive matchers must add cases for ContentBlock, ContentBlockStart,
    ContentBlockDelta, AgentEvent, SessionEvent, and
    mentra_provider::responses::model::ResponsesInputItem reasoning variants.
  • Exhaustive AgentSnapshot literals must add run_generation; patterns
    should use ...
  • Shell authorization preview JSON gains a validation object. In Warn
    mode, the reused AuthorizationDenied hook is advisory; inspect its action
    and outcome rather than treating the event name as proof execution stopped.
  • Existing custom AgentStore implementations compile through the default
    allows_disk_artifacts() == true; no-durable-trace stores should override it
    to return false.
  • Existing custom TaskStore implementations compile through default
    mutate, but that fallback is not atomic and should be overridden for
    concurrent writers.
  • Default agents have empty steering queues, shell validation remains Off,
    and file tools remain Batched.
  • Public time = "0.3" and url = "2.5" requirements remain compatible with
    downstream resolution. Resolver v3 and lockless Rust 1.85 CI enforce the
    repository MSRV without exact public pins.

Operational caveats

  • TaskBoard reads are live, but façade mutations refresh an agent's cached
    task snapshot only at the next normal refresh or run boundary.
  • The pre-existing full-board failed-run restore can overwrite a concurrent
    successful task mutation that occurred after the snapshot was captured.
  • Agent memory, agent records, and run checkpoints do not share one atomic
    store transaction. Steering/team/background input is requeued after late
    errors, but earlier finalization writes may already have committed.
  • wait_for_teammate_reply consumes inbox delivery and must not race the agent
    loop's inbox read. The host owns and must route the returned content.
  • An unsatisfied snapshot wait can remain pending while runtime observers
    retain watch-channel senders.

Crate versions and publication order

  1. Publish mentra-provider 0.4.0.
  2. Publish mentra 0.10.0, which depends on provider 0.4.
  3. Create the single repository tag and GitHub release v0.10.0.

Verification

This release is expected to pass:

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace
  • a fresh lockless cargo +1.85.0 check --workspace --all-targets