* test(mcp): check advertised schemas against a portable dialect in every profile * fix(mcp): re-emit advertised patterns in a portable regex grammar * fix(mcp): present discover_tools input through the selected profile The hot-cold catalog registered discover_tools directly with the SDK, so the default compact input profile still advertised its canonical schema, including page-size defaults clients apply on their own (#5322). Route every listed input schema, transport discovery included, through one server-owned presentation, and pass the selected presentation to the deferred server, which serves recorded tool schemas but not discovery. * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * fix(mcp): validate advertised dialect by selected profile * fix(mcp): preserve schema widening through references * feat(mcp): project compact input schemas into the portable advertised dialect One projection (advertisedDialectProjection.ts) owns the compact input advertisement: one type per node, items on every array, string literals as enums, oneOf widened to anyOf, allOf merged, tuples as element unions, exclusive bounds made inclusive, and every keyword outside the dialect dropped. Each rewrite is exact or widening; server validation is unchanged. The root description and sentences for dropped cross-field constraints move to the tool description, which Codex and Zed keep. The compact baseline falls to nullable values only (29), which the dialect cannot express without narrowing an input. The gateway shape repairs (typeArrayItemUnions, hasGatewayIncompatibleShape), the second dependentRequired-to-prose copy and the strict-gateway test denylist are removed; the dialect checker gates the inline presentation instead. * feat(mcp): omit output schemas from tools/list by default No surveyed model API reads an output schema, MCP client validators repeat REA's own result validation, and complete output schemas were about 92% of the default tools/list. REA_MCP_OUTPUT_SCHEMA_PROFILE now resolves to off through one owner (resolveMcpOutputSchemaProfile); compact and full remain selectable. structuredContent is still delivered, and the deferred server serves both off and full from the recorded catalog with the matching recorded identity. Tests and artifact verifiers that validate results against complete advertised output contracts select full explicitly. * docs: describe omitted output schemas as the default in README translations * fix(mcp): select schemas in verification workflows * fix(mcp): refuse zero-padded repeat bounds and record host-specific path patterns * fix(mcp): keep projected schemas permissive * fix(mcp): keep references valid when presentation widens their targets * fix(mcp): keep a single union branch's closure scoped to its properties * fix(mcp): select complete output schemas in the Electron verifier * fix(mcp): select complete output schemas in standalone verifier probes * fix(mcp): keep an allOf member's tuple tail with its own positions * fix(mcp): relax references into negations and conditionals presentation may remove * refactor(contracts): declare root discriminators as typed schema annotations * test(mcp): select the borrowed Evidence contract from its family * fix(mcp): keep astral literals and dynamic references widening in every mode * fix(mcp): omit astral literals and relax untracked references when presentation widens * fix(mcp): select complete output schemas in every verifier transport * fix(mcp): read reference pointers by schema position, not segment spelling * fix(mcp): protect references into collapsing boolean unions and keep referencing branches out of the collapse * fix(mcp): keep reduced schemas open when their root admits names by pattern * test(mcp): keep the reduced-schema pattern case outside the size-limited block * fix(mcp): omit patterns whose classes name astral characters * fix(mcp): decide union collapse and pointer protection from canonical branches * docs(mcp): document non-u astral matching and pin BMP agreement across V8 modes * fix(mcp): keep prototype-named properties as own properties in the dialect projection * test(mcp): select full output schemas in packet and signal schema checks * test(mcp): expect the advertised base64 schema to omit the unbounded pad-bit probe * fix(mcp): protect references into unevaluated keywords lost evaluation removes * fix(mcp): validate the doctor probe reply against the canonical output contract (#10655) * fix(mcp): validate the doctor probe reply against the canonical output contract * test(mcp): replay doctor probe validation under every output profile * test(mcp): accept typed-branch nullable unions in the advertised dialect (#10649) * test(mcp): select full output schemas in HTTP session workflows * fix(mcp): emit stack-safe classes with non-ASCII members and protect draft-07 reference siblings * fix(mcp): protect references into literal siblings of relaxed draft-07 references * feat(mcp): omit output schemas from tools/list by default (#10646) * feat(mcp): omit output schemas from tools/list by default No surveyed model API reads an output schema, MCP client validators repeat REA's own result validation, and complete output schemas were about 92% of the default tools/list. REA_MCP_OUTPUT_SCHEMA_PROFILE now resolves to off through one owner (resolveMcpOutputSchemaProfile); compact and full remain selectable. structuredContent is still delivered, and the deferred server serves both off and full from the recorded catalog with the matching recorded identity. Tests and artifact verifiers that validate results against complete advertised output contracts select full explicitly. * fix(mcp): select schemas in verification workflows * fix(mcp): select complete output schemas in the Electron verifier * fix(mcp): select complete output schemas in standalone verifier probes * fix(mcp): select complete output schemas in every verifier transport * test(mcp): select full output schemas in packet and signal schema checks * fix(mcp): validate the doctor probe reply against the canonical output contract (#10655) * fix(mcp): validate the doctor probe reply against the canonical output contract * test(mcp): replay doctor probe validation under every output profile * test(mcp): accept typed-branch nullable unions in the advertised dialect (#10649) * test(mcp): select full output schemas in HTTP session workflows * fix(mcp): keep the Evidence union on described borrowed inputs (#10597) * fix(mcp): keep the Evidence union on described borrowed inputs borrowEvidenceInput installed its advertised projection on one schema instance. A call site's .describe() rebuilds the schema from its definition, so match_native_functions advertised left and right as unconstrained values in every input profile. Install the projection in the borrowed parser's constructor so derived schemas keep it, for both borrowed inputs and borrowed arrays. * test(mcp): select the borrowed Evidence contract from its family * docs(mcp): admit baseline growth only for restored contract declarations * fix(mcp): state reduced multi-type properties as typed branches, not type lists The reduced fallback derived a property's types and emitted them as a type list, which Gemini, Moonshot and Ark reject. A property whose canonical schema is anyOf string and number therefore traded a typed union for a rejected construct when the inline projection fell back. Emit one type, or anyOf typed branches, so [T, null] becomes the dialect's nullable union. * feat(mcp)!: retire the full schema profiles and declare complete observations as a typed annotation (#10718) * refactor(mcp): declare complete observations as a typed annotation applied only on the wire * test(mcp): compare complete-observation declarations with their owning text * refactor(schema): couple Zod checks with their JSON Schema constraint keywords (#10725) * refactor(schema): couple Zod checks with their JSON Schema constraint keywords * refactor(schema): declare pattern approximations and object output roots as typed annotations (#10754) * refactor(schema): declare pattern approximations and object output roots as typed annotations * fix(schema): refuse pattern declarations JSON Schema cannot state * test(schema): select guided_workflows from its contract family * feat(mcp)!: retire the full input and output schema profiles (#10841) * feat(mcp)!: retire the full input and output schema profiles The compact input presentation is now the only advertised input schema, and output schemas are either omitted (`off`, the default) or bounded (`compact`). Catalog identity, the build-recorded digests and the recorded startup catalog collapse to those presentations: two digest profiles instead of six, one recorded catalog instead of two, and no input dialect baseline. Tests and verifiers that validated replies against listed full output schemas now validate against the canonical output contract, which REA already enforces server-side; tests that asserted canonical input restrictions read the canonical input schema instead of a full listing. BREAKING CHANGE: `REA_MCP_INPUT_SCHEMA_PROFILE=full` and `REA_MCP_OUTPUT_SCHEMA_PROFILE=full` are refused at startup and by `rea setup` with a configuration error naming the setting. Remove the setting from the client registration (or rerun setup with `REA_MCP_INPUT_SCHEMA_PROFILE=compact` / `REA_MCP_OUTPUT_SCHEMA_PROFILE=compact`). `REA_MCP_INPUT_SCHEMA_PROFILE` still accepts `compact`. Server-side validation is unchanged. * test(mcp): validate replies against canonical output contracts at every listed-schema reader tools/list omits output schemas by default, so fixtures, verifiers and the Android analysis runners that read a listed outputSchema now bind the canonical contract instead. connectLocalToolsMcp and advertisedMcpToolSchemas hand the SDK a definition carrying the canonical output schema, so the SDK client and caller-supplied validators check every successful reply. * test(mcp): resolve Android runners' output contracts from the selected repository The Android efficiency runners imported the canonical output-schema helper from the harness checkout while --repository selects the revision under test. Import it from the selected repository, as the runners already do for the SDK and Ajv. * test(mcp): let Android runners compare revisions before the canonical output helper A selected revision without scripts/lib/canonical-output-schema.mjs could not start the Android runners. Choose the output contracts in one harness helper: the selected revision's canonical contracts when it has them, otherwise its listed schemas under the full output profile it still supports. * fix(scripts): keep caller launch settings when the real Hopper verifier builds its server environment The verifier deleted REA_VERIFY_SERVER_COMMAND and REA_VERIFY_SERVER_ARGS_JSON from process.env itself before reading them, so a caller selecting an installed REA command silently ran the checkout's dist/main.js. Copy the environment, as main does, so only the child's environment changes. * test(mcp): validate whole replies against canonical output contracts wherever a listed definition is held tools/list omits output schemas by default and the full output profile is gone, so tests that handed the SDK a listed definition no longer checked complete replies. Attach the canonical output schema with withCanonicalOutputSchema at every held REA tool definition. Environment-served tools (not REA contracts), and the deferred-runtime and doctor tests that exercise per-profile listings, keep their listed definitions. * test(mcp): record the advertised catalog summary without the retired full profiles Retiring the full input and output profiles leaves only the compact input and compact output listings, so the summary drops the full-profile digests and every pattern only the full listings carried. Regenerated with npm run verify:advertised-schemas -- --update-summary.
46 KiB
Client and agent verification
FreeBuff MCP loading and personal skill discovery are currently unverified with an installed native client/version. Its temporary-filesystem coverage verifies REA's configuration and applicability boundaries only; it does not establish that FreeBuff consumes the written registration or skill.
Use these optional lanes to verify an installed client or evaluate an agent's REA workflow. Testing REA provides the normal development commands and provider lanes. Each record below states its host, client version, model fixture, and remaining coverage; a native-client run with a loopback model does not establish live model-service acceptance.
Launch environment verification
rea mcp doctor --json starts the production MCP adapter with the current runtime
executable and environment. A healthy result establishes that adapter's
initialization, discovery and target-free request flow, with the request-flow
reply validated against the canonical binary_session output contract whatever
output schema profile the server lists. It does not verify a
client's configured launcher or its inherited environment. Test the generated
registration through the actual client, including a reduced PATH when checking
desktop or service startup. Record the client version and launch environment
separately from terminal doctor results. See launcher troubleshooting.
Published Pi code-mode renderer limit
A separate probe of the published @earendil-works/pi-codemode 1.1.0 and 1.2.0
declaration renderers rendered the full compare_web_captures input as
args: unknown: its generated TypeScript type exceeds Pi's 16,000-character
default. REA keeps the full advertisement's fields by inlining references when
the shared form would exceed Pi's 32-reference expansion limit; retaining that
shared form would leave later fields unknown instead. The compact
input presentation keeps advertised inputs below its character limit by
reducing nested validation structure, while REA continues to validate calls
against the complete canonical input schema. See the compact input schema profile
for details of its reduced forms.
Custom renderer hosts can raise inputMaxChars through renderToolSignature or
renderToolSample; renderDeclarations does not expose that override. The
probe exercised the published renderer code, not a native Pi host or model, and
does not establish broader Pi compatibility. See the pinned upstream
declarations.ts
and renderer usage notes.
Cline
The original contributor reported a run on 2026-11-11 on Linux (Fedora 45),
using Cline CLI 3.0.74 and the integration based on REA main at 9924bf344.
That run checked client config listing and a direct registered-server MCP
handshake that listed the complete catalog of that build. It predates the
verifier lifecycle changes below and does not establish their real-client
behavior.
npm run verify:cline-client creates its sandbox home before launching commands
and removes inherited CLINE_MCP_SETTINGS_PATH, CLINE_DATA_DIR and CLINE_DIR.
Setup therefore exercises the default
~/.cline/data/settings/cline_mcp_settings.json path under the sandboxed home.
Cline's CLI must list that registration using the sandbox's explicit
--data-dir; this checks the file parser, not independent default-home discovery.
The exact registered launcher then
completes SDK initialization and tool discovery through REA's owned stdio
transport. Stdin stays open until discovery finishes. Command and transport
cleanup completes before the verifier records lineage or reports success.
The updated orchestration has recording-port coverage for delayed discovery, failed server identification and failed cleanup. These tests use the installed SDK and verifier lifecycle owner, but do not execute Cline or a real REA server. The updated real-client lane has not been rerun during this reconciliation.
Not covered by the lane: a model-driven tool call inside Cline. Cline's provider
configuration (providers.json) is versioned and auth-shaped, and the CLI ignores
OPENAI_BASE_URL, so the loopback model fixture cannot drive it without depending
on that private schema. The IDE extension is not covered either: its MCP settings are
UI-managed and live under editor-specific globalStorage roots, which rea setup
does not write in this release.
llama.cpp
The manual stdio connection was checked on
macOS arm64 with Node.js 24.18.0, llama-server b11715 (9d1878a43), and the
published rea-agents@6.5.0 package. GET /tools exposed REA tools without
enabling llama.cpp's built-in tools. With the source checkout at 9e372c6, all
forwarded names, descriptions and input schemas matched a direct MCP client.
Calls through POST /tools returned session metadata and JavaScript analysis
Evidence for a fixture at a Unicode path. A missing target returned REA's input
error, and a subsequent session call still succeeded. The owned llama-server
process exited successfully after the checks. No native analysis engine or
Windows host was exercised.
A local Qwen3-1.7B Q8_0 run selected the JavaScript analysis tool and received its Evidence, but its follow-up answer reached the output-token limit. Other small Qwen3 attempts returned proposed calls as ordinary JSON text rather than tool calls. These runs do not establish dependable model-driven investigations. A request with the full catalog and task history exceeded a 16,384-token context; select tools for the task instead of assuming that discovery implies model fit. The checks exercised HTTP and stdio, not browser interaction with the Web UI.
End-to-end, integration and golden evidence
The optional verify:qwen-client, verify:pi-client, and verify:hermes-client
lanes require an installed native client. Select its executable with
REA_VERIFY_QWEN_COMMAND, REA_VERIFY_PI_COMMAND, or REA_VERIFY_HERMES_COMMAND.
They configure disposable profiles through the public REA CLI, preserve caller
settings and backups, and exercise real stdio MCP calls and skill loading. The
call mode checks complete catalog discovery and actual JavaScript Evidence;
pass -- chat to check plain chat with REA enabled. Qwen also reads the full
result that its client offloads, and Pi exercises default codemode execution.
Use REA_VERIFY_RUNTIME_ROOT to select a production-only installed REA package.
Receipts retain client versions, result digests, host coverage and owned-process
cleanup. These lanes use a deterministic loopback model and do not prove live
model-provider compatibility. Pi and Hermes remain POSIX-only. Qwen, Pi and Hermes
bind both HOME and USERPROFILE to the disposable account. Qwen and Pi discover
the shared personal skill through their default search paths without an explicit
skill setting; Hermes discovers it through the selected HERMES_HOME.
Set REA_VERIFY_HERMES_STICKY_PROFILE=1 to exercise native Hermes selection of
a named sticky profile with HERMES_HOME still pointing to its root.
For Qwen on POSIX, set REA_VERIFY_QWEN_REDUCED_PATH=1 and select its JavaScript
entry point with REA_VERIFY_QWEN_COMMAND to test a restricted client environment.
Setup retains the caller's PATH; the native Qwen chat or call run then uses
an isolated PATH containing only Bash for the shell-tool fixture. The lane
checks that node, npm and npx cannot be found and uses the generated REA
registration unchanged. Its receipt records reducedPath, clientPath and
registrationCommand; the option alone does not establish a passing native run.
The Qwen lane also supports native Windows (verified with Qwen Code 0.25.1 and
Node 24.19.0 for both chat and call). With Node 24.18.0, the same call
journey reached full Evidence readback but the client aborted during exit with
UV_HANDLE_CLOSING; that run remains a failure, not a compatibility claim.
Select the npm install's
node_modules/@qwen-code/qwen-code/cli-entry.js with REA_VERIFY_QWEN_COMMAND,
because execFile cannot launch the qwen.cmd shim directly. A selected .js,
.mjs or .cjs entry point runs under the verifier's Node. Windows path checks
use native separators; persisted output is read through Qwen's real shell tool
with a shell-independent encoded Node payload. Windows receipts report process
lineage as unavailable when the verifier has no retained native Job Object lease.
verify:gemini-client requires an installed Gemini CLI (verified with
@google/gemini-cli@0.63.0 on POSIX and native Windows); select it with
REA_VERIFY_GEMINI_COMMAND. A selected .js, .mjs or .cjs entry point runs
under the verifier's Node. On Windows, select the npm install's
node_modules/@google/gemini-cli/bundle/gemini.js, because only a gemini.cmd
shim reaches PATH.
The optional lane uses native GEMINI_CLI_HOME discovery in an isolated
Git project, checks setup plans, backups and idempotence, activates the installed
personal skill, validates all forwarded input JSON Schemas against their declared
dialect, forwards the complete REA catalog and checks full JavaScript
Evidence for a Unicode path. Use -- chat for ordinary chat with REA enabled,
or REA_VERIFY_RUNTIME_ROOT for a production-only installed REA package.
The local fixture exercises the real Gemini API adapter, including its
untrusted_context tool-result envelope. Token counts are synthetic; live
Google API compatibility remains unverified. The lane disables
the client's memory-based relaunch to preserve the caller's Node heap budget.
verify:opencode-client requires an installed OpenCode (verified with
opencode-ai@1.18.35); select it with REA_VERIFY_OPENCODE_COMMAND.
The optional POSIX lane configures isolated XDG roots and OPENCODE_CONFIG_DIR,
checks setup plans, backups, preserved JSONC comments and idempotence, activates
the installed skill, validates all forwarded input schemas and verifies complete
JavaScript Evidence for a Unicode path. JSONC is the default fixture; set
REA_VERIFY_OPENCODE_CONFIG_FORMAT=json for JSON. Use -- chat for ordinary
chat or REA_VERIFY_RUNTIME_ROOT for a production-only installed package.
The native core runs with external plugins disabled through OPENCODE_PURE;
the local OpenAI-compatible fixture has a caller-declared one-million-token
context and synthetic usage. Skills use an explicit isolated skills.paths
directory, so default OS-home discovery remains unverified. Live model APIs and
native Windows are also unverified.
verify:claude-client requires installed Claude Code (verified with
@anthropic-ai/claude-code@2.1.296 on POSIX and native Windows); select it
with REA_VERIFY_CLAUDE_COMMAND. On Windows, select
claude.exe: npm installs put only a claude.cmd shim on PATH, and the real
executable is under node_modules/@anthropic-ai/claude-code/bin.
The optional lane uses native CLAUDE_CONFIG_DIR discovery, an independent
Git workspace, user settings and default built-in tools. It preserves caller
preferences and backups, checks idempotent setup, waits through the native
WaitForMcpServers tool when discovery is pending, and validates the complete
catalog and forwarded input schemas. Call mode loads the personal skill through
native Skill, checks its full body and verifies named-schema JavaScript Evidence
for a Unicode path. Use -- chat for ordinary chat with REA enabled, or
REA_VERIFY_RUNTIME_ROOT for a production-only installed package. The local
Anthropic Messages/SSE fixture preserves native resource-hint envelopes in its
request artifacts. Usage is synthetic; live Anthropic API and bare-mode
personal-skill activation remain unverified by this lane.
verify:copilot-client requires installed GitHub Copilot CLI (verified with
@github/copilot@1.0.95); select it with REA_VERIFY_COPILOT_COMMAND.
The optional POSIX lane uses native COPILOT_HOME discovery, an independent
Git workspace, guarded setup plans, preserved registrations, backups and
idempotence. Native skill add registers the isolated installed skill; call
mode loads its full body, validates all forwarded input schemas and checks
named-schema JavaScript Evidence for a Unicode path. When Copilot spills a
large MCP result, the model requests native view with forceReadLargeFiles
and validates the complete returned Evidence rather than its preview.
Use -- chat for ordinary
chat or REA_VERIFY_RUNTIME_ROOT for a production-only installed package.
The native offline BYOK adapter uses a loopback OpenAI completions/SSE fixture
and gpt-5.4 model metadata; model inference and token usage are synthetic.
Set REA_VERIFY_COPILOT_MODEL to examine another client model ID and
REA_VERIFY_COPILOT_WIRE_MODEL for its backend model name (defaults to the client
ID). Every actual HTTP request's model is checked and recorded separately.
Both HOME and USERPROFILE point to the disposable account; native skill add
still selects the installed skill directory explicitly.
The same native client passed chat and analysis under REA's former full input
profile with the actual wire model gpt-4.1 under a distinct BYOK model ID:
REA_VERIFY_COPILOT_MODEL=rea-gpt-4.1 REA_VERIFY_COPILOT_WIRE_MODEL=gpt-4.1 npm run verify:copilot-client -- chat
REA_VERIFY_COPILOT_MODEL=rea-gpt-4.1 REA_VERIFY_COPILOT_WIRE_MODEL=gpt-4.1 npm run verify:copilot-client -- call
Those runs used the fixture's requested one-million-token BYOK prompt setting;
effective capacity and live API acceptance remain unknown. With the built-in
gpt-4.1 model ID, the verified client blocked the former full input-schema
profile before HTTP with compaction_static_context_blocked. That profile was
removed, so the verifier now compares the input schemas forwarded by Copilot
with REA's compact advertisement:
REA_VERIFY_COPILOT_MODEL=gpt-4.1 npm run verify:copilot-client -- chat
REA_VERIFY_COPILOT_MODEL=gpt-4.1 npm run verify:copilot-client -- call
The recorded client results above remain scoped to their executed revisions; this verifier change is not a new client run. Compact native workflows passed with the complete tool inventory. Compact advertisements can reduce nested validation structure; the server still validates complete canonical inputs. Live model APIs, native Windows and default OS-home skill discovery remain unverified.
verify:grok-client requires installed Grok Build (verified with the official
Linux x64 1.0.50 binary); select it with REA_VERIFY_GROK_COMMAND. This optional
POSIX lane isolates GROK_HOME, an independent Git workspace and additional
skill roots, disables foreign configuration discovery, guards setup writes,
preserves unrelated registrations/backups and checks idempotence. Call mode
loads the full skill through native read_file, queries all REA names and input
schemas through native search_tool, and calls analysis through use_tool.
If discovery reports partial, the native agent diagnoses REA registration and
retries discovery. No startup-timeout override or fixed readiness delay is used.
A larger Unicode-path fixture exercises native result offloading: the full
retained Evidence is validated against its named schema, then native terminal
queries recover the selected export facts, subject and full artifact digest in
the next model request. This verifies useful artifact recovery without claiming
that every offloaded graph fact enters model context. Native line-number and
truncation envelopes remain in the request artifacts. Use -- chat for ordinary
chat, or REA_VERIFY_RUNTIME_ROOT for a production-only installed package.
The loopback OpenAI completions/SSE custom model declares a one-million-token
context and synthetic usage. Live xAI APIs, native Windows and default OS-home
skill discovery remain unverified.
verify:commandcode-client requires installed Command Code (verified with npm
1.79.2); select it with REA_VERIFY_COMMANDCODE_COMMAND. Auth, MCP tokens and
sessions use the actual OS home, so provision a disposable POSIX account rather
than overriding HOME. Set REA_VERIFY_COMMANDCODE_ACCOUNT_HOME to that account's
actual home and create .rea-client-verification there with exactly
Disposable REA client verification account followed by a newline. The lane
owns that account's .commandcode configuration and shared REA skill. Build the
runtime as the checkout owner, then run node scripts/verify-commandcode-client.mjs
as the disposable account; the npm shortcut also needs a writable checkout.
The verifier does not create accounts or install clients. It guards setup
targets, preserves an unrelated registration and backups, checks idempotence,
and verifies native default shared-skill discovery and complete activation.
Default deferred-schema delivery stays enabled: the native prompt advertises
every REA tool, exact-name search_tools returns every input schema, and a native
shell query recovers the saved catalog's count and digest when the client spills
it. Actual analysis of a Unicode-path fixture delivers full named-schema Evidence
to the next model request. Use -- chat for ordinary chat or
REA_VERIFY_RUNTIME_ROOT for a production-only installed package. The loopback
OpenAI completions/SSE model is a keyless BYOK endpoint declaring a million-token
context with synthetic usage. A synthetic account-key value satisfies the
client's print-mode gate; native local-only mode refuses hosted API calls.
Updates, telemetry and cron are disabled. Hosted authentication, live models
and Windows remain unverified.
verify:omp-client requires installed OMP (verified with the official Linux x64
18.8.7 binary); select it with REA_VERIFY_OMP_COMMAND. This optional POSIX lane
isolates the default agent, global config and XDG roots, guards setup targets,
preserves unrelated registrations and backups, and checks idempotence. It
compares native rejection of an invalid profile with REA's refusal to plan
fallback writes. OMP's default xd:// interface mounts the complete REA catalog
as devices: call mode reads the complete installed skill and tool documentation,
then dispatches analysis through native write. It checks full named-schema
JavaScript Evidence with a Unicode path in the next model request. Device
metadata and documentation are distinct from forwarding all JSON schemas as
model functions. Native print-mode MCP readiness uses its defaults.
Use -- chat for ordinary chat or REA_VERIFY_RUNTIME_ROOT for a production-only
installed package. The loopback OpenAI completions/SSE model fixture declares a
one-million-token context and synthetic usage. Live model APIs, native Windows,
named-profile native execution and default OS-home skill discovery are
unverified; skill discovery uses an explicit isolated custom directory.
verify:deepseek-client requires an installed DeepSeek Harness (dsh;
verified with @deepseek-ai/dsh@0.2.0-rc.2) and Git. Set
REA_VERIFY_DEEPSEEK_COMMAND to select its executable. This optional POSIX lane
seeds caller model settings and a stale Cordis registration in an isolated
DSH_HOME, then runs public setup --client dsh dry-run, setup, repeated setup,
and scoped doctor. It checks the backup and unrelated patches before booting
Harness with the generated registration. After native execution it uninstalls
through the public CLI and checks that only caller patches remain. HOME and
USERPROFILE point to the disposable account. The native default
~/.agents/skills search path discovers
the installed skill without a DSH_AGENTS_HOME override. A separate Git root prevents inherited project skills from
masking a missing installation. The default call mode checks skill loading,
complete catalog discovery, the actual forwarded input schemas and regexes,
and full JavaScript Evidence for a Unicode path. Use -- chat for ordinary
chat with REA enabled, or REA_VERIFY_RUNTIME_ROOT for an installed package.
The fixture uses Harness's custom OpenAI adapter and the one-million-token
context capacity declared by its default DeepSeek Flash model; it does not
establish live DeepSeek API or native Windows coverage. Receipts include
request artifacts, result digests and owned-process lineage.
The DSH acceptance journey also exercises public setup, approval, doctor, generated-launcher MCP startup and uninstall without an installed Harness. That journey proves REA workflow behavior, not native Cordis expression evaluation. Filesystem regressions retain tagged values and unrelated rows across alias dependencies and check refusal of unsafe YAML without mutation.
Full E2E tests invoke the production command dispatcher and real providers,
without fake launchers, runners or responses. verify:keyed-archive writes
Foundation binary, XML, and integer archives using one run-owned Swift module
cache. It checks CLI and separate stdio MCP parity, pagination, escaping-path
rejection, an XML graph golden, and numeric meaning for safe controls, unsafe
integers, boxed numbers, and integral-valued reals. verify:asset-catalog
compiles source-owned colors with
actool, invokes real assetutil, then checks CLI/MCP results, exact catalog
digest, every raw metadata field, pagination and malformed input rejection.
Neither artifact workflow requires Hopper or launches it. Both run in macOS CI.
verify:macos-bundle needs only macOS with Command Line Tools. It compiles a
source-owned app with clang: a versioned framework, XPC services, an app
extension, a login item, a privileged helper, launchd plists, and a helper tool,
signed ad hoc. It packs the app as a directory, a ditto ZIP, and an APFS DMG,
then checks that inspect-artifact plus project-apple-application-graph
report the same bundle anatomy for all three through the CLI, with stdio MCP
parity. It also checks that the DMG is detached afterwards. The same app
covers trace-dylib-resolution:
- each resolution status and finding, with CLI/MCP parity;
- for every traced image, dependencies, rpaths, and install names equal to
otool -l; - for the main executable and an XPC service, a predicted load order equal to
the images dyld actually loads under
DYLD_PRINT_LIBRARIES.
The lane also compiles executable/library pairs with empty embedded directory,
versioned-path, and suffix settings. It checks present and removed dependencies
through CLI and MCP, and compares actual DYLD_PRINT_SEARCHING diagnostics for
root-level candidates. These cases distinguish an empty search directory from
an empty versioned scan or a suffix that only repeats the original path.
It runs in macOS CI.
Prepare the native inspector before cases that measure producer output or exit behavior; keep startup deadlines and cancellation in distinct cases. Run real process-capture verification separately from package or build checks. On macOS, new npm processes can become token-unreadable after changing their display title and prevent verified cleanup during a capture's ownership sweep.
MCP SDK transport tests with recording providers remain integration tests.
They are useful for schema drift and failure projection but do not prove that
Hopper, Ghidra or another substituted engine works. verify:package proves
packaging/install behavior and fake-provider integration; use the corresponding
real-provider lanes for engine claims. Packed-bridge checks verify shipped files and Python syntax.
Real Apple dispatch and Interface
Builder verifiers currently prove format integration through production readers.
verify:hopper exercises an installed Hopper through the production stdio MCP
server and CLI. It checks source-owned call chains, CFG edges, references and
complete large inventories, then probes unnamed bookmarks, annotation clearing,
batch validation before mutation, malformed addresses and regexes, segment-end
partial reads, and synthetic file-offset rejection. Advertised schemas are
validated in their JSON Schema dialect and successful replies are checked against
their advertised output schemas. Navigation checks cover interior-object cursor
readback and mapped-memory boundaries. Annotation probes verify invalid native
text and duplicate destinations/names before mutation, preserve unselected label
owners, and exercise explicit batch label swaps. Function locals retain observed
names and stack displacements. Graph probes check symbol/interior-address parity
and a source-owned recursive cycle; literal tracing preserves complete queries
and whitespace. Disposable binary copies prove that switching and closing
actually removes the native document, and that CLI byte, function-dossier,
literal-trace results and invalid-address diagnostics agree with MCP.
No provider is mocked in this lane.
Real search probes cover Unicode names, literal metacharacters, case and regex
modes, annotation cache invalidation, complete native fragments of long literals
checked against byte reads, escaped UTF-8/control text, byte-preserving Latin-1
decoding, and Hopper's UTF-16 symbol-name truncation boundary. It verifies native
CallReference classifications across reference and dossier results, retains long
string fragment metadata in dossiers, and exercises pathological regex deadline
and cancellation followed by successful requests in the same native session. When the macOS
Objective-C fixture is present, the lane also verifies native UTF-16 string objects
and their inferred encodings against their actual bytes. Native terminal calls
are checked across reference, instruction, assembly, block-range and procedure-length
projections; block endpoints are normalized using actual native membership.
Exact Objective-C names also exercise named CLI selectors for function, instruction,
decompilation, reference and search operations. A literal --help trace query proves
that selector data is preserved independently of global CLI flags.
Unmapped annotation destinations and
oversized later batch names fail before any earlier edit is applied.
verify:hopper:deadlines checks the native client's optional request deadlines
on macOS with an owned source-built fixture. Zero and elapsed deadlines must
leave native comments unchanged, including when a synchronous progress observer
delays timer dispatch. It also observes a short analysis deadline and verifies
subsequent wire recovery and clean shutdown. Caller timeout does not interrupt
Hopper's synchronous native operation. Socket boundary tests deterministically
cover active and queued expiry, late replies and timer cleanup.
The Linux demo lane remains a separate verify:hopper:linux command. Hopper
6.4.2's ELF loader did not recognize the original 4,119-byte literal or three
non-ASCII byte strings in the measured fixtures. The lane retains complete raw
byte checks for those literals through source-owned symbols. Recognition of the
original full-length literal is bound to its exact source address; its decoded
object coverage remains explicitly unverified on Linux even when recognized.
Absent non-ASCII recognition also reports decoded-object coverage as unverified.
Recognized non-ASCII and control-text objects must still match their source
bytes, encoding, filters and searches.
A separate 548-byte ASCII literal requires native fragmentation, shortened
provider display, complete decoded fragments and dossier provenance on Linux;
the macOS lane retains the original full-length recognition requirement. These
are observed fixture/build capabilities, not universal Hopper length limits.
Its lifecycle checks attempt competing CLI launches for the active target and a
different target, requiring rejection before either can change the owning
MCP session's documents or procedures. Lease boundary tests also preserve
unresponsive or malformed live endpoints while allowing confirmed stale
sockets to recover.
verify:setup:linux exercises installation on a clean supported Linux runner as
root. Use a disposable VM: this lane installs Hopper and its Linux runtime
dependencies through the system package manager. Set REA_VERIFY_SERVER_COMMAND
to the CLI entrypoint being verified. The command builds and checks source-owned
ELF fixtures before testing the read-only Hopper setup plan, approved
installation, scoped doctor, real CLI/MCP analysis, rejection of a modified
launcher, idempotent setup without requesting a reinstall, and owned child
cleanup. Before installation and after teardown, a clean-runner process scan
also rejects surviving Hopper demo helpers or Xvfb groups, including orphans
whose launcher exited. This scan observes processes without signaling them.
Hopper detection compares executable file identity through /proc, covering
alternate or configured launcher paths even after an invoked symlink is removed.
The dedicated runner must have no unrelated Hopper/Xvfb sessions. It requires
the repository's pinned development toolchain and an
existing host C compiler, file, nm, and strings. Use verify:hopper:linux
instead when Hopper is already installed.
verify:hopper:fat is a separate macOS lane requiring installed Hopper and the
existing Xcode clang/lipo toolchain. It compiles arm64/x86-64 thin executables and
one- and two-slice FAT32 containers, verifies exact/interior address mappings
against bytes in the original files, checks CLI/MCP parity, and checks owned
runtime cleanup. Source byte changes, removal, permission denial (for non-root
callers), and nonregular replacement must retain native partial mapping facts,
reject unverified original-file coordinates,
and recover after restoration. Single-slice FAT cases also relocate the slice
without changing its loaded bytes. verify:hopper:fat64 additionally checks
FAT64 preparation through Hopper's native Mach-O loader, source-container
mappings, profile identity,
malformed and ambiguous slice rejection, and temporary-image lifetime. Both
lanes have been verified on Hopper 6.1.0-demo; this establishes REA's prepared
FAT64 workflow, not native FAT64-loader support.
Cross-architecture fixture compilation is not required by verify:hopper.
Golden tests use immutable captured text inputs with producer/source provenance
under tests/fixtures/golden/. Expected results are reviewed for the semantic
claim; capture commands do not automatically approve new expected outputs.
Do not call handcrafted utility output or synthetic binary builders real-data
goldens. Keep unsupported binary layouts and malformed boundaries as targeted
regressions until a real fixture establishes equivalent coverage.
verify:browser exercises source-map failure isolation and expanded-output limits through the compiled CLI and stdio MCP with real Chrome. It also submits five 2 MiB source-map annotations, checks retained script identities and explicit map omissions, and closes its owned fixture target. Replacement and document-reset behavior has separate producer-boundary coverage.
The raw Chrome fixture launchers use --password-store=basic so Linux startup
does not wait for an unlock prompt from a reachable but locked desktop keyring.
Such a stall leaves the initial page unloaded with empty or placeholder CDP URLs;
it does not establish permission to capture that page. See
the keyring diagnosis.
On Windows, browser verifier lanes that launch an owned fixture require a standard, non-elevated caller token. They inspect the verifier caller before allocating fixture resources and refuse elevated or unobservable tokens; they do not change caller authority or claim to inspect the browser process token.
verify:browser also captures a source-owned noise canvas as a real PNG above
8 MiB through the CLI and stdio MCP, with complete byte/digest parity and real PNG
decoding. Its SDK client explicitly permits the larger inline JSON response;
this lane does not establish large image-comparison request transport coverage.
The scenario checks read locale, timezone, device scale and viewport dimensions from actual page JavaScript through CLI and stdio MCP DOM captures. They also verify that attached-page emulation is released after success, initialization failure, action failure and cancellation while the external target stays open.
verify:browser:network is a focused real-browser lane for transaction identity,
selected request/response bytes, binary and compressed responses, duplicate
headers, credential and declared-secret redaction, redirects, streaming cutoff,
CLI/MCP parity, and owned-profile cleanup. Set REA_BROWSER_EXECUTABLE to an
installed Chrome-family browser. An optional script argument selects an already
installed package's scripts/rea.mjs entry point for packaged-artifact checks.
The complete verify:browser lane includes these same checks.
After building, verify:browser:dom checks empty and HTML-whitespace form
destinations against a native Chrome DOM-property oracle through CLI and stdio
MCP. It requires REA_BROWSER_EXECUTABLE and accepts an optional installed REA
entrypoint. The full browser lane includes the same public-adapter assertions
before other fixtures navigate the selected page.
verify:browser:scripts checks active script capture → exact-byte export →
existing static JavaScript analysis through CLI and stdio MCP, including
manifest readback, competing query variants, and resolved relative imports.
It uses an installed browser and accepts an optional installed REA entrypoint.
The complete verify:browser lane also exercises passive script export through
both public adapters. See website script export.
verify:browser:modules compares CLI and stdio MCP traces against an independent
real Chromium module-loading fixture: import-map scopes, package prefixes,
null/backtracking rejection, query/fragment identities, repeated module instances,
lazy and computed unknowns, exact source/map identities and no implicit refetch.
Set REA_BROWSER_EXECUTABLE; the optional script argument selects an installed
package entrypoint. The complete verify:browser lane and existing conditional
Chrome CI include this verifier. See module relationships.
Agent evaluation and conformance records
Evaluate native, JavaScript, managed and browser investigation tasks through a real local Codex CLI with:
npm run verify:agent
The verifier's scenarios, transcript scoring, fixture rubrics, and report gates
are development verification code under tests/evaluation/model-evals/. The
source-owned evaluator runs alongside the compiled REA tools; it is excluded
from the shipped runtime package.
The lane runs scenarios sequentially in standalone Codex (--no-daemon) with a
disposable HOME and CODEX_HOME under ~/.cache/rea-agent-evaluations/. Set
REA_AGENT_EVAL_ROOT to choose another parent directory outside the OS temporary
directory: current Codex refuses helper aliases under /tmp, preventing shell
commands and skill reads even if MCP works. Each owned run directory is removed
after verification unless fixture retention is requested. Commands share the
owned-process supervisor: native ownership preparation has its own bounded
deadline before each short command budget, and timeouts join bounded process-tree
and output cleanup before returning. If cleanup remains incomplete, the lane retries its retained
owner and preserves the run directory (including disposable auth) rather than
removing files still in use; the error retains ownership and recovery details.
Command stderr is limited to 32 KiB and combined version output to 8 KiB;
exceeding these diagnostic budgets fails explicitly. Scenario JSON events stream
to the evaluator without retaining a second raw stdout copy. Cleanup attempts the
remaining run tree even if auth removal fails, and reports unresolved cleanup
together with the original verification failure. The lane
installs the packaged skill and MCP registration through public rea setup,
rather than copying a skill into a project that also inherits the caller's
skills and configuration. Only authentication is copied, when present, and it
is removed after confirmed process cleanup even with
REA_AGENT_EVAL_KEEP_FIXTURES=true. No user configuration,
rules, plugins or history is copied; shell snapshots and additional agents are
disabled. Existing API-key environment authentication remains available.
The native provider scenario preapproves only open_binary and
close_binary in the disposable client so it reaches REA's actual provider
boundary instead of stopping at Codex approval. Its scenario contract accepts
one provider_unavailable open refusal without a close, or one successful open
followed by a successful close. Other errors, an unclosed session, and a close
without acquisition fail. These outcomes and the prompt are owned together in
tests/evaluation/model-evals/AgentEvaluationScenarios.ts; generic successful-tool sequences
still apply to scenarios that require them. The provider scenario checks routing,
reported limitations, and cleanup; free-form answer correctness remains
unassessed. It does not validate a real native engine or authorize runtime execution.
Select a smaller run with REA_AGENT_EVAL_SCENARIOS, a comma-separated list of
scenario IDs. asar-zh exercises the packaged desktop rubric from a Chinese
request. javascript-module-view exercises summary analysis, module paging and
item inspection in a tree with unrelated modules; its routing and text checks
remain heuristic, so review the retained transcript for selector choice and
coverage claims. Set REA_CODEX_CLI to an installed Codex executable and
REA_AGENT_EVAL_MODEL to an account-supported model. Use an external resource
limit for the whole process tree when testing on a constrained host; a Node
heap limit alone does not bound client and child-process memory.
missing-target leaves desktop fixtures visible without selecting one in the
request. It requires zero REA calls and a JSON-only request for an app name or
artifact path, with no preceding prose or Markdown fences. Its prompt and
whole-answer validator are defined together in AgentEvaluationScenarios.ts.
Its expectedFirstTool is null, and
targetClarificationPassed grades that limited routing outcome independently
of analysis prose heuristics. Analyzing a nearby example cannot pass this case.
The packaged desktop, parser-comparison, and managed scenarios assess a closed set of known fixture claims. Each final answer must be a strict JSON manifest containing exactly the requested claim IDs, values, Evidence IDs, and Evidence authority and confidence. Golden values are not included in the prompt. The evaluator checks exact values against both the fixture oracle and authenticated successful REA results; an Evidence ID by itself is insufficient. Missing, duplicate, extra, contradictory, incorrectly sourced, or unsupported claims fail the scenario.
The desktop rubric covers the exposed bridge API and members, renderer and main IPC operations, and the resolved preload. It binds its Evidence to the exact packaged artifact path and SHA-256. The parser rubric checks the precise heading depth addition, discriminant, complete comparison counts, and the explicit limit on runtime semantics. Its comparison must link to the two delivered source analyses and use the requested module and export selectors. Boundary tests package the same source-owned desktop fixture and compare the same source-owned parser files through actual MCP tool results, then verify that fabricated answers fail.
The managed rubric checks the exact public top-level type set and the CLI entry
point's declaring type and method name. The exact type-set claim requires an
unfiltered member inventory: selection must be null and the Evidence parameters
must omit type_names. A selected inventory can still ground the entry-point
claim. Both inspections must describe the freshly built DLL's SHA-256. Entry-point
resolution additionally requires complete artifact and member metadata, matching
non-null module MVIDs, and a unique method at the header's metadata token. These are
static metadata claims, not runtime behavior;
compiler-generated member counts, token values, and MVIDs are not golden answers.
Per-scenario factualCorrectness is passed, failed, or not_assessed within
the configured_fixture_claims scope. A pass establishes only the configured
claims, not unrestricted factual correctness. Native, browser,
navigation-context, and address-context scenarios have no factual rubric and
remain not_assessed.
The closed factual scenarios request complete producer Evidence on the initial
inspection or analysis so their source selectors can authenticate all configured facts.
Summary/page/item workflows are exercised separately by javascript-module-view;
its heuristic gate does not establish full-producer factual correctness.
All scenarios retain routing, workflow, validation, repetition, process-exit,
and token-use gates. Configured factual scenarios additionally require a factual
pass. Their answer-text heuristics are diagnostic and do not affect the gate.
Validation counts include complete text-only REA invalid_request envelopes
and failed SDK calls whose arguments violate the named current REA contract.
Client approval rejections and provider unavailability remain distinct failures;
truncated JSON previews are not parsed into invented error codes.
Repeated binary_session observations separated by a successful open_binary
or close_binary are treated as lifecycle verification. An unchanged retry,
including one after a failed lifecycle call, still counts as repetition.
Scenarios without a rubric retain the legacy text-heuristic gate.
answerTermCoverageMet checks case-insensitive substrings,
epistemicCuePresent checks keywords, and finalCitesEvidence checks only an ID's
presence. These metrics can still accept fabricated prose and must not be read
as factual assessments. Set REA_AGENT_EVAL_TRANSCRIPT_DIR to retain complete
tool results and final answers for review.
Report schema version 4 adds negative routing scenarios with nullable
expectedFirstTool and a targetClarificationPassed outcome. Consumers must
allow an expected absence of REA calls; this does not make an analysis scenario
pass without its required tools. Native provider records additionally report
scenarioOutcome (provider-unavailable, opened-and-closed, or failed) and
scenarioOutcomePassed; a failed outcome fails the gate independently of prose
heuristics. Version 3 changed the top-level
factualCorrectness from a constant
string to an assessment summary with status, scope, and assessed/passed/failed/
not-assessed scenario counts. Scenario records include the factual assessment and
configured claim IDs. The evaluation scope is
routing_workflow_and_configured_fixture_claims. Update report consumers for
these changes. The narrower heuristic field names introduced in version 2 remain:
answerHeuristicsMet, epistemicCuePresent, answerTermCoverageMet, and
requiredAnswerTermGroups.
Regenerate the managed conformance manifest and Evidence completion ledger from live verification results, or check them for drift:
npm run evidence:generate
npm run evidence:check
The records preserve unsupported and unverified coverage as explicit unknowns. Run the matching real-tool prerequisites described in this guide.
Focused tool-description trials
For a wording or discoverability question, begin with one representative case per affected workflow boundary and its nearest valid alternative. Repeat a concrete failure or ambiguous result after repair. Add repetitions when the requested confidence or comparison needs them; a large matrix is not the default. Use the user's selected model and budget, and verify the actual client and Node executables used by the trial rather than assuming the development shell's versions apply.
Reuse the existing optional lane and source-owned scenarios where they fit:
REA_AGENT_EVAL_SCENARIOS=javascript-module-view npm run verify:agent
Select the account-supported model with REA_AGENT_EVAL_MODEL. Read the selected
prompt and rubric before interpreting the gate: closed factual scenarios request
complete producer Evidence, while javascript-module-view exercises retained
views with heuristic scoring. Neither gate alone proves correct selection or
fully supported prose for a different task. Extend the narrow scenario or grader
in the existing evaluation tooling when necessary; reusable runners and fixtures
belong there, not in skills or copied temporary harnesses.
Capture the actual initialize and tools/list surface. Compact presentation may
remove parameter descriptions or nested selector shapes, so a concise exact call
example can remain necessary. Verify the producer-to-consumer handoff before
removing its visible syntax. For a wording comparison, hold prompts, schemas,
tool order, fixtures, permissions and host settings fixed; change one surface at
a time. Use fresh agent context without the audit's answers. Record later source,
fixture or runtime changes separately rather than claiming a controlled delta.
Score these outcomes separately:
- Tool selection, accepting other valid routes.
- Canonical argument validity and the exact requested paths, IDs, selectors, fields, units and delivery. Structurally valid arguments can select the wrong input; fixtures should refuse that selection instead of returning the expected answer anyway.
- Recovery and cleanup. A valid unresolved lookup is not a malformed request; normal status reads and cleanup-only retries are not automatically mistakes. Do not infer that work stopped from a host-only timeout.
- Final claims against returned facts and coverage. Correct text does not erase malformed-call loops, and valid calls do not prove every claim. A failed name lookup is not a negative reference search; an exhausted partial page does not establish absence in unexamined source. Generic responses without state facts cannot establish that a session is closed.
Retain prompts, condition/catalog hashes, actual calls/results, failures, final answers, model/client/runtime versions and cleanup outcomes. Report whole-task input, cached input, output and elapsed time when available, and label unmeasured CPU or process-family memory. Fewer description bytes do not establish fewer task tokens or faster execution. Remove copied authentication after owned processes settle and review retained artifacts before sharing them.
Controlled errors can test agent recovery without target effects. Label them as simulated and verify applicable workflows separately through the production adapter and real provider boundaries. State tool-subset versus full/progressive catalog scope and remaining provider/host coverage. Small one-shot trials are smoke checks, not statistical success rates or evidence that newer models need less guidance in general.