Commit Graph
28 Commits
Author SHA1 Message Date
gensokyo-dev d2bf07558e chore: merge current main after environment export 2026-10-19 21:30:53 +00:00
7a0c47bfa4 feat(environment): export an environment manifest as an agent environment bundle (#4999)
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>
2026-10-20 05:29:43 +08:00
Edgar Arakelyan 32ccaafe9f chore: merge environment export (62e8ce38) into scenario capture after the serve merge 2026-10-19 13:32:29 -07:00
gensokyo-dev d31da9cc17 fix(environment): share authenticated input snapshots and preflight exported catalogs 2026-10-19 19:47:02 +00:00
gensokyo-dev 510142a041 chore: update environment export with latest main
# Conflicts:
#	docs/agent-environments.md
#	docs/cli.md
#	docs/specs/agent-environments/environment-serve/spec.md
#	src/application/environment/environmentReplay.test.ts
#	src/application/environment/environmentReplay.ts
#	src/application/environment/environmentSource.ts
#	src/application/environment/environmentTools.test.ts
#	src/application/environment/environmentTools.ts
#	src/cli/environmentCommands.ts
#	src/cliCommandNames.ts
#	src/server/environment/serveEnvironment.test.ts
#	src/server/environment/serveEnvironment.ts
#	tests/boundary/cli/cliStartupImports.test.ts
#	tests/boundary/cli/environmentServeCli.test.ts
#	tests/boundary/process/environmentServeShutdown.test.ts
#	tests/fixtures/environmentServe.ts
2026-10-19 19:17:51 +00:00
10f1994fe1 feat(environment): serve an environment manifest as a replay environment (#4975)
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>
2026-10-20 03:06:29 +08:00
Edgar Arakelyan 150f9a5f2b chore: merge environment serve (b217929a) into environment export 2026-10-19 10:49:59 -07:00
Edgar ArakelyanandClaude Opus 5.5 b217929a81 fix(environment): alias long query names, bound reply line metadata, keep empty queries
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>
2026-10-19 10:26:07 -07:00
Edgar ArakelyanandClaude Opus 5.5 130bc4326a fix(environment): keep exact JSON numbers, stop startup on shutdown, bound described paths
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>
2026-10-19 10:06:59 -07:00
gensokyo-dev afcd29d29f chore: sync replay follow-ups with author and latest main 2026-10-19 16:33:41 +00:00
gensokyo-dev 167c6aeb2f fix(environment): bound and mark replay discovery metadata
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.
2026-10-19 16:33:01 +00:00
Edgar ArakelyanandClaude Opus 5.5 7510c1a3c8 fix(environment): bound observed values in parameter descriptions
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>
2026-10-19 09:23:30 -07:00
Edgar Arakelyan 00f27c2c3b chore: merge environment export (23b80c24) into scenario capture 2026-10-19 08:55:37 -07:00
Edgar Arakelyan ede425e9d5 chore: merge environment serve (5e242c13) into environment export 2026-10-19 08:53:19 -07:00
Edgar ArakelyanandClaude Opus 5.5 5e242c1359 fix(environment): prefer verbatim path matches and validate data-plane messages
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>
2026-10-19 08:53:11 -07:00
Edgar ArakelyanandClaude Opus 5.5 3c2a8db2e7 feat(environment): build environments from browser scenario captures
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>
2026-10-18 21:52:25 -07:00
Edgar ArakelyanandClaude Opus 5.5 fca1a0e925 chore: merge environment serve (da920d47) into environment export
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:12:19 -07:00
Edgar ArakelyanandClaude Opus 5.5 da920d4726 fix(environment): honour the JSON-RPC envelope on the data plane and limit base64 bodies by their bytes
- 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>
2026-10-18 21:11:46 -07:00
Edgar ArakelyanandClaude Opus 5.5 5b5dc77794 chore: merge environment serve (9196cf73) into environment export
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:58:57 -07:00
Edgar ArakelyanandClaude Opus 5.5 9196cf7302 fix(environment): mark every replay result, warn about the captured catalog and bound base64 decoding
- 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>
2026-10-18 20:58:38 -07:00
Edgar ArakelyanandClaude Opus 5.5 178668fc74 fix(environment): readable bundle inputs, an honest replay check and admitted export reads
- 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>
2026-10-18 20:52:25 -07:00
Edgar ArakelyanandClaude Opus 5.5 ac1fbd282e chore: merge environment serve (d8d53713) into environment export
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:39:57 -07:00
Edgar ArakelyanandClaude Opus 5.5 d8d53713e3 fix(environment): advertise untrusted-content instructions and keep non-UTF-8 bodies as base64
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>
2026-10-18 20:38:54 -07:00
Edgar ArakelyanandClaude Opus 5.5 6ec7ff3870 chore: merge environment serve (4216aa89) into environment export
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:28:04 -07:00
Edgar ArakelyanandClaude Opus 5.5 124adf945c fix(environment): keep every tool input addressable, flag unrecorded bodies and bound truncation
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>
2026-10-18 20:27:06 -07:00
Edgar ArakelyanandClaude Fable 5.1 fe55c94e66 feat(environment): serve an environment manifest as a replay environment
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>
2026-10-18 19:43:09 -07:00
Edgar ArakelyanandClaude Fable 5.1 877d0d1229 fix(environment): report the framework's image-store helper instead of counting it as a leak
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>
2026-10-18 19:43:09 -07:00
Edgar ArakelyanandClaude Fable 5.1 c6c2a64af3 feat(environment): export an environment manifest as an agent environment bundle
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>
2026-10-18 19:43:09 -07:00