runProductionMcpDoctor wrapped the SDK StdioClientTransport and only joined its
close calls. That transport clears its direct-child reference, ends stdin and
signals only that child, so a server whose launcher exited after forking an
inherited-stdio descendant left the descendant running while the doctor
reported nothing but the transport deadline.
Run the doctor on OwnedMcpStdioTransport, which spawns the child in a dedicated
POSIX process group or Windows job and verifies group and token-owned
descendant cleanup before close returns. Feed stderr through a sink on
acquisition so diagnostics survive an early child exit and still honor the
64 KiB retained prefix and full byte count.
Covered by a fixture that forks a descendant, exits, and is timed out: the
regression asserts the descendant is gone after the doctor returns.
A terminal call on one branch does not end the whole function: other
branches can still reach the following code, which stays in the body and
pseudocode. The function-level limitation now says Ghidra excluded that
call's fall-through and that code reachable only through it is missing
if the callee returns. It is listed before the call-specific facts so a
bounded composed summary that admits limitations in order keeps it.
The body-coverage tests now check the counted records and their reasons
instead of freezing the explanatory sentence.
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ghidra's Non-Returning Functions - Discovered analyzer can mark a
returning callee, such as an imported operator new thunk, as
non-returning. Ghidra then clears the fallthrough at each call site and
refits the callers, so a constructor decompiles to a few plausible
lines. REA reported the terminal call with the FunctionManager flag but
did not say the result omits the code after it or how to compare.
That analyzer bookmarks each entry it marks with the Analysis comment
"Non-Returning Function Found" (Ghidra 11.0 through 12.1.4 source); the
name-list Known analyzer writes "Non-Returning Function Identified".
When a terminal call's callee, or the function a thunk forwards to,
carries the Discovered bookmark, the call's limitation now says the
flag was inferred, and the function adds one address-free limitation
that its body and pseudocode end at that call and omit the following
code if the callee returns, with the REA_GHIDRA_DISABLED_ANALYZERS
comparison. A flag without the bookmark keeps an unknown origin.
The function-boundary observation contract moves to v5 so snapshots
from earlier bridges are not replayed without the qualification.
Refs #10365
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
decompile_all set its top-level "procedure_info is unavailable" caveat
from a per-call flag that only a newly attempted function could raise.
A resume that skipped every verified file, or selected nothing, rewrote
the manifest and decompile-index.json with an empty limitations list
while every retained record still reported an unavailable body.
The export owner now answers from the records it retains: the summary
counts every non-external record whose body is unavailable, including
records an earlier run wrote, and repeats the reason when all share one.
The per-call flag is removed. A fresh export whose procedure_info works
but leaves some bodies unavailable now reports that caveat too; a later
attempt that records a known body clears it.
Fixes#8351
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The handler regression added in #10390 listed tools under the full input
profile and matched every advertised schema before calling each tool. It
took about 14 s locally and passed the 30 s deadline on loaded CI runners.
advertisedPatternsVMode.test.ts already proves that no input or output
profile advertises the surrogate escape, so this case now checks only the
runtime refusal through the default-profile handlers, as the
relative-path case does.
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rea mcp --http printed "Choose another --port or stop the process using
it" for every listener failure except a missing host allowlist, so a host
lookup failure, an unassigned address or a permission denial got port
advice. StreamableHttpListenError already classifies the native failure
and owns a recovery for each kind.
Startup now always prints that owned recovery behind one shared lead-in,
and the fixed message is removed. The native cause text stays out of
stderr as before.
Fixes#7346
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shared reader lifecycle case waits for a member's writable side to
finish before it reads anything. That only happens while the member fits
below the readable high-water mark. Node's default is 16 KiB on Windows and
64 KiB elsewhere, and the ESP flash fixture's first member is a 32 KiB
bootloader region, so both cases hung until the 30 s timeout on Windows.
Pick the first nonempty member that fits the default buffer and assert
that it fits the opened stream before waiting.
* refactor(cli): run one-shot commands through one shared owner
scripts/rea.mjs and the test CLI session worker each implemented the
one-shot command sequence: argument normalization, output admission,
configuration errors, version documents, the Amp scope refusal, and
result delivery. The worker copy had drifted: it never rendered
formatted version reports or the Amp refusal.
Move the sequence into src/cliOneShot.ts. Both callers supply a host
for their streams, exit and resource ownership. The launcher keeps
closed-pipe status, worker shutdown and process exit; the session
worker captures output per command.
The cliOutput bundle entry is superseded and removed. The dispatcher
test now replaces only the command runtime, so output admission runs
production code. A new parity test compares the file session with a
fresh process.
* test(cli): bundle the one-shot entry in the runtime bundle fixture
The test bounded each hdiutil and CLI step with its own 10-30 s process
deadline. On hosted macOS runners the test takes 32-45 s (about three
times a local run), and the busy-image CLI call, which verifies the whole
image before its attach is refused, exceeded 30 s and was killed in two
recent main runs. Remove those per-step deadlines; the project deadline
still bounds a hang.
* test(mcp): open stdio clients through the shared local-tools fixture
Twelve files built their own StdioClientTransport and Client for
`rea mcp`. Those clients never listed tools, so the SDK did not
validate structured results against advertised output schemas, and each
file repeated transport setup, stderr draining and close ordering.
Use connectLocalToolsMcp, which lists tools, validates replies,
silences logging, leaves deep providers unconfigured and owns cleanup.
Per-test clients register test-scoped cleanup; module-level clients
collect cleanup for afterAll.
* test(mcp): keep failed file-scoped MCP cleanup owned
The three module-level clients removed every cleanup callback before
running them, so a failed cleanup lost its only handle. Add
fileLocalToolsMcp, which connects before the file's tests and removes
each cleanup only after it succeeds, and use it in those files.
After REA stopped a Rizin debug session (frame or output limit, deadline,
cancellation, protocol failure) or the debugger exited, later commands
returned a generic invalid_request and status gave no reason. GDB
collapsed the same states the same way.
Both managers now keep a published session addressable until
close_*_session releases it, record the first reason it stopped, report
it as closed_reason in session status, and refuse later commands with
capability_unavailable naming that reason and the close-then-restart
recovery. An ID the server never returned, or that close released, still
fails as invalid_request with its own recovery. Retained stopped
sessions keep their slot, which the capacity recovery now says. A GDB
command deadline now records its reason like cancellation already did.
Fixes#8024
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rizin exits 0 when its shell refuses a statement, so execute_rizin_command
reported completion_status complete with exit code 0 and an empty stdout
that read as a genuine empty result.
Rizin 0.6 through 0.9.1 log exactly four refusal lines from
librz/core/cmd/cmd.c: an unknown command, a wrong argument count, an
invalid statement (RZ_CMD_STATUS_INVALID, which also stops the remaining
statements) and a parse error. The Rizin command profile now classifies a
completed process's stderr against those lines; the shared one-shot
service reports completion_status "rejected" and a limitation that names
the refusal and says stdout holds only earlier statements' output. Other
ERROR lines come from commands that ran and stay diagnostics.
Fixes#10364
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`cliIntegerArgument` piped a regex-guarded string into a number but never
published Zod's input view, so `--schema` advertised a bare integer for 15
fields while the parser accepted only decimal argv text. `environment-serve
--port` had the same gap through the transforming MCP_PORT owner.
Remove `cliIntegerArgument` and route every call site through
`cliDecimalField`, binding each field to its domain or contract owner where
one exists so bounds, defaults and optionality come from that owner. Export
the input-view publisher as `publishArgvInput` and apply it to `--port`,
which keeps the MCP_PORT grammar shared with `rea mcp --http`.
The decimal catalog test now requires every numeric field's advertisement
to admit its decimal argv token, covers repeated options and
string-advertised token grammars, and checks `--schema` output directly.
The string branch's missing numeric range (#9348) is unchanged.
Fixes#9344
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Probes in a source and a built project read each collected test's
deadline, including test, suite, and module long-running tags, so a
change in project inheritance or tag resolution fails directly. Both
the policy and the probes read one set of base deadlines.
Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Explicit deadlines at or below the project deadline only shortened it:
a literal 30-second value also disabled the coverage scaling, which timed
out wide-capacity regressions on main. Workloads above the built
deadline use the long-running tag. Deadlines derived from an operation
budget remain.
Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Source projects allow 30 seconds and built projects 120 seconds, both
doubled under coverage, and hooks share their project's deadline instead
of Vitest's 10-second default. A long-running tag covers bounded
workloads that need more.
Co-Authored-By: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(javascript): give the wide fingerprint regression a capacity deadline
Each case runs about 22 s of CPU-bound projection on a typical hosted
runner. Its explicit 30 s deadline failed on slower runners at both two
and four Vitest workers, and it also overrode the suite's 60 s
coverage-mode allowance.
* test(ci): double test deadlines on hosted runners
Hosted CI jobs run four Vitest workers on a four-core runner. CPU-bound
capacity cases then share every core with other workers and their
subprocesses; three such cases exceeded the 30 s deadline at four
workers (16.8-22.7 s at two). The deadline only needs to bound a hang,
so hosted CI doubles it: 60 s, or 120 s with coverage. Local runs keep
30 s and 60 s.
* test(ci): check worker and deadline policy for local and hosted runners
The policy test loaded vitest.config.ts in a child that inherited the
parent's GITHUB_ACTIONS, so on CI it observed the hosted deadlines and
failed. Select the runner explicitly and check both: two workers and the
base deadline locally, four workers and twice the deadline on hosted CI.
* test(ci): retire loader-ownership history seeding
Both timing tiers now publish javascriptLiteralLoaderOwnership.test.ts's
own duration (fast 23.7s, full 26.6s), so the seeding returned its input
unchanged. Remove it and its tests.
* docs(ci): describe shard weighting without retired loader seeding
The advertised-pattern guard only inspected the default profile and only
rejected the `\0` and `\u0000` NUL spellings, so a `\uD800` range shipped
in 6.9.0 unnoticed. Reject any unescaped `\u` or `\0` escape, and run that
check for each input and output schema profile.
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rea-agents 6.9.0 advertised `^[^\uD800-\uDFFF]*$` on every local path
input. RE2 has no `\u` escape and Rust's `regex`/`jsonschema` crates refuse
non-scalar code points, so strict MCP clients and gateways (DeepSeek, RE2
gateways, Open Design) rejected the complete tools request and no REA tool
could run.
Move the rule into one runtime check, `rejectUnpairedSurrogates`, which
advertises nothing and still raises the `invalid_format` regex issue, so
CLI and MCP corrections keep reason, expected value, and message. The
objdump disassembly symbol already enforced the same rule with its own
refinement; it now shares the owner and the correction shape.
Dropping the pattern also brings inspect_android_jni_bindings within the
compact profile's per-schema budget, so compact delivery now keeps its
DEX dimension pattern. The descriptor admission test follows the actual
presentation instead of assuming compact always omits it.
Fixes#10238Fixes#10348Fixes#10198
Co-Authored-By: gensokyo-dev <gensokyo-dev@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(desktop): preserve own state keys in task witnesses
* test(desktop): preserve witness parse failure details
* fix(desktop): retain own column keys in task conditions