[PR #4975] [MERGED] feat(environment): serve an environment manifest as a replay environment #6707

Closed
opened 2026-11-01 21:42:26 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4975
Author: @earakely-scale
Created: 10/18/2026
Status: ✅ Merged
Merged: 10/19/2026
Merged by: @gensokyo-dev

Base: main ← Head: feat/environment-serve


📝 Commits (10+)

  • 46dd8f0 feat(mcp): serve the MCP server over streamable HTTP
  • b0ec63c fix(mcp): harden the streamable HTTP listener's session replacement and shutdown
  • 9ed8f06 fix(mcp): compare the media type proper and bind before creating the server
  • b76f354 fix(mcp): classify loopback from the bound address and keep startup failures out of onerror
  • fb22df3 fix(mcp): match Accept ranges exactly and keep a session whose shutdown failed
  • 54a7475 refactor(mcp): release the listener through one helper
  • 1741882 fix(mcp): fire the shutdown hook once, stop awaiting the probe's tee and keep every Set-Cookie
  • 354b4d8 fix(mcp): latch startup signals so the HTTP entry never ends without cleanup
  • 136d073 fix(mcp): keep a startup signal's exit status through the entry's normal return
  • a23f5f1 fix(mcp): close the connection after a reply sent before the body was read

📊 Changes

43 files changed (+4771 additions, -49 deletions)

View changed files

📝 docs/.vitepress/config.ts (+1 -0)
➕ docs/agent-environments.md (+239 -0)
📝 docs/cli.md (+34 -1)
📝 docs/index.md (+1 -0)
➕ docs/specs/agent-environments/environment-serve/plan.md (+36 -0)
➕ docs/specs/agent-environments/environment-serve/spec.md (+133 -0)
➕ docs/specs/agent-environments/environment-serve/tasks.md (+12 -0)
➕ docs/specs/agent-environments/environment-serve/verification.md (+245 -0)
➕ src/application/environment/environmentReplay.test.ts (+460 -0)
➕ src/application/environment/environmentReplay.ts (+263 -0)
➕ src/application/environment/environmentReplayCapacity.test.ts (+50 -0)
➕ src/application/environment/environmentReplayNumbers.test.ts (+65 -0)
➕ src/application/environment/environmentSource.test.ts (+196 -0)
➕ src/application/environment/environmentSource.ts (+291 -0)
➕ src/application/environment/environmentTools.test.ts (+332 -0)
➕ src/application/environment/environmentTools.ts (+316 -0)
📝 src/cli.ts (+2 -0)
➕ src/cli/environmentCommands.ts (+210 -0)
📝 src/cliCommandNames.ts (+1 -0)
📝 src/cliJsonInput.ts (+19 -2)

...and 23 more files

📄 Description

Summary

Adds rea environment-serve <manifest.json> --evidence <capture.json> [--host H] [--port N]: retained-capture replay tools over MCP, the discovery card at /.well-known/agent-env.json, and the /agentenv JSON-RPC stub. No captured application executes; the default REA MCP transport remains stdio. Refs #4933; uses merged #4955.

Final head: a215627ec773074716a75355637ebb98dca0fa37. Original author history and initial readiness declaration are retained, including author b217929a; integration started from main and was updated through 1b3ac942.

Problem and expected behavior

A manifest previously had no running replay surface. The command authenticates both Evidence documents and their parent relationship, selects the best retained path/query match, and identifies target content and missing/inexact/truncated facts. It establishes no authorization model or stateful application/reset behavior.

Change and scope

Application owners load/index retained data, derive one argument map for schema and replay, and admit the complete catalog. Discovery uses bounded descriptive samples with omission counts and complete lookup facts retained in Evidence. Long path/query keys have collision-safe aliases; unsafe JSON numbers stay original text; lossy numeric RPC IDs are refused. URL/form parsing has one owner, streaming selected fields and scanning only requested path coordinates.

The server reuses the SDK and HTTP lifecycle owner. Target-content labeling covers standalone cards, initialization, replay and SDK-generated errors. Cancellation reaches the regular-file reader and native DNS/listen startup; a cancelled startup never announces a listener. A 1 MiB conservative serialization reservation admits whole discovery before constructing SDK schemas/binding, returning a non-retryable capacity error on oversized input. Body, recorded-line and content-type truncation remain explicit.

Contract and boundary impact

  • Semantic owner/earliest changed stage: application environment loading, catalog admission and replay; adapters consume those facts.
  • Scope/authority: retained Evidence and the existing inbound listener; same effect class as merged #4955. See contribution scope; no new target execution, injection, mutation or protection recovery.
  • CLI/MCP: one additive command and per-manifest tools with closed schemas; REA's own MCP inventory/default stdio registration is unchanged. Card field names retain the existing protocol shape.
  • Compatibility: HAR only; loopback default, one active MCP session. Request bodies have the shared 4 MiB bound; JSON-RPC batches admit at most 100 messages.
  • Evidence/cleanup: parent identities, ordinal, match, encoding, body-presence and truncation facts remain visible; complete inputs stay unchanged. DNS/bind cancellation and normal SIGINT/SIGTERM shutdown release owned listeners.
  • Generated/package impact: CLI inventory regenerated and checked; no dependency/install changes. Ignored generated outputs are not committed.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

Negative controls demonstrated rounded numeric bodies, missing pre-initialization card labeling, oversized descriptions, and an old compiled CLI binding after SIGTERM during an Evidence read or paused DNS lookup. The new compiled cases return cancelled/143 without announcing a listener. The capacity regression authenticates an actual projected 10,000-field fixture, asserts those fields exist, then verifies a typed refusal before listening; the initial excluded-HTML fixture attempt failed and is not counted as passing.

Four actually recorded unauthenticated GitHub REST responses were inspected into HAR Evidence and two tools. Ten SDK replays checked body/status/line/provenance, including warm calls, DELETE and session replacement. Card labeling before initialization, argument errors, default stdio, mismatched Evidence, blank names, occupied ports, input digests and SIGTERM/port release passed on the final production build.

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

Pinned Node 24.18/Linux; heavy tasks used one CPU/worker. Family RSS sums descendants every 50 ms and may double-count shared pages.

Executed check Result Elapsed / CPU Peak family RSS
Full static/runtime gate (production tree ac1e36bf; final head changes only the capacity fixture) 8 tasks passed 225.607 / 217.296 s 4523.50 MiB
Final source/HTTP/SDK/domain suite 158 tests / 12 files passed 12.074 / 10.907 s 751.00 MiB
Final compiled CLI/MCP/process boundaries 17 tests / 5 files passed 59.393 / 56.972 s 903.93 MiB
Isolated global catalog 10 tests passed, 2 GiB heap cap 21.404 / 20.730 s 1331.09 MiB
Actual API replay workflow Passed, 10 equivalent replays 28.682 / 27.642 s 873.64 MiB

Packaged skill build, generated docs/facts/licenses and all five README consistency checks passed. The earlier 512 MiB catalog-worker attempt exhausted that local heap; the bounded isolated rerun above passed. Former native startup cleanup checks passed after updating main. Windows console interrupts, non-loopback deployment and arbitrary third-party enforcement of the advisory catalog notice remain unverified; these checks make no native-analysis claim.

Resource experiments (controlled metadata stress, not newly observed target requests):

  • Public CLI capture/view/serve, card and eight concurrent SDK lists with 1500 synthetic query names: unchanged 183,798-byte card; before/final elapsed 8.391/9.243 s, CPU 7.991/8.861 s, family RSS 507.27/503.43 MiB. Separate cold processes/caches do not establish a speed or memory gain; this calibrates admission.
  • Selection with 20,001 segments and pairs: first call 14.033/17.238 ms before/after, 20 warm calls 96.544/125.186 ms (94.898/123.495 ms CPU), process max RSS 165.0/162.7 MiB. Bounded retained state costs extra scanning time in this case.
  • Catalog construction/serialization with 10,000 observations/ordinals: 2,128,399/2,945 bytes; first call 15.235/1.584 ms, 20 warm calls 243.826/3.621 ms (240.682/3.652 ms CPU). Whole-process max RSS 127.6/137.1 MiB includes different module imports; no memory reduction is claimed. Capture loading, SDK and extra analyst lookups are excluded.
  • Four fresh --help runs kept identical stdout: before/final 8.662/10.267 s, CPU 8.531/10.066 s, family RSS 387.57/386.41 MiB. Host caches were not flushed and intervening main updates are included; no startup speedup is established.
  • Agent tokens and extra analyst calls remain unmeasured; response bytes are not token counts.

HAR SHA-256: f0d98a7bc5e55becb5c0cff2ee0978468463b0d17f81b79d5d21a13c47c9f286. Capture: ev_fe6367745865f768078d918a529bfbee3bcb883342de25aa7869343b4ae1bb8d; manifest: ev_bc2f23ecd9a9358fba1802bfc8f06184271e38be65c7eb65e3258a8ab9cd37ae.

Compatibility, safety, and release

Additive retained-data serving; no package/install changes or captured-application execution. All reported review threads have fix/validation explanations and are resolved. Greptile passed on the final head. A fresh Codex review is unavailable because the repository's code-review quota is exhausted; this is not counted as a passing review. Merged by gensokyo-dev at 2026-10-19 19:06:30 UTC as 10f1994fe1a0bbddeb846ee8078a80a483a652f1, using the explicit authorization to bypass queued final CI. The preceding production head passed GitHub static/source checks; the final head additionally passed the corrected capacity regression and all local final checks above. Full final CI was queued at merge and is not claimed green.

Author readiness

Human owner: @earakely-scale

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4975 **Author:** [@earakely-scale](https://github.com/earakely-scale) **Created:** 10/18/2026 **Status:** ✅ Merged **Merged:** 10/19/2026 **Merged by:** [@gensokyo-dev](https://github.com/gensokyo-dev) **Base:** `main` ← **Head:** `feat/environment-serve` --- ### 📝 Commits (10+) - [`46dd8f0`](https://github.com/morluto/rea/commit/46dd8f0e2b5ff74e09821e09e51bc6fd47f3bc1a) feat(mcp): serve the MCP server over streamable HTTP - [`b0ec63c`](https://github.com/morluto/rea/commit/b0ec63cc0399ad9ca7bd00a65cb1c2d753cfd47b) fix(mcp): harden the streamable HTTP listener's session replacement and shutdown - [`9ed8f06`](https://github.com/morluto/rea/commit/9ed8f06f75ea772dfd81d552142b059852e530c3) fix(mcp): compare the media type proper and bind before creating the server - [`b76f354`](https://github.com/morluto/rea/commit/b76f354d76384abe56b079b0b37e1367d1908efd) fix(mcp): classify loopback from the bound address and keep startup failures out of onerror - [`fb22df3`](https://github.com/morluto/rea/commit/fb22df370b5146b3798b6f83e64317e2785ecfcb) fix(mcp): match Accept ranges exactly and keep a session whose shutdown failed - [`54a7475`](https://github.com/morluto/rea/commit/54a747560207c06196a1ba4eb8b8ca062f15ddc5) refactor(mcp): release the listener through one helper - [`1741882`](https://github.com/morluto/rea/commit/174188279b6ce482354966ed542436514d3d4624) fix(mcp): fire the shutdown hook once, stop awaiting the probe's tee and keep every Set-Cookie - [`354b4d8`](https://github.com/morluto/rea/commit/354b4d8c0867f3d0eadaae2b0dfe42cea810287e) fix(mcp): latch startup signals so the HTTP entry never ends without cleanup - [`136d073`](https://github.com/morluto/rea/commit/136d073fa019fb8a1c5ef95ff70ecaf6d34676c4) fix(mcp): keep a startup signal's exit status through the entry's normal return - [`a23f5f1`](https://github.com/morluto/rea/commit/a23f5f13524b5403794f3599e26f93cc18398820) fix(mcp): close the connection after a reply sent before the body was read ### 📊 Changes **43 files changed** (+4771 additions, -49 deletions) <details> <summary>View changed files</summary> 📝 `docs/.vitepress/config.ts` (+1 -0) ➕ `docs/agent-environments.md` (+239 -0) 📝 `docs/cli.md` (+34 -1) 📝 `docs/index.md` (+1 -0) ➕ `docs/specs/agent-environments/environment-serve/plan.md` (+36 -0) ➕ `docs/specs/agent-environments/environment-serve/spec.md` (+133 -0) ➕ `docs/specs/agent-environments/environment-serve/tasks.md` (+12 -0) ➕ `docs/specs/agent-environments/environment-serve/verification.md` (+245 -0) ➕ `src/application/environment/environmentReplay.test.ts` (+460 -0) ➕ `src/application/environment/environmentReplay.ts` (+263 -0) ➕ `src/application/environment/environmentReplayCapacity.test.ts` (+50 -0) ➕ `src/application/environment/environmentReplayNumbers.test.ts` (+65 -0) ➕ `src/application/environment/environmentSource.test.ts` (+196 -0) ➕ `src/application/environment/environmentSource.ts` (+291 -0) ➕ `src/application/environment/environmentTools.test.ts` (+332 -0) ➕ `src/application/environment/environmentTools.ts` (+316 -0) 📝 `src/cli.ts` (+2 -0) ➕ `src/cli/environmentCommands.ts` (+210 -0) 📝 `src/cliCommandNames.ts` (+1 -0) 📝 `src/cliJsonInput.ts` (+19 -2) _...and 23 more files_ </details> ### 📄 Description ## Summary Adds `rea environment-serve <manifest.json> --evidence <capture.json> [--host H] [--port N]`: retained-capture replay tools over MCP, the discovery card at `/.well-known/agent-env.json`, and the `/agentenv` JSON-RPC stub. No captured application executes; the default REA MCP transport remains stdio. Refs #4933; uses merged #4955. Final head: `a215627ec773074716a75355637ebb98dca0fa37`. Original author history and initial readiness declaration are retained, including author `b217929a`; integration started from main and was updated through `1b3ac942`. ## Problem and expected behavior A manifest previously had no running replay surface. The command authenticates both Evidence documents and their parent relationship, selects the best retained path/query match, and identifies target content and missing/inexact/truncated facts. It establishes no authorization model or stateful application/reset behavior. ## Change and scope Application owners load/index retained data, derive one argument map for schema and replay, and admit the complete catalog. Discovery uses bounded descriptive samples with omission counts and complete lookup facts retained in Evidence. Long path/query keys have collision-safe aliases; unsafe JSON numbers stay original text; lossy numeric RPC IDs are refused. URL/form parsing has one owner, streaming selected fields and scanning only requested path coordinates. The server reuses the SDK and HTTP lifecycle owner. Target-content labeling covers standalone cards, initialization, replay and SDK-generated errors. Cancellation reaches the regular-file reader and native DNS/listen startup; a cancelled startup never announces a listener. A 1 MiB conservative serialization reservation admits whole discovery before constructing SDK schemas/binding, returning a non-retryable capacity error on oversized input. Body, recorded-line and content-type truncation remain explicit. ## Contract and boundary impact - Semantic owner/earliest changed stage: application environment loading, catalog admission and replay; adapters consume those facts. - Scope/authority: retained Evidence and the existing inbound listener; same effect class as merged #4955. See [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope); no new target execution, injection, mutation or protection recovery. - CLI/MCP: one additive command and per-manifest tools with closed schemas; REA's own MCP inventory/default stdio registration is unchanged. Card field names retain the existing protocol shape. - Compatibility: HAR only; loopback default, one active MCP session. Request bodies have the shared 4 MiB bound; JSON-RPC batches admit at most 100 messages. - Evidence/cleanup: parent identities, ordinal, match, encoding, body-presence and truncation facts remain visible; complete inputs stay unchanged. DNS/bind cancellation and normal SIGINT/SIGTERM shutdown release owned listeners. - Generated/package impact: CLI inventory regenerated and checked; no dependency/install changes. Ignored generated outputs are not committed. Expected effects: - [x] Read existing files or captured data. - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [x] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage Negative controls demonstrated rounded numeric bodies, missing pre-initialization card labeling, oversized descriptions, and an old compiled CLI binding after SIGTERM during an Evidence read or paused DNS lookup. The new compiled cases return cancelled/143 without announcing a listener. The capacity regression authenticates an actual projected 10,000-field fixture, asserts those fields exist, then verifies a typed refusal before listening; the initial excluded-HTML fixture attempt failed and is not counted as passing. Four actually recorded unauthenticated GitHub REST responses were inspected into HAR Evidence and two tools. Ten SDK replays checked body/status/line/provenance, including warm calls, DELETE and session replacement. Card labeling before initialization, argument errors, default stdio, mismatched Evidence, blank names, occupied ports, input digests and SIGTERM/port release passed on the final production build. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed Pinned Node 24.18/Linux; heavy tasks used one CPU/worker. Family RSS sums descendants every 50 ms and may double-count shared pages. | Executed check | Result | Elapsed / CPU | Peak family RSS | | --- | --- | --- | --- | | Full static/runtime gate (production tree `ac1e36bf`; final head changes only the capacity fixture) | 8 tasks passed | 225.607 / 217.296 s | 4523.50 MiB | | Final source/HTTP/SDK/domain suite | 158 tests / 12 files passed | 12.074 / 10.907 s | 751.00 MiB | | Final compiled CLI/MCP/process boundaries | 17 tests / 5 files passed | 59.393 / 56.972 s | 903.93 MiB | | Isolated global catalog | 10 tests passed, 2 GiB heap cap | 21.404 / 20.730 s | 1331.09 MiB | | Actual API replay workflow | Passed, 10 equivalent replays | 28.682 / 27.642 s | 873.64 MiB | Packaged skill build, generated docs/facts/licenses and all five README consistency checks passed. The earlier 512 MiB catalog-worker attempt exhausted that local heap; the bounded isolated rerun above passed. Former native startup cleanup checks passed after updating main. Windows console interrupts, non-loopback deployment and arbitrary third-party enforcement of the advisory catalog notice remain unverified; these checks make no native-analysis claim. Resource experiments (controlled metadata stress, not newly observed target requests): - Public CLI capture/view/serve, card and eight concurrent SDK lists with 1500 synthetic query names: unchanged 183,798-byte card; before/final elapsed 8.391/9.243 s, CPU 7.991/8.861 s, family RSS 507.27/503.43 MiB. Separate cold processes/caches do not establish a speed or memory gain; this calibrates admission. - Selection with 20,001 segments and pairs: first call 14.033/17.238 ms before/after, 20 warm calls 96.544/125.186 ms (94.898/123.495 ms CPU), process max RSS 165.0/162.7 MiB. Bounded retained state costs extra scanning time in this case. - Catalog construction/serialization with 10,000 observations/ordinals: 2,128,399/2,945 bytes; first call 15.235/1.584 ms, 20 warm calls 243.826/3.621 ms (240.682/3.652 ms CPU). Whole-process max RSS 127.6/137.1 MiB includes different module imports; no memory reduction is claimed. Capture loading, SDK and extra analyst lookups are excluded. - Four fresh `--help` runs kept identical stdout: before/final 8.662/10.267 s, CPU 8.531/10.066 s, family RSS 387.57/386.41 MiB. Host caches were not flushed and intervening main updates are included; no startup speedup is established. - Agent tokens and extra analyst calls remain unmeasured; response bytes are not token counts. HAR SHA-256: `f0d98a7bc5e55becb5c0cff2ee0978468463b0d17f81b79d5d21a13c47c9f286`. Capture: `ev_fe6367745865f768078d918a529bfbee3bcb883342de25aa7869343b4ae1bb8d`; manifest: `ev_bc2f23ecd9a9358fba1802bfc8f06184271e38be65c7eb65e3258a8ab9cd37ae`. ## Compatibility, safety, and release Additive retained-data serving; no package/install changes or captured-application execution. All reported review threads have fix/validation explanations and are resolved. Greptile passed on the final head. A fresh Codex review is unavailable because the repository's code-review quota is exhausted; this is not counted as a passing review. Merged by `gensokyo-dev` at 2026-10-19 19:06:30 UTC as `10f1994fe1a0bbddeb846ee8078a80a483a652f1`, using the explicit authorization to bypass queued final CI. The preceding production head passed GitHub static/source checks; the final head additionally passed the corrected capacity regression and all local final checks above. Full final CI was queued at merge and is not claimed green. ## Author readiness Human owner: @earakely-scale - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:42:26 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6707
No description provided.