Export an authenticated capture and environment manifest as a pinned agentenv bundle with provenance, a replay verifier and smoke task.
Followups preserve immutable input ownership, bounded discovery, caller paths and numeric values; bind bundle writes and package copying to retained filesystem owners; verify POSIX modes; retain cleanup authority; and verify framework/npm executable selection. Default MCP remains stdio.
Validation: pinned Linux toolchain, typecheck/build/lint/format/docs/knip, 452 focused tests, ten product-catalog cases, real GitHub response replay in the generated non-root Docker image, and the real pinned agentenv framework smoke workflow. Platform and resource-measurement limits are recorded in the feature verification document.
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Serve retained capture Evidence as a bounded MCP replay environment with discovery.
Preserve default stdio, caller-selected facts and complete source Evidence.
Fix numeric fidelity, argument identity, startup cancellation and bounded discovery,
query/path matching and output metadata. Verify real recorded API data and public
CLI/MCP workflows; preserve explicit gaps for Windows and third-party hosts.
Co-authored-by: Edgar Arakelyan <edgar.arakelyan@scale.com>
Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A captured query name longer than 64 characters is advertised under a
short, collision-safe `query_<n>` alias, with the captured name sampled
in its description; replay maps the alias back, and the manifest keeps
the full name.
Replies cut `recorded_path` and `recorded_query` to 1 KiB and set
`recorded_line_truncated`, so a megabyte-scale recorded URL is not
echoed into every reply; selection still uses the full recorded line.
An explicit empty query (`/api?`) keeps its `?` in `recorded_query`. The
shared WHATWG URL parser reports it as "", like no query, so the replay
exchange reads the delimiter from the recorded URL instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replay parses a JSON body only when every integer survives exactly; a
body with an integer outside JavaScript's safe range, such as an id of
9007199254740993, is returned as its recorded text instead of with
other digits.
A SIGINT or SIGTERM that arrives while environment-serve reads and
authenticates its files now ends startup with a cancelled result before
the listener binds, rather than binding and stopping at once.
A tool description cuts a captured path longer than 1 KiB at a
character boundary and points to the manifest Evidence, matching the
list sample budget; the manifest keeps the full path.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sample captured observations, request-body keys and record ordinals before joining them. Preserve complete manifest facts and replay selection, and show omission counts with their Evidence source. Share the capture trust notice across standalone cards, tool discovery and MCP initialization.
A parameter description lists at most ten observed values, each cut at
64 characters, followed by a count of the rest. tools/list and the
environment card are served whole, so a capture with many or very long
path values no longer inflates them; the manifest keeps every value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replay ranks a record whose path segment equals the argument as written
above one that matches only after percent-decoding, so two recorded
spellings that decode alike no longer resolve by manifest order.
The /agentenv data plane answers -32600 for an id that is not a string,
number or null and for params that are not an object or array, and
refuses a batch of more than 100 messages before building any reply.
The environment MCP server now extends RequestTrackingMcpServer, which
the HTTP owner requires since the streamable-HTTP change it builds on.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The environment-manifest view, environment-serve and environment-export
accepted only inspect_web_network_capture HAR Evidence, so an environment
needed an external capture script and HAR scrubbing step. They now also
accept capture_browser_scenario Evidence: a session REA records in a
browser it launches, with credential headers and declared secrets
redacted.
Each network transaction becomes one HAR-shaped record in request order,
so the manifest accumulator, the replay and the bundle work unchanged. A
redacted URL is never templated, an unattributable transaction is left
unrepresented, and a scenario that selected neither response bodies nor
header values is refused because tools are chosen by response media
type. The bundle README names the capture kind and, for a scenario, the
scenario definition's SHA-256.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The data plane treated a batch or a notification as one call and
replied to everything. Notifications now get 202 with no body, a batch
gets one reply per request in it, and an empty batch or a message that
is not a JSON-RPC request gets -32600 invalid request.
- The replay limit applied to a base64 body's spelling, so a binary body
under 256 KiB was truncated because its base64 is a third longer. The
limit now applies to the recorded bytes, and a cut keeps whole base64
groups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A transport wrapper marks every tools/call result as target content,
including the argument errors the SDK returns before a replay runs.
- The server's instructions add that tool names, descriptions, parameter
names and observed values come from the capture too, so the catalog is
treated as data like the replies.
- Strict UTF-8 decoding keeps a leading byte-order mark instead of
dropping it from the recorded text.
- A large retained base64 body is decoded only as far as the 256 KiB a
reply can carry, and the replay reports it truncated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The Dockerfile copies manifest.json and evidence.json owned by the node
user, so a private host umask cannot leave the runtime user unable to
read them.
- The generated verifier keeps the first record's own unknown status
instead of borrowing another record's, and an error reply never passes
the check, even when the recorded status is unknown.
- Export checks, before reading an input, that reading and natively
parsing the whole file fits live heap headroom, with the same rule the
bounded JSON reader applies to native parsing, and refuses it as a
resource constraint otherwise.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The replay MCP server serves names, descriptions and replies taken from a
captured application but advertised no instructions, so clients that
rely on server instructions had no warning not to follow target text. It
now carries the same untrusted-content instructions as REA's own server,
moved next to the target-content result marker so both import it.
Retained HAR base64 bodies were decoded as UTF-8 even when the bytes were
not UTF-8, inventing replacement characters. They are now decoded
strictly; other bytes are returned exactly as base64 with
body_encoding: "base64".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Path parameters, query parameters and the write body share one argument
object, so a query named like a path parameter or 'body' could not be
supplied, and query names such as 'constructor' were dropped as already
taken. One argument map, used by both the schema and the replay scorer,
now renames a colliding query to query_<name> and a colliding body to
request_body, and is built without inherited keys. Replay results gain
body_recorded, so a body the capture did not keep is not passed off as a
recorded null, and truncation encodes only the 256 KiB prefix instead of
the whole body.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add rea environment-serve <manifest.json> --evidence <capture.json>
[--host] [--port]: it loads an environment-manifest view and the capture
Evidence it was projected from, refuses a manifest whose parent evidence id
does not match the capture, builds one MCP tool per manifest tool and serves
them over streamable HTTP beside an environment card at
/.well-known/agent-env.json and a data plane at /agentenv that refuses every
method. Each tool call replays the retained record whose path and query
values best match the arguments, cites the record ordinal and evidence id,
marks replayed content as untrusted target content, and truncates bodies
over 256 KiB with a flag. Nothing executes the captured application.
Refs morluto/rea#4933
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The first hosted run of the real-agentenv lane failed only on the cleanup
check: agent-env's local image store starts a registry:2 helper
(`agentenv-registry[-<port>]`) on first use and keeps it running across runs,
so a fresh runner ends the run with one more container than it started with.
The verifier now lists containers with their names, reports that helper under
`image_store_helpers` and asserts that nothing else was added.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add rea environment-export <manifest.json> --evidence <capture.json> <dir>
[--package-tarball <path>] [--name <override>]: it reads and authenticates the
manifest and capture pair once and writes an agent environment bundle folder
(README with provenance and a rights note, envs/<name> with a Dockerfile that
pins this exact rea version or installs a given tarball, the manifest and the
Evidence as byte-identical copies, a Python verifier that checks replay
through the MCP endpoint, and a smoke task) that the agentenv framework runs
with agent-env run. Refuses a non-empty directory and a mismatched pair
before writing. Adds the real-agentenv hosted lane, which packs the checkout,
exports a bundle from the source-owned capture fixture and runs it on the
runner's Docker with a pinned agentenv-framework, wired into the CI planner
and its guard tests.
Refs morluto/rea#4933
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>