Classify selected-input read failures at the shared artifact boundary and remove duplicate phase-based translations from TShark and sigrok. Keep other read stages raw for their existing owners and retain cleanup resources until retry succeeds.
Extend the descriptor outcome matrix with post-run private-copy integrity failures, late cancellation, retained command output, failed cleanup, and successful retry.
Project admitted output facts beside the command owner and remove adapter-local copies. Preserve byte-count omission, explicit signal and exit facts, and caller-specific truncation and failure policies.
Update ADB timeout regressions to assert the existing prerequisite frame and original process cause, including captured output on both frames.
Stop interactions and sampling before final observation, and stop the owned
target before failure-path rendering. Cache finalized terminal facts through
disposal and cleanup retry while preserving the original failure.
Version deferred terminal observation order for every normalization profile,
including disabled PID and port normalization. Add public CLI/MCP descendant,
partial-evidence and compatibility controls without replacing upstream owners.
Fixes#6443
* fix(ghidra): report kernel OOM kills as a memory constraint
A kernel or container OOM killer ends Ghidra with SIGKILL and prints no
java.lang.OutOfMemoryError, so the failure fell through to the generic
execution_failure that points at `rea doctor`.
On Linux with cgroup v2, read the process's own memory.events oom_kill
count before launch and again after a SIGKILL. When it rose, project
resource_constraint (memory) with the group's memory.max, and advise on
the whole process tree (native decompiler processes included) instead of
a larger Java heap. Otherwise name the signal as a possible OOM kill.
Fixes#5859
* fix(ghidra): scope OOM-kill attribution to what the cgroup proves
Review follow-up for the SIGKILL projection:
- The process supervisor records stop_requested before it sends any
signal, and Ghidra diagnostics carry it, so a SIGKILL from REA's own
stop is never reported as an outside kill. Only process and protocol
failures qualify; launcher (start) failures can include REA's rollback.
- Word the memory constraint as an OOM kill in REA's cgroup or a child
group; the count is per cgroup, not per process tree.
- Keep the open_binary reopen guidance for an established session.
- Resolve the cgroup directory through the cgroup2 mount in
/proc/self/mountinfo, so subtree mounts are joined from their root,
and read kernel files to EOF within a budget.
- Report memory_max as "max" for an unlimited group and null only when
the limit could not be read.
Keep typed search denial and acquired snapshot facts through cleanup and finalization. Record unfollowed symlink coverage at the snapshot owner, preserve physically enumerated parents, and retain uncertainty beneath omitted links without losing proven sibling deletions.
Update parsed omission contracts, public CLI/MCP regressions and documentation without introducing a new lifecycle or coverage framework.
Fixes#6446Fixes#6444
* feat(decompile): write function pseudocode to a directory and return a manifest
Add decompile_all and `rea decompile-all` so a caller can write one
provider pseudocode file per function, or a filtered set, and receive
only a small manifest. The result stays bounded when the program is
larger than a local model's tool-result cap.
Resume continues an export for the same target digest, provider,
analysis profile, and layout. Matching files are skipped, conflicting
files stay unchanged, and one function's failure does not stop the
rest. Cancellation leaves files already written. Requesting dwarf
layout reports that compilation-unit paths are unavailable.
Simulated-provider tests cover the manifest, resume, filters, limits,
cancellation, and the failure cap. MCP registration, CLI coverage,
schema validity, the product catalog, check:fast, and docs:check
passed. Real Ghidra was not exercised.
Refs #6090
* fix(decompile): keep unknown export identity unresumable and recover torn journals
Resume treated two missing target or profile digests as a match, so an
export of one binary could continue into another. Resume now requires both
digests, and a decompiler observation without the export's profile, or with
a different target, is recorded as profile_changed.
A crash during a journal append left a torn final line that made the export
unresumable. Text after the last newline is now treated as uncommitted and
truncated before the next append, and stale temporary files are removed.
An inventory row with an empty address aborted the whole export because its
failure record failed the journal schema. Such rows are now excluded and
counted in the limitations.
A limited resume retried the same recorded failures first and never reached
new functions. Functions not yet attempted now run before retries. File path
reservations come from every journal line, so an output_io record no longer
releases a path. The index is rebuilt from the journal in numeric address
order, and journal close and cleanup failures return a Result.
The cancellation test now cancels after a file is committed and checks that
file survives and is skipped on resume. Redundant snapshot-replay checks are
removed, the CLI limit uses the contract constant, and --snapshot no longer
claims decompile-all updates it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): refuse resume of a missing export and repair journals by byte offset
A second review round found that resume against a directory that does not
exist silently started a full new export and reported it as resumed. Resume
now requires an existing export directory.
The torn-line repair measured the committed journal from decoded text, so
damaged UTF-8 could move the truncation point past the end of the file. The
journal is now read as bytes and cut at the last newline byte, and an intact
journal is not truncated, so a concurrent append is kept.
A per-function observation for a different target is now recorded as
target_changed instead of profile_changed. A failure to remove a partly
created output directory is reported instead of hidden. The journal handle is
closed on every path again, including an unexpected throw. The path allocator
no longer gives up after 1,000 collisions and reuses a taken name.
Tests now use createTestTempDirectory, assert journal lines against the
journal schema, and cover resume of a missing directory, resume with an
unknown analysis profile, and a target-mismatched observation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): keep a function's first file name across failed retries
Reserving every journal path stopped other addresses from taking a path, but
an address looked up only its latest record. After its file went missing and
a retry failed without a path, the next resume moved the function to a
hash-suffixed name and orphaned the original. Each address now keeps the
first path the journal gave it.
A matched commit still ran the decompiler but did not count toward limit.
The limit now counts every function taken on after skipping verified files.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): never follow a journal symlink and check procedure_info identity
Torn-line repair truncates the journal, and the journal was opened through
any symlink in the export directory, so repair could truncate a file outside
it. The journal must now be a regular file and is opened without following
symlinks where the platform supports it.
Body ranges from procedure_info were written without checking that the
observation belonged to this export or described the requested function. An
observation with a different provider, profile or target, or another entry
point, now leaves the body unavailable with that reason.
File, journal and index writes now use FileHandle.writeFile, which writes the
whole buffer instead of trusting one write call. The stale temporary sweep is
removed: a matching file name does not prove this export created the file.
The inverted-range test now uses one address space so it reaches the
inversion check.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): bound returned caveats and keep verified checksums
Ghidra names each terminal call's address in its per-function caveats,
so decompile_all copied one new caveat per function into the returned
Evidence and the answer grew with the program. The returned Evidence
now keeps the eight most often observed distinct per-function caveats,
grouped by provider and text as they are rendered, plus a count of the
rest. Inventory caveats are unchanged, and other workflows are not
bounded. Each function keeps the caveats of the observations it used:
a written file in its header, now including procedure_info caveats,
and a failed attempt in its journal and index record. A procedure_info
observation for another target or profile is foreign and contributes
none.
A failure record for a function that was already written replaced the
record holding its checksum, so after a transient read error a resume
decompiled that function again. The journal now keeps the last
successful write separately from the latest attempt. Resume verifies
against that write and records it again once the file verifies.
A caller abort that arrives while the export finishes now returns
cancellation with the caller's reason instead of a success manifest,
as #6143 does for other late finalization. A publish, index or close
failure stays the primary error.
Also make the missing-journal resume error say what to do, and add
boundary tests: one runs decompile-all through the real CLI against a
fake Kuna to check flag mapping, the relative output directory,
filters and limit; one runs decompile_all through production MCP
registration to check that the caveat bound is applied.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): keep each function's complete caveats in the index
The returned Evidence keeps eight distinct per-function caveats and
counts the rest, pointing readers at the export. A written function's
file header truncates its caveats after 4,000 characters, and its
journal record kept none, so a large function with many terminal calls
could lose caveats from both the answer and the export.
Every journal record, written or failed, now keeps the complete caveats
of the observations its attempt used, and decompile-index.json carries
them. The header stays a readable summary and, when truncated, says
that the index keeps the complete list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): report external functions instead of failing them
Ghidra classifies imports as external functions with an empty body and
returns null pseudocode for them, as its limitations state. decompile_all
recorded each one as an invalid_pseudocode failure ("not text"), so a
dynamically linked program reported every import as a decompiler failure:
34 of 116 functions in /usr/bin/xxd.
procedure_info owns the external classification. When it classifies a
function as external, the export now records status "external", counts it
in counts.external, writes no file and requests no pseudocode. The record
keeps the body fact as observed. The journal header pins the target,
provider and profile, so a resume skips a recorded external function
without asking the provider again; a limit below the external count still
leaves nothing remaining. A null pseudocode result for a function whose
classification is not external is reported as no_pseudocode.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): report finalization failures after a cancelled export
When the caller's abort stopped the publish loop, decompile_all returned
that cancellation before checking the index write and the journal close,
which had already run. A failure to finalize the export was hidden, so
the caller could not tell the saved index or journal was incomplete.
Publish failures stay primary, then index and close failures. A
cancellation counts as the caller's only when the caller's signal is
aborted, and is then reported after a successful finalization with the
caller's own reason. A provider's own cancellation, without a caller
abort, stays a publish failure like any other. Tests cover an index
failure and a close failure after the caller stops the loop, a stopped
loop with a successful finalization keeping the caller's reason, and a
provider cancellation staying primary over an index failure.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): remove a created output directory that cannot be secured
createPrivateDirectory ran mkdir and chmod as one step. When mkdir
succeeded and chmod failed, it returned an error before #create reached
its cleanup, leaving an empty directory behind. A fresh export then
refused the existing directory, and a resume refused it for having no
journal, so the caller had to remove it by hand.
mkdir and chmod are now separate. A mkdir failure created nothing, so
nothing is removed. A chmod failure after this call created the
directory removes it with a non-recursive rmdir: it is still empty, so a
path another process filled or replaced meanwhile is refused rather than
deleted, and that refusal is reported.
A filesystem boundary test fails chmod for the new root and checks the
directory is gone and a retry succeeds. A module test confirms that a
function written earlier and now classified as external still reports a
changed file at its path as output_exists.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* refactor(process): share the socket lease with owners other than Hopper
The socket lease that keeps two REA processes from opening the same Hopper
document lived only in HopperLease, with Hopper error messages built in.
A decompile export needs the same guarantee for its output directory.
OwnedLease now holds the lease mechanism unchanged: a listening local
socket that the operating system ends with its process, owner identity
answered by the live holder, and recovery of a stale socket serialized
through a recovery directory. Callers map a tagged LeaseFailure to their
own error. HopperLease keeps its exports and maps each failure to the
same HopperStartError message as before. On Windows the lease is a named
pipe, which needs no stale recovery.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* fix(decompile): hold the output directory per run and stop on repeated write failures
Two runs could resume the same output directory at once. Each read the
journal once, and the index each wrote reflected only its own view, so
the last writer could drop the other run's records. A run's torn-line
repair could also truncate the other run's append.
DecompileExport now holds a lease on the output directory, named by its
device and inode, from before the journal is read (or, for a new export,
from just after the directory is created and before its journal exists)
until the journal is closed. A second run is refused as a retryable
capacity constraint that reports the holder's process ID. The lease ends
with its process, so a crashed run leaves no lock to clear. The lease is
released on every open failure, and a failed release is reported.
An export also kept decompiling every remaining function when its files
had stopped being writable mid-run, for example on a full disk, failing
each one with output_io. After five consecutive functions whose files
could not be written or read, the export now stops with an output error
that carries the counts and the last failures. A verified file or any
other outcome ends a run of failures. Committed files and records stay,
the index is still written, and a later resume continues.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AoJZDPcrgmMsCqLG4LfiFb
* docs(native): record directory export verification
Record matched real Ghidra outputs, bounded caveat and cleanup regressions,
actual catalog-inclusive context estimates, runtime measurements and coverage
limits for the pinned integration.
* fix(native): bound export summaries and reserve portable paths
Use one case-folded reservation owner for allocation and resumed journals.
Budget inline failures and provider caveats by encoded JSON bytes while
retaining complete records in the output index. Align the tool contract
with the collector order and verify SDK result-window behavior.
* docs(native): refresh final export measurements
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Share incremental replacement UTF-8 decoding across web and JavaScript workers, bound content before complete-line allocation and handle split CRLF consistently. Keep named schemas, request versus checkpoint failures, worker reuse and stream cleanup authority in their servers. Cover real server recovery and deterministic byte boundaries.
Centralize run-token extraction at the environment observation boundary and require an own field. Build decoded OS environment records without host prototypes while retaining source names, empty values and last-assignment precedence.
Reject inherited matching tokens before cleanup signaling, preserve normal owned-group behavior, and verify live Linux process environments alongside native CLI/MCP capture workflows.
Keep aliases on selected paths at clear text delimiters so a longer sibling filename is not rewritten as the executable. Version the normalization contract and cover source and actual PTY behavior.
Fixes#6586
capture-process recorded exit.code 0 for a target a scenario event killed
with SIGKILL or SIGTERM, beside the nonzero exit.signal. The result builder
and the retained observation each kept any nonnegative PTY exit code for an
exited capture without consulting the signal; only finalization checked it.
Project the exit once in captureExitObservation, whose normal exit code is
null when a nonzero signal ended the target, and use the same rule for
finalization. Normal exits keep their codes, including 0 and 3, and deadline
exits remain null.
Fixes#6445
* test: prefer structured assertions over recovery prose
Lock regex, IDA, Hopper/Kuna, MCP budget, capture-heap, and pcap
failures on error codes and reported limits instead of full recovery
sentences.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: keep decoder heap negatives off the Windows reserve
"512 MiB" also appears in the Bun Windows reserve sentence. The
negative check stays on "512 MiB (source setting)", which is the other
adapter's heap.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: keep the one-retry cap and deadline recovery tokens
The lost-connection guidance must say once only, so an unlimited
"whenever it is safe" rewrite fails. Deadline recovery still has to
name set, restart, the floor, and the maximum constant.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: keep heap, MCP, pcap, and preload recovery tokens
Codex still wanted the set/restart/floor/maximum heap guidance, MCP
default/floor/maximum bounds, Wireshark install guidance, and the
dropped-preload attribution limit as separate tokens.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: keep shared-context and transport recovery tokens
Shared-context capture must still exclude requests without a known root
or descendant frame. Shutdown must end the REA process before starting
again, and a failed HTTP listen must offer another port or stopping the
process that holds it.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: keep handoff, input-check, and budget format tokens
Skill and server guidance must still tell the user to restart the MCP
client. Process failures must still say to check the input files. Invalid
MCP phase budgets must still say positive decimal integer and ms.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: bind budget floors and active deadline sources
The phase-budget minimum is the start of "from N to M ms", so a digit
inside the maximum no longer satisfies it. Capability text must contain
the active "N ms (source ...)" pair, not the default number and a heap
source mentioned apart.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: bind heap MiB sources and pcap host tokens
A configured 256 MiB request must appear as "256 MiB (source setting)",
so a byte-sized 256 no longer passes. Unsupported pcap hosts must still
name Linux, util-linux, Windows, and owned Job Objects as separate tokens.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: bind the selected decoder heap to MiB and source
The two-adapter limitation must contain "256 MiB (source setting)".
The exhaustion message binds that capacity as "256 MiB V8 old-generation
heap (source setting)", so a byte-sized 256 no longer passes.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: bind doctor client seconds and prlimit absolute guidance
Doctor recovery must name startup_timeout_sec of the policy's seconds,
so a hardcoded 60 no longer passes while the policy stays 30. A relative
prlimit must say the value must be absolute and tell the user to check
REA_TSHARK_PRLIMIT_COMMAND.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test: assert integrity codes for rehashed evidence and coverage
Independently rehashed process Evidence and a tampered digest project
evidence_integrity_mismatch. An unsupported comparison operation stays
invalid_request. Unsupported inventory coverage status is an integrity
failure whose reason carries the coverage.status schema issue.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
* refactor(process): share paired prlimit ceiling ownership
Route firmware, Wakaru, and pcap paired ceilings through
LinuxResourceLimits without changing their byte or CPU budgets.
Keep EVMole's soft-only limits as a dated architecture-guard exception.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(pcap): admit capture limits without host prlimit
The ceiling test only checks the shared argument prefix, so it uses a
temporary executable instead of /usr/bin/prlimit.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* style(pcap): format the capture ceiling test
oxfmt rejected the object literal wrapping in PcapNativeBound.test.ts.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(windows): report missing native launch controls as unavailable capabilities
An admitted Windows native artifact may predate the optional protocol stdin
or Job Object memory limit controls. WindowsOwnedProcess correctly refused
such launches, but threw a plain Error, so providers projected the refusal
as execution_failure with generic `rea doctor` advice and left the package
remedy in nested diagnostics.
Introduce RuntimeControlUnavailableError as the shared owner of expected
host-control refusals. PrivateRuntimeRootUnavailableError and the new
WindowsNativeControlUnavailableError (which records the missing control)
extend it, and the six provider adapters that hand-built the same
AnalysisCapabilityUnavailableError now project any subtype through one
helper. The refusal still precedes every native launch.
Fixes#6050
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* refactor(errors): drop capability imports superseded by the shared helper
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(process): make the regex worker heap request configurable
REA_REGEX_WORKER_HEAP_REQUEST_MIB keeps the 128 MiB default and refuses
values outside 8 to 16384 MiB. A positive Node --max-old-space-size still
overrides the request and is not clamped by the setting.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): set the regex worker heap floor to the measured startup bound
On Node 22.23.4 a 5 MiB old-generation request aborts the regex worker
during startup, and 6 MiB starts it and returns a match. The setting floor
is that measured bound.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): raise the regex worker heap floor to 7 MiB
6 MiB passes configuration but returns ERR_WORKER_OUT_OF_MEMORY for a
trivial match on supported Linux Node 24 and Node 26.0.0. 7 MiB returned
that match on the measured 22, 24, and 26 lines. A clean-process test
runs the production worker at the floor.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
* feat(config): make the regex matching deadline configurable
REA_REGEX_MATCHING_DEADLINE_MS defaults to 5000 ms and refuses values
outside 1..2147483647. Recovery and capability text name the effective
deadline, its source, and how to change the setting.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(setup): preserve the regex matching deadline in registrations
Setup validated REA_REGEX_MATCHING_DEADLINE_MS but left it out of the
selected registration environment, so a caller override never reached
the launched server and matching fell back to 5000 ms.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* test(config): restore a stubbed regex matching deadline on failure
Kuna deadline assertions now unstub the environment in finally, so a
thrown construction or expectation cannot leave the setting stubbed.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Final filesystem observation reconstructed root admission from the initial
snapshot's root entries, so an initially absent root (no entry) whose ancestor
became a regular file failed capture with ENOTDIR after the child completed.
A returned initial snapshot now admits every selected root for the run. One
tagged path lookup classifies ENOENT and ENOTDIR as observed absence and other
unavailable lookups (EACCES, ELOOP, ...) as entry_unavailable omissions that
keep the root incomplete. Selected roots that are obstructed or denied before
launch still fail capture.
Fixes#6213
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Electron and process scenario path admission caught every realpath or
stat failure as an invalid_value input issue, so a correct path beneath a
directory without search permission returned invalid_request with
schema-correction recovery instead of a host access denial.
Admission now classifies EACCES/EPERM from path resolution and metadata
reads as the existing AnalysisAccessDeniedError (selected path,
system_code, filesystem-read boundary). Missing, looping or otherwise
unresolvable paths and reachable files without execute permission keep
their input-error semantics. Electron reports invalid selections before a
denial on another field. Process PATH search still continues past a
denied directory; only an explicitly selected executable reports denial.
Fixes#6117
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Construct integer formats directly while preserving bounds, refinements, metadata and current shared schema owners. Keep Incur-dependent CLI numeric coercion declarations unchanged.
Verify canonical advertisements, 126 numeric boundary cases, 974 actual CLI parser cases, broad source tests and real public-artifact SDK workflows. Record 72 normal tasks and 12 separate owned-inspector heap diagnostics with whole-family resource bounds; distinguish SDK spans and asymmetric audit overhead. Generate numerical report sections from receipts and reject stale tables through documentation conformance checks.
Closes#6236. Current-head CI and Greptile pass; actionable review findings are addressed. Codex review was unavailable due repository usage limits.
* fix(pcap): report workspace allocation failures by their system cause
Pcap workspace allocation and snapshot writes mapped every filesystem
error, including ENOTDIR and EACCES from mkdtemp, to a file-size resource
constraint with null limits and worker file-size advice. Flutter's owned
snapshot storage had the same errno-blind mapping, while TShark and sigrok
carried duplicate copies of the correct split.
Move the private-workspace failure projection into one shared owner:
ENOSPC/EDQUOT/EFBIG stay file-size resource constraints with their system
code and path; descriptor exhaustion and every other failure become
provider workspace failures carrying stage, workspace path, failing path,
system code and cause-specific recovery.
Fixes#6123
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(flutter): locate owned storage failures by their workspace
mapOwnedIoFailure always passed a null workspace path, so a descriptor
write or read failure without its own errno path lost every location.
Thread the owned root through: allocation keeps null (no workspace yet),
snapshot failures use the allocated root, and package-reader system
errors propagate to the request owner, which maps them against the
snapshot root instead of mapping early without it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(process): record withheld unrelated Linux processes as unverified
The token sweep after an owned command (for example the Ghidra Java probe
run by setup and doctor) failed cleanup when an unrelated same-UID process
started during the sweep and Linux denied its /proc/<pid>/environ. Setgid or
setuid programs (mismatched real/saved IDs) and non-dumpable processes are
withheld by the kernel exactly like another account's processes, which were
already recorded as unverified.
Derive the kernel restriction from the same stat-bracketed procfs read that
already supplies the effective UID: all Uid/Gid IDs from status, and the
root ownership procfs reports for a non-dumpable process's environ. Keep that
fact through exit settlement. Related candidates still fail closed.
Fixes#6204
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(process): define caller credentials on hosts without geteuid
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(process): settle owned cleanup with the launcher's own exit proof
When owned process-group verification fails while the supervised
launcher is still mid-exit, the supervisor now waits up to the kill grace
for its own child-exit observation and verifies once more after it
arrives. Verification is not repeated when the exit was already observed
before cleanup started, so there is no new evidence and the original
failure is kept. Nothing is signaled based on the wait.
Fixes#6134
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(process): bound Hopper session cleanup attempts by exit evidence
The fake Hopper launcher exits after its shutdown acknowledgement. When
the supervisor first observes that exit during a failed verification, it
verifies once more, so the first close makes one or two attempts depending
on timing. The test now asserts that bound. Later session retries, made
after the exit was already observed, make exactly one attempt each.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Fixes#5148.
Add opt-in durable managed member summaries and authenticated paging while preserving complete default output, original Evidence, cleanup ownership and queued cancellation.
Verified with bounded real Newtonsoft/Redux/Rust tasks, independent oracles, 556 focused tests and the expanded domain gate; paired token estimates and latency tradeoffs are recorded in experiments/analysis-efficiency/managed-cli.md.
* fix(process): report the effective regex worker heap
Node gives --max-old-space-size, including NODE_OPTIONS, precedence over
the worker's 128 MiB resourceLimits request. Name that effective
old-generation heap and stop saying the request has no runtime override.
The matching deadline stays a fixed cap.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): keep SIGXCPU and SIGXFSZ retries uncertain
The signal does not prove the retained rlimit was exhausted, so an
unchanged retry may succeed. Project that retry as possible instead of
saying it fails the same way.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): leave percentage heap overrides unestablished
--max-old-space-size-percentage takes precedence over the absolute flag
in either order. Node computes that MiB from startup memory, which a
later read does not recover, so the effective heap stays unknown instead
of the 128 MiB request or an absolute flag.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): read launch NODE_OPTIONS, not process.env
A preload can rewrite process.env.NODE_OPTIONS after V8 has applied the
original flags, and those flags are not copied into execArgv. Use the
initial environment block when it can be read, and leave the effective
heap unestablished when that provenance cannot be recovered.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): leave env-file heap overrides unestablished
--env-file and --env-file-if-exists can supply NODE_OPTIONS when that
variable was absent from the initial environment. The file is not in
/proc/self/environ, so a missing entry is not the 128 MiB request.
An initial NODE_OPTIONS is still parsed, because Node does not let the
file replace it.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): leave --max-heap-size old generation unestablished
A positive --max-heap-size or --max_heap_size sets the total heap, not the
old generation, and can stay below the 128 MiB worker request when an
old-space flag is also present. The effective old generation stays
unestablished while that value is in effect. Zero or empty clears it.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): leave config-file heap options unestablished
--experimental-config-file and --experimental-default-config-file can
apply a heap percentage from a file that is not launch provenance. The
effective old generation stays unestablished when either flag is present,
including beside an absolute --max-old-space-size.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): read launch exec argv from the command line
process.execArgv can be cleared after V8 applies --max-old-space-size.
Linux recovers those tokens from /proc/self/cmdline and leaves the heap
unestablished when that vector cannot be separated from the program entry.
Heap probes compare pinned absolute limits instead of a percentage of host memory.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(process): leave a title-overwritten command line unestablished
process.title and --title replace /proc/self/cmdline with the title.
A buffer without a program entry is not an empty option list, so the
heap stays unknown instead of the 128 MiB request. The command-line
probe does not read /proc off Linux.
Co-authored-by: morluto <morluto@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(cancellation): preserve caller abort reason in cancellation errors
Several application, provider, and MCP boundaries constructed
AnalysisCancelledError, ArtifactReaderFailure, or
DetachedPgpSignatureError for an already-observed or newly-observed abort
without passing the caller's signal.reason as the error cause. The typed
result then reported cancellation with an undefined reason even though the
exact object supplied to AbortController.abort(reason) was still available.
Pass signal.reason as the cause at each producing cancellation site:
JavaScript artifact reconstruction and file abort checks, derived MCP
operation checkpoints, detached PGP verification, ASAR listing admission,
Dart AOT inspection and its provider guard, evidence-file analysis views,
binary layout and recorded crash admission, WASM inspection admission,
and the Kuna shared assembly-index wait.
Cancellation classification and cleanup behavior are unchanged.
Fixesmorluto/rea#5935Fixesmorluto/rea#5944Fixesmorluto/rea#6100Fixesmorluto/rea#6101Fixesmorluto/rea#6110Fixesmorluto/rea#6113Fixesmorluto/rea#6121Fixesmorluto/rea#6131Fixesmorluto/rea#6132
* test(cancellation): assert the exact caller reason identity
Copied reasons satisfied toMatchObject, so the tests would pass even if the
caller's abort reason were replaced by a structurally equal copy. Capture the
rejection and assert the cause is the same object.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35b247e9-c793-4b8f-979a-807c27112cf5
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 35b247e9-c793-4b8f-979a-807c27112cf5
Name REA_SWIFTC_COMPILE_TIMEOUT_MS, its effective milliseconds, the
1..2147483647 range, and the omitted 120000 ms default when a Darwin
ownership-helper compile times out. A change applies after REA restarts,
on the next ownership-helper compile.
Producer SIGXCPU and SIGXFSZ recovery says REA retains the tighter
inherited limit. Agent-visible fixed caps in this theme say this release
has no runtime override. Numbers are unchanged.
Refs #5910
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>