## What changed
Add `auto_review.timeout_ms` to configure the overall Guardian review budget, including setup and retries. Keep the default at 90,000 milliseconds; setting it to `0` disables the review deadline while preserving cancellation, retry attempt limits, and independent transport timeouts.
Carry the configured deadline through review execution and report the configured budget in review telemetry, using zero for unlimited reviews.
## Testing
Add coverage for shared setup budgets, configured timeouts, cancellation with unlimited reviews, and retry attempt limits without a deadline.
GitOrigin-RevId: 00404e0cb2f2cfaf6de183d6e27f5e4a371942a8
## What changed
- Include ready environments' configured hooks in lifecycle events and execute command hooks using each owner's shell, working directory, shell environment policy, and managed network policy.
- Resolve tool environments before `PreToolUse` and use those targets for tool hooks, execution, and permission review. Route MCP hooks by server ownership and file-copy hooks to both endpoints.
- Preserve environment, MCP server, and terminal session selectors across hook input rewrites, rejecting attempts to switch targets.
## Testing
Add regression coverage for permission-request selector preservation, MCP resource hook ownership, and file-copy hooks that rewrite paths while preserving source and target environments.
GitOrigin-RevId: 31a3a6830523965285dab451cfc866c620ef6c83
## What changed
- Read optional tool descriptions and parameter schemas for `history`, `notes`, `new_context`, and `get_context_remaining` from the acting model's catalog messages.
- Support catalog namespace descriptions for history and notes, preserving explicit empty and whitespace descriptions.
- Share catalog override handling across native tools and MCP resource helpers. Keep bundled schemas when overrides are invalid, preserve encrypted parameters, and leave tool identity and transport fields unchanged.
## Testing
Add coverage for sparse catalog serialization, schema fallback and encryption preservation, per-step tool definitions, and context tool updates when switching models. Extend outgoing-request tests to verify history and notes overrides while retaining history image attachments.
GitOrigin-RevId: 1adac8b5009f95c91adba491f20a4e2e2dc91475
## What changed
- Add `environment_hooks` to `EnvironmentConfig` for hooks from an environment's effective managed requirements. Initialize it empty for inferred thread configurations and report the handler count in debug output.
- Move `HookEventsToml`, `MatcherGroup`, and `HookHandlerConfig` into `codex_protocol::hooks`, with re-exports from `codex_config::hook_config`.
- Validate MCP hook input recursively to reject nulls and integers outside the signed 64-bit range without converting through `toml::Value`.
GitOrigin-RevId: 410506c8e2b89c9519c81d86b44ccd760d751693
## What changed
Add an optional `NetworkPolicyMetadataProvider` to the MCP runtime. Advertise `codex/network-policy-meta` only to trusted ChatGPT origins when a provider is available, and attach policy metadata only when the sending session also advertises support.
Strip caller-supplied policy metadata and derive restrictions from the call's captured permission profile and server environment. Resolve metadata against each session's capabilities, including after recovery, while retaining one policy snapshot per call. Fail the call before sending if policy resolution fails. Existing runtime callers leave the provider unset.
## Testing
Add tests for capability negotiation, trusted-origin restrictions, forged metadata removal, both tool dispatch paths, and policy snapshot reuse. Add HTTP session-recovery coverage for changing capabilities and policy-resolution failures while preserving caller metadata and read-only restrictions.
GitOrigin-RevId: 4b978f986abc0475fc67659be98fc01a2d6ce7cd
## Why
A requirements denial on a custom `codex_apps` registration could block the trusted hosted Apps replacement. Requirements filtering also lost whether a server had been explicitly disabled, which must remain effective across runtime overlays.
## What changed
- Track explicit disables separately from requirements denials, retaining the requirement source across catalog rebuilds and server materialization.
- Allow trusted host-owned Apps to bypass a previous registration's requirements denial while preserving explicit disables and blocking later custom replacements.
- Preserve combined explicit and requirements disables during repeated filtering, and reject those servers when preparing standalone MCP login HTTP clients.
## Testing
Extend regression coverage for hosted Apps replacements, later custom replacements, cloud catalog refreshes, repeated requirements filtering, and standalone login rejection.
GitOrigin-RevId: 736a13c40fbf7436b4d0682f70c335f33f45962f
## What changed
Move inline crate tests into `lib_tests.rs` and nest related test suites under each crate's `tests` module. Update imports, subprocess test filters, logging targets, and snapshot names to match the new module paths.
Keep test helpers accessible where needed and preserve the schema writer's exact test name used by release tooling.
GitOrigin-RevId: de55eaae66dce4941abb33dd0b2f170093daa8f9
## Why
`message_board_tools` always exposed all nine discussion tools. Consumers need a way to expose a subset, such as `read_thread` and `list_threads`, over the same board.
## What changed
Accept an ordered slice of the new `MessageBoardTool` enum and optional description overrides in `message_board_tools`. Use the enum for schemas and dispatch, and keep the agent extension's existing tool set and order through `MessageBoardTool::DISCUSSION`.
## Testing
Extend the local-board integration test to verify that a reader-only selection exposes exactly the requested tools in the supplied order and reads the existing discussion.
GitOrigin-RevId: 60026d73768330ff4b694c3a9e99480e3ed7af27
## Why
Local message boards use a fixed database filename. Callers need separate storage for boards that share a session identity.
## What changed
- Add `LocalBoardOptions` with a validated `storage_namespace`, and support it when opening, configuring, and permanently deleting boards.
- Allow `LocalBoard::with_options` to select storage for its connections.
- Store custom namespaces in `message_board_<namespace>_1.sqlite`, while preserving `agent_message_board_1.sqlite` for the default namespace.
- Have the agent message board extension select the same namespace for opening, setup, and deletion.
## Testing
Add coverage for namespace isolation, reopening saved posts, and avoiding collisions with other runtime databases. Update setup tests to exercise a custom namespace through reopening and deletion.
GitOrigin-RevId: a6ea8d171809625edeedc3a8ac3ee2e1bbf1682a
## What changed
Move the message-board API, types, permissions, storage backends, and tool implementations into the new `codex-message-board` crate. Keep extension registration in `codex-agent-message-board-extension`, and update core and the remote client to use the shared crate directly.
Move the existing board tests with the implementation and add the crate to the Cargo workspace and Bazel build.
GitOrigin-RevId: 33ce527c2bef7f862eba55cb9b32222902ccf4ad
## Why
Failed cloud discovery previously retried before each model step. Apply a cooldown across steps and turns to avoid repeated discovery requests while a provider remains unavailable.
## What changed
- Share per-thread retry backoff logic between cloud skill and plugin catalogs, starting at 30 seconds and doubling to a maximum of 5 minutes.
- Scope cooldowns to authentication and MCP resource generations so account changes and reconnects permit immediate recovery.
- Clear backoff after successful discovery or configuration resets, while allowing cancelled refreshes to retry immediately.
## Testing
Update lifecycle and concurrency tests to cover shared cooldowns, reconnect recovery, and cancellation. Use paused time to verify exponential delays, the 5-minute cap, and backoff across turns.
GitOrigin-RevId: 30dab5ceba51e8ad64c0794c1729719e99f577ce
## Why
Authentication can change between model steps. Refresh cloud catalogs before the next step so plugin acceptance and skill instructions reflect the current auth scope, including plugins that are no longer available.
## What changed
- Add a `refresh_catalog_for_step` lifecycle hook and rebuild MCP when plugin catalogs change.
- Reuse successful discovery within a turn and auth scope, serialize concurrent refreshes, and allow retries after failures or cancellation. Limit cloud skill discovery warnings to once per turn.
- Skip cloud discovery during prewarm and other context-only captures, and check hosted plugins even when no executor roots are selected.
## Testing
Add regression coverage for mid-turn auth rotation and plugin removal, serialized refreshes and retries, stale discovery results, and prewarm boundaries.
GitOrigin-RevId: 355681e84dc765e8dc1a04608779d95c706c2188
## Why
A delayed conversation classification can reach execution after a newer request has already published a score and committed history, leaving it with no useful work to contribute.
## What changed
Pass the classification's sampling timestamp into conversation requests and check for newer scores and retained history before starting inference. Return `Superseded` only when both have advanced; keep requests that can still contribute either a score or history.
## Testing
Add regression tests covering supersession of scores and history separately and together, including a classification delayed by permissions. Verify skipped requests send no inference request and preserve cached scores, approvals, and score progress.
GitOrigin-RevId: ef78a59e2010a82ac4f1fb93568a562447187099
## Why
Guardian review metrics derived duration from wall-clock timestamps, while analytics measured elapsed time when tracking the result. Clock changes and delayed tracking could produce inconsistent latencies.
## What changed
Capture one monotonic duration at review completion and pass it to both metrics and analytics. Preserve wall-clock timestamps for event ordering, and saturate analytics latency conversion at `u64::MAX`.
## Testing
Add a regression test covering skewed wall-clock timestamps and delayed tracking, verifying that the duration metric uses the captured interval and completion timestamps are preserved.
GitOrigin-RevId: 19eafb8e1f1a3d13a751bdc72c218e4cafeae410
## What changed
Move cached cloud skill contents into `SkillCatalogState` alongside the published catalog generation. Prepare auth scopes and access cached contents under the same lock, clearing contents when the auth scope changes and retaining them when a partial refresh preserves a complete catalog. Keep generation checks around asynchronous discovery and reads.
Use the auth key already captured by `prepare_cloud_generation` when creating a cloud plugin generation, so the stored and returned keys match.
GitOrigin-RevId: 426bb7868baf9ff7855988291783a8d3e38d9c93
## What changed
- Update Cargo and Bazel toolchain pins, CI and release workflows, and Windows setup from Rust `1.95.0` to `1.99.1`.
- Adapt Rust code to updated APIs and lint requirements, including `try_update` and `as_chunks`, and refresh the halfwidth sound marks snapshot.
- Update `webpki-root-certs` from `1.0.5` to `1.0.10` in the Cargo and Bazel lockfiles.
GitOrigin-RevId: e1aaed63b7e72bb8c8bbe25b32c6329c9a37b6c3
## Why
Decisions snapshot comparisons reject requests containing reasoning or compaction, while conversation comparisons already omit those items. A parent compaction also causes snapshot comparisons to be rejected.
## What changed
- Share filtering of reasoning, compaction, and context compaction across both comparison modes, and ignore parent compaction when building the Decisions request.
- Distinguish malformed request setup from unsupported input items. Record setup errors as failures and unsupported input items as skipped comparisons.
## Testing
Extend the HTTP contract test to cover both comparison modes with reasoning, compaction, context compaction, and parent compaction while preserving message content. Update assertions for the distinct setup and unsupported-input errors.
GitOrigin-RevId: e3ba0cce3b6457b3e3eab3589352b70288cbb1ef
## What changed
Add `MessageLifecycleContributor` hooks to capture extension state when local agent control publishes a message and notify contributors when the recipient commits it to history, before sampling.
Carry shared delivery state through submissions, input queues, and mailbox eviction with `PendingAgentMessage`. Notify consumption at most once per delivery, release captured state when consumed or abandoned, and drop pending mail outside queue locks. Preserve the serialized message format without republishing restored history.
## Testing
Extend the mailbox eviction test to verify that publication state survives eviction and retained messages are consumed before the first resumed model sample.
GitOrigin-RevId: 9a1f6832bd48ec646a3fd179485c095e8dcc72cc
## What changed
- Add `CodeModeCellTiming` notifications for yielded executions, terminal waits, and unavailable cells, with thread, call, and cell identifiers.
- Measure how long completed results remain buffered before retrieval and carry `result_buffered_for` through the runtime, stdio protocol, and gRPC response metadata. Immediate delivery reports zero; waits without a completed result report no buffering measurement.
- Default missing buffering data to zero for compatibility with older hosts.
## Testing
Extend runtime tests to verify buffering duration with a paused clock and retrieval through termination. Add gRPC conversion tests for nanosecond precision, optional metadata, and the distinction between immediate delivery and no completed result.
GitOrigin-RevId: 60c0c5a3affa69ac3779bf1812fca50f5748af76
## Why
Guardian V2 previously skipped optional Decisions comparisons in conversation mode as unsupported evidence.
## What changed
- Start comparisons from the prepared conversation input, including retained history or rebuilt evidence after a history reset.
- Extract the classifier rubric and preserve evidence message roles, content order, and boundaries. Omit retained reasoning and compaction items while continuing to reject other unsupported evidence.
- Measure baseline sampling through the usable score, before history draining and commit, and report skipped comparisons when preparation fails or the request is superseded.
## Testing
Extend coverage to both classifier modes for comparison disagreements, failures, and disabled or uninitialized comparisons without changing baseline scores. Verify conversation evidence across history reuse and resets, malformed input rejection, and budget failures before either backend sends a request.
GitOrigin-RevId: ce32cf876d15d3b82e0b83ac02c33447e7724a51
## What changed
- Add `--cloud-skills-snapshot PATH` to load a cloud skill catalog and resource contents from JSON once at app-server startup, without contacting a live skill service.
- Expose snapshot skills through the native `skills.list` and `skills.read` interface, preserving aliases and prompt visibility. Reads remain available after the snapshot file is removed.
- Validate package boundaries, required resources, duplicate packages, and size limits; fail startup for missing or invalid snapshots.
- Keep frozen cloud catalog and read caches independent of live MCP resource changes.
## Testing
Add provider, cache, app-server, and core scenario tests covering validation, exact resource contents, authority boundaries, startup failures, and listing and reading frozen skills alongside a named executor.
GitOrigin-RevId: d438a5d678121db3e17515fc5edcd00d4e20b900
## What changed
- Rename the snapshot comparison entry point to `start_snapshot_comparison` and extract request spawning into `spawn_request`.
- Accept a `ContentItem` rubric and an iterator of evidence in the request adapter.
- Read the Decisions comparison feature flag once per classification and simplify the budget rejection test setup.
GitOrigin-RevId: b4a294eeecb6069db0f80ff6e4f13f558cbd7815
## What changed
Record `codex.guardian.turn.blocking_ms` when a turn completes or aborts, with an `outcome` label. Count overlapping approval waits once, exclude idle gaps, and split pending reviews across the active turns they span. Use each turn's telemetry so samples retain the servicing turn's model attribution.
## Testing
Add unit coverage for overlapping waits, idle gaps, late turn completion, and duplicate stops. Extend integration coverage to verify attribution across turns and model changes for yielded command reviews and MCP elicitation, including aborted turns.
GitOrigin-RevId: a3e6a0c32a06fe58ea93119ecd941076100fb82c
## What changed
Split retained conversation scoring into `Reservation::prepare` and `PreparedConversation::run`, exposing the complete admitted input before model execution. Keep the history fork and capacity permit owned by the prepared conversation, and recheck authorization, score expiry, and backend generation before execution.
## Testing
Extend conversation tests to verify that preparation sends no model request, execution uses the prepared input, dropping a prepared conversation releases capacity, and stale prepared reviews cannot start model execution.
GitOrigin-RevId: c96cc6fac69179a78ecd7bcdb8e5a4b3087aa6e6
## Why
A temporary exec-server transport loss could emit a thread environment disconnect notification while the session was still recovering.
## What changed
- Add `EnvironmentConnectionState::Recovering` for interrupted transports and pending session recovery.
- Suppress thread lifecycle notifications during recovery, emit a connected notification after successful recovery, and report disconnection when recovery fails.
- Ignore recovery callbacks from retired clients so they cannot overwrite the connection state during refresh.
## Testing
Add coverage for fast and near-deadline recovery, recovery timeout, rejected session resume, and retired-client callbacks. Extend app-server coverage to verify one lifecycle notification per selected thread and usable `environment/info` after recovery.
GitOrigin-RevId: d6dce5cc5264af29b6f993daa209b93102122e40
## Why
Cancelled or timed-out Guardian reviews can admit transcript evidence without completing a review. Reusing that session can leave subsequent reviews without the evidence they need.
## What changed
Mark interrupted reviews for rollback to the last completed review instead of reusing their live context. Preserve committed review history and replay pending evidence on the next review.
## Testing
Add cancellation and timeout regression coverage that verifies encrypted evidence appears exactly once in the next review, the last completed review survives rollback, and interrupted or denied commands do not execute. Update session disposition assertions and make the program-change session reuse test wait for review completion before releasing the classifier result.
GitOrigin-RevId: f39552b24db5309cffddd9eda97280256be3e97b
## Why
Full-transcript fallback can select encrypted agent messages already present in the reviewer's history. These duplicates should not consume the input budget or displace new evidence.
## What changed
- Reconcile native agent messages with the effective reviewer history and earlier messages in the pending input before budgeting, including after compaction.
- Deduplicate messages with nonempty IDs while preserving messages without IDs. Allow delivery again when the prior copy is absent from the current history.
- Reject conflicting authors, recipients, or content under the same ID without modifying the pending context.
## Testing
Add coverage for duplicate admission, conflicting payloads, redelivery after history removal, and retained reviewer requests. Extend the history eviction regression to verify that full-transcript fallback reuses the reviewer and preserves a single encrypted agent message.
GitOrigin-RevId: 97e90f6359a7cf5a75d1c5967fc98cd885afb4e4
## Why
Skill tools depended on World State rendering to initialize their catalogs and could return `skill catalog is not ready for this step` before rendering completed.
## What changed
- Add an asynchronous `ToolContributor::prepare_for_step` hook and await all contributors before constructing tools.
- Prepare immutable skill catalogs, aliases, plugin policy, and configuration for each step. Tools, invocation detection, and World State rendering consume the prepared state without relying on rendering to perform discovery.
- Apply configuration reloads to subsequent steps while preserving live authorization checks for skill reads.
## Testing
Add coverage for preparation completing before tool construction and World State rendering, skill tools working before rendering, catalogs remaining stable across steps, and configuration reloads during discovery.
GitOrigin-RevId: 1fb95c58c412488353f3bd4403824d6d1476d3d0
## What changed
- Record review attempt counts and final outcomes with a `retried` tag.
- Measure retry waits by failure reason and whether the wait ends in a retry, cancellation, or deadline; count retries only when another attempt will run.
- Count required synchronous reviews with the `required_sync` route.
- Use the originating turn's telemetry for Guardian reviews so metrics retain that turn's model attribution.
## Testing
Add metric assertions for attempt counts, retry outcomes, and waits interrupted by cancellation or deadlines. Extend the delayed cached-score integration test to verify route and retry-wait metrics use the originating turn's model after a model override.
GitOrigin-RevId: 681a719ad5dd9e4436cb37b6f5f972cb11a5c890
## Why
A skill can be available from Cloud and multiple executor environments. Reading its instructions needs to expose where supporting files live and allow discovery of locations omitted by response limits. Package aliases also need to keep identifying the same roots as catalogs change.
## What changed
- With executor capability discovery V2, add `skills.installations` to list enabled locations with source filtering and pagination, without reading skill contents.
- Let `skills.read` select Cloud or a specific executor environment through `source`. Return bounded installation metadata and an `installations_truncated` flag so callers can retrieve omitted locations.
- Share bounded, append-only alias assignments between catalog rendering and tools within a live thread. Preserve each step's alias snapshot and render only root mappings used by its catalog entries.
- Use discovery-root metadata when constructing executor skill locators, with a fallback when it is absent. Preserve the legacy read response and tool set outside discovery V2.
## Testing
Add coverage for installation filtering and pagination, response budgets, source-specific reads and cursors, and alias stability across catalog and plugin changes. Add an end-to-end scenario that discovers an omitted installation and reads its instructions from the selected environment.
GitOrigin-RevId: a04e51e8242b21288d9d7b822780f9f1e093151d
## What changed
- Build executor skill catalogs from discovery V2 inventories without reopening host paths or falling back to legacy discovery.
- Merge Cloud and executor skills by remote plugin identity and skill name, retaining Cloud metadata and accepted provider read routes. Apply plugin selection and disablement before merging.
- Share a stable catalog across each step's rendering, list/read tools, and explicit and implicit skill invocations.
- Preserve unmatched executor entries when Cloud catalogs are unavailable or partial; only complete Cloud catalogs disable unmatched remote entries.
- Bind discovery caches to captured environments and executor sessions, and refresh MCP when V2 inventories change. Preserve pending invalidations when forced MCP refreshes fail.
## Testing
Add regression coverage for V2 inventory sharing and refresh, environment isolation, catalog merging, partial Cloud results, disabled plugins, and catalog consistency across steps and read routes.
GitOrigin-RevId: 842bdcbc9e19364dd69a9abf9e48330b7425a76c
## Why
Skill aliases already identify their source, but `skills.read` searched the cloud catalog before the executor catalog even for executor aliases.
## What changed
Parse package locators to recognize cloud (`c0/...`), executor (`e0/...`), and host (`r0/...`) aliases. Restrict cloud and executor alias lookups to the matching catalog, while retaining the existing search order for other package strings.
Share the source-to-prefix mapping between alias generation and parsing, and preserve the string representation and tool schema for package locators.
## Testing
Extend alias tests to cover source recognition, JSON round trips, and malformed alias strings, including leading zeros, missing suffixes, non-ASCII prefixes, and overflowing indices.
GitOrigin-RevId: f835e47a244aa0cf9eb95980ea23f4d7fcedd511
## What changed
- Use V2 discovery inventories for plugin MCP contributions when supplied, including empty or failed inventories; retain legacy discovery when no V2 snapshot is supplied.
- Merge plugins by canonical identity, using cloud metadata and enablement for remote plugins and attaching executor installations only when versions match. Preserve configured executor-local plugins and executor enablement when cloud data is unavailable.
- Keep installation order stable across refreshes and run merged MCP declarations on the first retained executor installation while preserving attribution for the others.
- Carry local and remote identities through selected-plugin snapshots, skill attribution, and active-plugin telemetry. Track disabled plugin IDs alongside disabled roots.
- Preserve a complete cloud catalog when a partial refresh arrives, and cap tool-description plugin attribution at 1,024 bytes while retaining all plugin associations.
## Testing
Add coverage for catalog parsing and reconciliation, enablement and discovery-mode selection, installation refresh ordering, executor-specific MCP normalization, selected-plugin snapshots, and bounded UTF-8 attribution text.
GitOrigin-RevId: a8ad352de6a2b8dc4bfd1ff6a5c62ee8ed1d1664
## What changed
- Count adaptive reviews and record synchronous review routes as `async_fallback` or `required_sync`, with the review reason in snake case.
- Record cached score readiness and score age in milliseconds, measured from input sampling time and including inference time.
## Testing
Extend approval tests to assert fallback routing, adaptive review counts, score readiness, and sampled score age.
GitOrigin-RevId: 1200b3297add6c4467e460de87b4a6d8d31e1fc4
## What changed
- Add sampling retry counters that distinguish transport retries from authentication recovery, with failure reasons.
- Record attempt counts and final outcomes for successful, failed, cancelled, and superseded sampling requests.
- Carry retained-score telemetry until the consumer accepts or discards the score, so queued scores that expire are recorded as superseded and accepted early scores remain successful even if response draining fails.
## Testing
Add metric assertions for transient recovery, retry exhaustion, authentication recovery, cancellation, supersession, and retained-score acceptance or discard, including expiry while a score is queued.
GitOrigin-RevId: 36babd6f431f22cf15b73355e6e026a256a81004
## Why
Guardian request counts grouped by input size should reflect admitted sampling inputs without counting synchronous transport retries more than once.
## What changed
- Add a shared `token_bucket` label to admitted total-input observations in `codex.guardian.context.request_tokens` for synchronous and asynchronous reviews. Use inclusive upper bounds in 20k-token steps through 240k, followed by 256k and overflow buckets.
- Record synchronous request tokens after budget admission, once per sampling step, including the complete input. A fresh step counts again even when its input is identical.
- Preserve asynchronous component histograms for oversized classifications, but omit `token_bucket` so rejected inputs do not contribute to counts grouped by that label.
## Testing
Add coverage for bucket boundaries, synchronous retry deduplication and budget rejection, asynchronous retained-history reuse and reset, and admitted versus oversized classification metrics.
GitOrigin-RevId: fac2f102a4c48c5fd21d56bfa701b95a1ff852d0
## Why
Cloning `ResponseItem::AdditionalTools` deep-copies its tool declarations for history and request copies.
## What changed
Store `tools` in an `Arc<[serde_json::Value]>` so clones share immutable declarations. Update constructors and existing test fixtures to use the shared representation.
GitOrigin-RevId: eb8831774afb45fe8431a796f34ae9d1243e884a
## Why
Contextual fragments and extension-owned world-state sections currently return strings, limiting them to text content.
## What changed
- Return `ContentItem` from fragment bodies and rendering, preserving classification and attribution. Apply text markers only to `InputText`; pass other content through unchanged.
- Allow extension prompt and world-state contributions to carry typed content, and preserve media in context-window hints.
- Hash non-text world-state fragments by their serialized content and role while retaining the existing text hashing behavior.
- Add shared content-to-tool-output conversion that preserves image references, image detail, and audio.
## Testing
Add coverage for typed world-state hashing and preservation of image content and attribution. Expand code-mode output tests to cover input text, output text, file-backed and inline images, and audio.
GitOrigin-RevId: 2ed00d466a3f169b151202f3eef71e667ea64be1
## What changed
Add the `codex-multi-env-copy-file` extension, exposing `multi_env_copy_file` when registered by the host. Copy files between distinct selected environments without loading their contents into model context, and return `bytes_copied` on completion.
Require absolute paths in each environment's native path convention and enforce each endpoint's sandbox policy and permission grants. Stream file contents where supported, with a buffered fallback for older executors. Reject same-environment copies and report I/O error kinds without exposing connection details. Warn that failed writes may leave a truncated or partially written target.
## Testing
Add integration tests for binary transfers in both directions, local and remote executors, path validation, opt-in tool visibility, endpoint permissions and grants, and unavailable or disconnected executors. Verify that copied contents stay outside model context.
GitOrigin-RevId: f5d9e423d105019834e0288828cb68c5711b3a49
## Why
The optional Guardian Decisions comparison rejected non-user messages and trusted skill evidence, and folded trusted tool evidence into the classification rubric.
## What changed
Send evidence as separate messages with their original roles, content order, boundaries, and optional `phase`. Support both `input_text` and `output_text`, keeping trusted tool and skill evidence separate from the rubric. Continue to accept inline images only in user messages and reject unsupported evidence.
## Testing
Update adapter and HTTP contract tests to cover mixed message roles and assistant output. Extend lifecycle coverage to verify that trusted skill evidence reaches Decisions while comparison results leave the baseline risk unchanged.
GitOrigin-RevId: 1b6814fe6db5891fb61604d6846a008c9e456054
## What changed
Add optional `inputImages` metadata containing each referenced local image's path and SHA-256 hash of the bytes read before normalization. Compute the hash from the same bytes used to prepare the edit request.
Preserve this metadata through completion events, persisted thread history, resume, and legacy rollout migration. Update app-server schemas and generated TypeScript and Python types; older items continue to deserialize without the field.
## Testing
Add coverage for input ordering, changed contents at the same path, unreadable or invalid references, serialization, persisted history and resume, and legacy migration.
GitOrigin-RevId: 522be8ec1e39c9b2bbe5b9ccb37ea67d17f0e21a
## What changed
- Upload generated images to the attachment store and expose `fileId` in image-generation items when available, with inline `result` fallback on upload or decoding failure.
- Preserve file references through legacy events, persisted rollouts, thread history, and task output summaries. Keep model-facing image preparation separate.
- Add attachment request tags and mark generated-image uploads with `usage=image_gen`, preserving the thread's ephemeral setting.
- Update public schemas and SDK types to accept either image representation, retain the Python `ImageGenerationThreadItem` alias, and prefer `fileId` when reading records containing both fields.
## Testing
Add coverage for file-backed generation and rollout persistence, legacy history replay, inline and transitional serialization, task output visibility, and Python SDK alias compatibility.
GitOrigin-RevId: f7a2bb5707e2f277348a547a988bc33c8e96d891
## Why
Competing SQLite writers can cause database opening and writes to fail with `SQLITE_BUSY`. Deferred write transactions can also encounter contention after taking a read snapshot.
## What changed
- Add up to two retries with 100 ms and 200 ms delays for SQLite busy errors during pool opening, writer admission, and standalone writes.
- Use a shared `BEGIN IMMEDIATE` helper across state, thread history, and agent message board writes to acquire the writer slot before reading.
- Preserve bound arguments when retrying standalone writes, and commit writes using `RETURNING` before exposing their results. Retry transaction admission without replaying an already-started transaction.
## Testing
Add tests using real SQLite writer contention to verify recovery after a competing writer releases its lock. Queue tests cover enqueue, update, and delete, checking preserved payloads, single revision increments, and no duplicate messages or unintended deletions.
GitOrigin-RevId: ac5bd31a87c67cc47fb385bf3fa5435a54ff70f0
## What changed
Replace duplicated content-kind strings with constants shared by fragment producers and consumers, including authorization checks, forked-history filtering, and memory instructions. Share the compaction summary kind between core and Guardian's transcript filter.
## Testing
Add a regression test verifying that Guardian excludes compaction summaries while retaining surrounding user messages, including a user message with identical text.
GitOrigin-RevId: 36dbdf0f82c61b52d2571ac1c392fb151c98151b
## What changed
- Add `ComposedContext::retain_new_images` and use it in Guardian review sessions and the async scorer. Compare host-prepared image references against admitted history, ignoring image detail, and skip scanning history when no images need checking.
- Restore `ConversationState` directly from a checkpoint, retaining committed history for rollback or transferring it with `take_history` for ephemeral forks.
## Testing
Extend tests for prepared-image matching across differing detail levels, image-free continuations that avoid scanning history, and checkpoint restoration and history transfer.
GitOrigin-RevId: bafeb6de9babc721182be43d0eb1a653955a0ebb
## Why
A failed Guardian inference can retain its input in a reusable session. Tracking transcript progress only after successful reviews can admit the same evidence again on retry.
## What changed
Advance transcript progress when a failed turn has retained its input and the session remains reusable, without counting it as a completed review or changing the committed fork checkpoint. Leave progress unchanged when failure occurs before input admission.
## Testing
Extend regression coverage for encrypted agent messages across review retries, pending evidence after compaction failures, and fork checkpoints after transcript admission without a completed review.
GitOrigin-RevId: 36239ec9d47f484bcfe68d65e7c8d8ab8660db0d
## Why
Native extensions need configured Responses metadata for request attribution, but extension calls used the MCP metadata template, which omits it. Image requests also did not forward the turn metadata to the backend.
## What changed
Use the Responses metadata template for native extension calls while continuing to exclude tool inventory. Forward the resulting metadata in the `x-codex-turn-metadata` header on image generation and edit requests.
## Testing
Extend metadata tests to cover configured values in extension calls and app-server tests to verify `display_name` and `turn_trigger` on image generation and edit requests, including a Unicode display name.
GitOrigin-RevId: a2ffaa4d15259c662917612391b8717ee34b9c6c
## Why
Unsupported evidence currently shares a single Decisions comparison reason, making it difficult to distinguish why a comparison was skipped.
## What changed
Report separate reasons for unsupported developer messages, other non-user messages, trusted skills, images, and audio. Keep these outcomes classified as `skipped` and retain the generic reason for other unsupported evidence. Expose `TrustedSkills::KIND` for identifying trusted skill fragments.
## Testing
Expand adapter tests for the distinct rejection reasons and add a lifecycle case verifying that trusted skill evidence skips the Decisions request, reports `trusted_skills`, and preserves the baseline score.
GitOrigin-RevId: 98f076d1aa6771d0209e7f5910eed0dcc40c6263
## What changed
- Preserve approval resolution sources through tool errors and tag cancelled MCP approvals with `error_type=approval`, `error_code=cancelled`, and `approval_source` (`guardian`, `user`, `hook`, or `unknown`). The source identifies the reviewer, not who caused cancellation.
- Record `context_changed` when validating a Guardian allow against changed authorization or review context, even when a concurrent stop or history reset determines the outcome. Retain the flag across retries and fresh-checkpoint recovery, and include it in the Guardian review counter.
GitOrigin-RevId: a19a986a7565f9a78a9bb2eaabdb5651834d28b8
## Why
An asynchronous approval currently waits for the redundant synchronous review to finish cancellation cleanup before returning a decision.
## What changed
Cancel the redundant review and let it drain under the parent's `ReviewerTasks` tracker so a current approval can return immediately. Revalidate the approval and check cancellation before approving the action. Hosts without a task tracker continue to wait for cleanup.
Keep the reviewer reservation held until cleanup completes, and let shutdown join the tracked attempt. Discard late results and evidence from the cancelled review.
## Testing
Add tests covering current, invalidated, and cancelled approvals while cleanup is blocked, suppression of late evidence, reviewer reservations during cleanup, and shutdown waiting for abandoned attempts.
GitOrigin-RevId: f227738e545243f99c19a6c557a78d330f9d2767