验证¶
已验证基础提交:cf4cc6faab0fb2c444ca054db8b98cb981bae6c9(拉取的 main 分支)。
工作树以该基础提交之上的提交形式承载了 manifest-view 与 streamable-HTTP 增量;本次增量的更改是叠加其上的未提交编辑。以下每项检查均按原样在评审回复轮次的该树上运行;没有报告任何未实际运行的检查。计时数据来自 macOS /usr/bin/time -l 命令统计(elapsed、user、system 秒数,以及命令及其等待的子进程的最大驻留集大小)。
已处理的评审意见¶
对第一轮的对抗性评审发现了一个应修复项和六个小问题;在下方各项检查运行之前,每个问题都已在其所属边界得到修复。
POST /agentenv之前通过request.json()读取流式node:http请求体,因此在返回-32700之前会缓冲 60 MB 的负载。现在该路由通过 SDK 的readRequestBody并配合DEFAULT_MAX_REQUEST_BODY_SIZE读取请求体,在解析前以 JSON-RPC-32000(id: null)返回413,并在该界限内通过领域层的safeParseJson进行解析。共享监听器的 JSON-RPC 错误辅助函数已导出为jsonRpcErrorResponse并复用,而非重新定义。- 已设置但为空的
ENVIRONMENT_NAME会以configuration_invalid拒绝,正如同级解析器中空MCP_HOST的处理;docs/cli.md和docs/agent-environments.md现已说明这一点,规范也记录了对设计中||读法的偏差是有意为之。 loadEnvironmentSource中的记录覆盖拒绝在已认证配对下不可达(Evidence id 是基于normalized_result计算的,因此匹配的父 id 意味着记录完全相同,且根据投影器的构造每条记录都带有请求行)。该分支已移除:被引用的记录无条件建立索引,没有请求行的记录会被忽略,工具会在调用时通过现有的无记录路径拒绝。相关声明已从docs/agent-environments.md和spec.md中删除,服务测试现在断言空 manifest 不会索引任何内容,且被篡改的捕获会被认证拒绝。- 所有公开的输入 schema 都以
additionalProperties: false结尾,因此未知参数会被拒绝为无效参数,而不会静默降级为省略参数。agentenv 框架的卡片消费者(verify_env_card.py、网关的tool.inputSchema透传以及规范一致性归一化器)只读取properties和required,因此多余的键不会影响它们;指南将其列为 echo schema 不携带的键。 - 工具描述现在为
METHOD template; replays retained records [ordinals]; evidence ev_…,符合设计文本的规定。 serveEnvironment向共享监听器传入onerror,该回调以error级别记录{ error }并转发给调用方;命令让取消信号与该失败竞争,并且在绑定后发生监听器失败时,会关闭监听器并返回与绑定失败相同的类型化resource_constraint错误(退出码1),而不是不提供任何服务。两种构造共享同一个transportError辅助函数。tests/boundary/cli/cliStartupImports.test.ts将dist/server/environment/serveEnvironment.js列为DEFERRED_IMPORTS中的environment-server,因此如果 serve 命令曾经急切导入监听器,--help探测就会失败。
环境设置¶
npm ci 退出码为 0(添加 540 个包,审计 541 个;elapsed 4.79 s,user 3.46 s,sys 7.34 s,880803840 字节)。在上述编辑之后,npm run build 退出码为 0(三个 turbo 任务;elapsed 4.61 s,user 14.76 s,sys 3.23 s,3053060096 字节),npm run test:prepare 退出码为 0(六个任务;elapsed 1.28 s,user 2.94 s,sys 0.67 s,424935424 字节),因此下方所有构建组运行和构建后的 CLI 检查都使用了包含修订后 serve 命令的 dist/。
静态检查¶
在最终树上各项均以退出码 0 通过:npm run check:fast(类型检查和 lint,2 个任务;elapsed 4.76 s,user 23.36 s,sys 2.56 s,4458840064 字节)。npm run format(4064 个文件;elapsed 0.93 s,user 4.12 s,sys 0.76 s,226344960 字节),随后 npm run format:check(全部 4064 个文件已格式化;elapsed 0.64 s,user 4.19 s,sys 0.66 s,219906048 字节)。npx knip(无发现;elapsed 3.49 s,user 4.92 s,sys 0.63 s,871645184 字节)。npm run check:ci:tasks(8 个任务成功,2 个由 turbo 缓存提供;lint:built 3756 个文件,0 错误;jscpd 3164 个文件,2583 个克隆,重复行占比 3.34%,低于 3.5% 阈值;游离标记扫描;elapsed 7.16 s,user 26.46 s,sys 5.88 s,2939142144 字节)。npm run verify:architecture-guards 在 1523 个源文件上通过,npm run verify:test-discovery 恰好发现全部 1592 个测试文件各一次。npm run docs:check(六个任务加 README 一致性测试,5 个用例;elapsed 3.37 s,user 3.49 s,sys 0.84 s,291618816 字节)。在本记录最后一次编辑后,npm run format、npm run format:check 和 npm run docs:check 被重新运行(均退出码为 0),同一静态检查集合也以无缓存方式重新运行:npx turbo run typecheck lint:built format:check knip metadata:check jscpd scan:todos --force(8 个任务成功,0 个缓存,重复占比 3.34%;elapsed 8.40 s,user 48.82 s,sys 7.77 s,4638474240 字节)。对所有 28 个新增或修改文件进行的不区分大小写的禁用词和标记注释 grep 未发现任何内容。
测试项目¶
最终树上的源组:/usr/bin/time -l npx vitest run --project services --project adapters 通过了 343 个文件、5196 个测试(8 个跳过),elapsed 99.55 s,user 93.60 s,sys 28.88 s,1781055488 字节。本次增量的文件包括 environmentSource.test.ts(4 个测试:配对认证与交换索引,父级不匹配作为 invalid_request 且路径为 ["evidence","evidence_id"],其他视图类型,非捕获证据与非 Evidence JSON,空 manifest 不索引任何内容且被篡改的捕获被认证拒绝)、environmentTools.test.ts(5 个测试:有序映射与 ; evidence 描述,带规则的必需路径参数,观测值与 additionalProperties: false,读取时无请求体的可选查询字符串,写入时的请求体对象,卡片的键顺序)、environmentReplay.test.ts(7 个测试,本轮未更改)和 serveEnvironment.test.ts(5 个适配器测试:卡片文本与 fixture 工具的 echo 卡片形状逐字节相等,/agentenv 对格式错误的请求体以 -32700 作出回答(而非 -32601),一个等于 DEFAULT_MAX_REQUEST_BODY_SIZE 加信封的路由级请求体返回 413 -32000 且 id: null,由 SDK 流式 HTTP 客户端驱动的完整监听器且 _meta 等于 TARGET_CONTENT_RESULT_META,精确与不精确的重放,无参数调用和未知参数均以 isError 拒绝,以及 renamed 覆盖配合超大请求体通过 node:http 返回 413 并释放端口)。
在 test:prepare 之后的重点构建组:npx vitest run --project cli-boundary --project mcp-boundary --project process-boundary --project boundary 针对 environmentServeCli、environmentServeMcp、environmentServeShutdown、mcpHttpShutdown、streamableHttpMcp、cliToolCoverage、cliStartupImports(现在带有 environment-server 延迟导入)、dispatcher、productCatalog、documentationFacts 和 ciTestProjects 运行,通过了 11 个文件、33 个测试(16.38 s elapsed,25.77 s user,5.94 s sys,941948928 字节)。
完整的构建组项目在后台 shell 中依次针对最终的 dist/ 运行,与此同时下文所述的构建后的 CLI 交互在前台运行。/usr/bin/time -l npx vitest run --project mcp-boundary 通过了 156 个文件(2 个跳过)、914 个测试(7 个跳过),耗时 166.23 s elapsed,319.51 s user,46.18 s sys,4452171776 字节。/usr/bin/time -l npx vitest run --project cli-boundary 退出码为 1:109 个文件通过、3 个失败,663 个测试通过、2 个跳过、7 个失败,耗时 432.45 s elapsed,725.28 s user,213.32 s sys,641597440 字节。没有失败文件属于本次增量。
javascriptApplicationJsonOutput.test.ts(4 个用例)和 javascriptApplicationProgress.test.ts(2 个用例)因工作进程的结果容量限制而失败(“The parent's result capacity was exhausted after retaining static facts for main.js”);在链路结束后于空闲主机上一同重跑,它们通过了 2 个文件、17 个测试(17.05 s elapsed,26.40 s user,8.47 s sys,282394624 字节),负载分类与上一轮记录一致。closedStdout.test.ts “stops quietly when the reader closes during streamed JSON” 在收到 1009 字节后以 1 而非 141 退出,单独运行和在项目中运行均如此;上一轮在干净克隆(macOS、Node 22.23.1、npm 12.0.2)上复现了该环境性失败。commandFinalizationCancellation.test.ts 在上一轮因 worker 顺序而失败,本轮通过。
/usr/bin/time -l npx vitest run --project process-boundary 退出码为 1:56 个文件通过、2 个跳过、3 个失败,463 个测试通过、19 个跳过、5 个失败,耗时 431.71 s elapsed,148.34 s user,114.81 s sys,710000640 字节。environmentServeShutdown.test.ts 和 mcpHttpShutdown.test.ts 在其中通过。jadxIntegration.test.ts 在 30 秒测试超时和 10 秒钩子超时下失败了三个用例(“retires an idle engine”、“completes large class inventories”、“close cancels active and queued work”),即上一轮记录在本主机上不同运行之间变动的那个通道。releaseArtifactCanary.test.ts 在解析 npm pack --json 时失败(“expected tuple, received object”),这是上一轮在干净克隆上复现的 npm 12.0.2 形状。processCaptureLifecycle.test.ts “keeps the process deadline bounded when the wall clock moves backward” 在 result.ok 上失败,错误为 expected false to be true;在空闲主机上单独重跑时,它以同样的方式失败,23 个通过(38.12 s elapsed,9.84 s user,18.07 s sys,323076096 字节)。该文件和 src/process/ 未被本次增量改动;该用例在一个真实进程捕获周围模拟 Date.now,并带有 1.5 秒的回退中止;它被记录为那个通道的主机相关失败,此处不作进一步分类。
构建后的 CLI 与原型捕获的交互¶
node scripts/rea.mjs inspect-web-network-capture grafana-like.har har --format json 写入了捕获 Evidence ev_4ee4759b…,包含 28 条记录;inspect-analysis-view 使用内联源和全部三条模板规则,写入了清单 Evidence ev_6553a8e5…,其父级为 grafana-example,共 19 个工具。environment-serve manifest.json --evidence capture.json --port 0 --json < /dev/null 在 stderr 上输出一行 {"transport":"streamable-http","url":"http://127.0.0.1:62305/mcp","msg":"MCP transport listening"},并且在关闭之前 stdout 上没有输出。
GET /.well-known/agent-env.json 返回了一张卡片,其顶层键、capabilities 键和工具键与回显卡片按顺序相同;其 inputSchema 的键为 type、properties、required 和 additionalProperties,即回显卡片的三个键加上收尾键。固定字段:protocolVersion 1.0、url /agentenv、preferredTransport JSONRPC、additionalInterfaces [{url:/mcp,transport:mcp}]、extensions null、operations []、children_environments null、19 个工具,其中 get_users_by_id 的描述为 GET /api/users/{numeric}; replays retained records [5, 6]; evidence ev_4ee4759b…。
Python mcp 1.30.0 客户端(httpx 0.28.1)针对 grafana-example 6.6.0(协议 2025-11-25)初始化,列出 19 个工具,调用 get_users_by_id {"id":"2"},读到 body.login == "probe"、replay.exact_match == True、_meta.provenance.untrusted_content == True,其中 source == "analysis_target";{"id":"999"} 得到 exact_match == False;get_folders_by_uid {"uid":"general"} 得到 recorded_path == "/api/folders/general";get_search {"query":"probe","type":"dash-db"} 返回一个列表体,其第一个标题为 probe dashboard,且 recorded_query == "?query=probe&type=dash-db";get_users_by_id {"id":"2","unknown":"x"} 返回 isError == True,且没有结构化内容。
POST /agentenv {"jsonrpc":"2.0","id":1,"method":"data/reset"} 返回 {"jsonrpc":"2.0","id":1,"error":{"code":-32601,"message":"method not found: data/reset"}}。一个 60 MB 的非 JSON POST 请求带有 Content-Length 头,在 curl 已发送 768332 字节后,于 1.4 ms 内收到 413 响应 {"jsonrpc":"2.0","error":{"code":-32000,"message":"Request body must not exceed 4194304 bytes"},"id":null},服务器驻留集之前为 269024 KiB,之后为 269040 KiB;同一文件以分块方式发送且不带长度时,在发送 5237311 字节后于 9.9 ms 内收到 413 响应,驻留集之前为 267952 KiB,之后为 274208 KiB,因此两种路径上的读取都会在边界处停止。一个位于边界内但格式错误的请求体({)收到了 400 响应 {"jsonrpc":"2.0","error":{"code":-32700,"message":"parse error"},"id":null}。
SIGTERM 在输出一份 stdout 文档 {"status":"stopped","url":"http://127.0.0.1:62305/mcp","environment":"grafana-example","tools":19,"evidence_id":"ev_4ee4759b…","manifest_evidence_id":"ev_6553a8e5…"} 后以状态 143 结束进程。使用 ENVIRONMENT_NAME=renamed 重启后,提供了一张名为 renamed 的卡片,其停止文档中报告了 "environment":"renamed",并且同样以 143 退出。ENVIRONMENT_NAME=(已设置但为空)在绑定之前以退出码 1 退出,并返回 {"code":"configuration_invalid","details":{"settings":[{"setting":"ENVIRONMENT_NAME",…}]}}。针对所选单条记录的捕获(--record 0,ev_3249d233…)提供清单时被拒绝,退出码为 1,并返回 {"code":"invalid_request","details":{"operation":"environment-serve","issues":[{"path":["evidence","evidence_id"],"reason":"invalid_value","expected":"ev_4ee4759b…",…}]}},其消息同时提到了两个标识符;省略 --evidence 时以 Incur 的 VALIDATION_ERROR 退出 1,其中点名了 evidence。这些运行之后,没有残留任何 rea.mjs 进程或监听器。
独立审查¶
第一轮的对抗性审查即为本次增量的独立审查;其结果与相应修复已列于上文。修复过程中还浮现出另一观察:serveEnvironment.test.ts 中的卡片字节级一致性断言会精确比较 inputSchema 对象,因此闭合该 schema 需要连同 services 测试一起扩展该预期——这正是卡片与所通告的 MCP schema 之间应有的耦合。
范围与测量限制¶
echo-card 比较在键、嵌套结构和工具条目上是精确的;inputSchema.properties 内的属性名必然与 echo 工具的单一 text 属性不同,且 inputSchema 包含一个 echo schema 所没有的键。exact_match 仅针对提供的值定义;省略的参数不会产生不匹配,因此无参数的调用在该工具的第一条记录上即为精确匹配。写入工具上的请求体会被接受并忽略。绑定后监听器的 error 路径已接好并通过类型检查,但没有被测试触发,因为共享监听器不暴露其 node:http 服务器。非回环绑定和放宽的 Host 检查未被测试;Python 交互、curl 检查及所有测试均使用 127.0.0.1。重放选择与请求体解析仅在包含 28 条记录的测试夹具上进行了测量;未进行大型捕获的计时。常驻内存集数值是对服务进程在每次请求前后各取一次 ps 样本所得。Token 用量与完整进程族的峰值未被测量;/usr/bin/time -l 的数值计入每个命令及其所等待的子进程。未在 Windows 上运行。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea