* feat(javascript): make the member-mutation work allowance a runtime setting
The member-mutation alias-state allowance from #11144 was a fixed constant, so a refused source could not be admitted without a code change.
Register javascript.member_mutation_alias_states (default 524288, 1 to 8388608 alias states) with the launch seed REA_JAVASCRIPT_MEMBER_MUTATION_ALIAS_STATES. The application, web bundle and reference-source boundaries resolve it from the accepted operation snapshot and launch environment, refuse a malformed seed before analysis, and send it to the workers with each source. A refusal names the setting, its effective value, source and range, and the recovery; worker parents rebuild it from the allowance they sent.
Refs #8294
* fix(javascript): keep the setting and recovery of a refused web script
A web bundle script refused by the member-mutation allowance kept only its reason and reported limits, so the public unknown lost the setting, value, source and recovery. Carry the refusal's structured limit and remediation on the per-script result and its javascript_analysis unknown, grouping scripts only when that recovery agrees. Assert structured limit facts and the owning formatter's recovery instead of fixed wording.
* fix(browser): keep only registered setting limits on a refused web script
* feat(javascript): keep syntax facts for a source whose member-mutation phase is refused (#11187)
* feat(javascript): keep syntax facts for a source whose member-mutation phase is refused
A source refused by the member-mutation work allowance during static analysis lost every fact, so the application graph counted it as skipped. Reference-source import failed outright on such a file.
Checkpoint the parser, comment and text facts the static owner can still state, with parse status partial, examination not-examined and refused_phase member-mutations, before reporting the refusal; the semantic phase is not started because it indexes the same mutations. Reference-source import keeps the file's declaration-level imports and records that its CommonJS require calls were not examined.
Refs #8294
* test(javascript): compare the reference-source refusal with its owning formatter
* feat(javascript): keep a refused web script's parse and text facts
A captured script whose member-mutation phase was refused lost every fact in analyze_web_bundle, so it was neither counted as parsed nor kept its vendor markers.
The analyzer now returns the script as unavailable with partial facts: refused phase, parse status and the inferences read from script text alone. Findings gathered before the refusal are dropped, because they may have read an incomplete mutation index. The worker parent states the refusal and its setting recovery from the allowance it sent, through the same helper the isolated analyzer uses for every unavailable script. The bundle counts the script as parsed, keeps its text inferences, and its javascript_analysis unknown carries refused_phase.
Refs #8294
* chore(mcp): record the member-mutation setting in the advertised summary
* fix(javascript): rebuild a parked source worker when the member-mutation allowance changes
A worker parked on a resource scope was reused when heap, timeout and precision matched, but its requests carry the allowance it was built with. After update_analysis_settings accepted a new allowance, the next analysis on that scope kept the old one.
The reuse check now compares the allowance's value and source, so a changed setting gets a worker built with it. The web bundle worker already takes the allowance per script.
* fix(javascript): refuse member-mutation work beyond a fixed allowance
Member-mutation indexing retained every scheduled alias state until its query finished, with no bound on the phase. Conditional self-selections before one member write (#8294) multiplied those states until the worker heap was exhausted.
Charge each scheduled alias state to a per-phase work meter. Past 524,288 states the phase is refused with a resource_constraint that names the fixed work allowance. The application and web bundle workers carry the reported limit to the parent, which rebuilds the refusal with that allowance instead of heap advice.
Refs #8294#6127#6344#7170#7510#8298
* test(javascript): prove the member-mutation meter spans the phase
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>
* perf(javascript): reuse the source-analysis worker within a process
Each analyze-javascript-application call started a new Node worker.
That startup, not fixture IO or the shared CLI session, dominated the
slow loader-review and factory-completion files.
Park one healthy worker on the artifact resource scope and on the CLI
process. Stop it when the scope, session, or one-shot process ends.
Do not reuse after failure, cancellation, or a different heap or timeout.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(cli): close the JavaScript worker when dispatch throws
Minimal dispatcher runtimes now export a no-op closeCliJavaScriptResources,
and CLI dispatch plus output rendering always await that cleanup. A dispatch
failure and a cleanup failure are both reported.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(artifacts): report close-hook failures with retained cleanup
When retained cleanup and the scope close hook both fail, the close error
keeps both causes and both resource labels. The pending owners and the hook
stay registered so the next close retries each path.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(javascript): stop a replaced analysis worker before the next one starts
A heap or timeout change now closes the parked worker before constructing
its replacement. The scope retains that process only when the close fails.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* style: format worker-reuse close and launch helpers
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(cli): report a failed JavaScript worker shutdown before exit
Share one in-flight close and drop the CLI scope only after it succeeds,
so a later caller retries a worker that is still owned. The one-shot
exit callback writes that failure and exits non-zero, while a closed
stdout pipe still exits 141.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(javascript): keep a worker parked during an overlapping limit change
Claim the scope slot only when it is still empty after the replaced
worker closes. A concurrent analysis that parked another healthy worker
keeps that process, and the extra worker is closed through its own port.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(artifacts): run later close hooks when an earlier hook fails
Run every registered close hook on each close. One failure is returned
unchanged, and several failures are aggregated so a later hook is not
skipped.
Co-authored-by: morluto <morluto@users.noreply.github.com>
* fix(javascript): fail a limit change when the previous worker stays alive
A failed close used to be retained and then ignored, so MCP could return
a successful analysis while the old process and its replacement were
both owned. The request now fails before the replacement is constructed,
and the still-live worker stays owned for a later close.
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>
Separate child and private-root ownership from JavaScript analysis protocols. Retain exact cleanup lifetimes across retries, late handshakes and runtime reuse; observe request-stream errors and preserve per-job file cleanup during worker reuse.
Admit unknowns before canonical construction and provenance interning. Offer independent per-file and application capacities through CLI, Evidence and the owned analysis worker, and reject over-allocation during streamed decoding.
Report examined omitted emission occurrences by family and reason without retaining discarded identities. Preserve omission-free graph identities and distinguish node truncation from overall partial coverage.
Fixes#4797
Serialize the typed resource reason once and let the application own path formatting, retaining partial static observations and reported limits.
Reviewed-PR: #3039
Co-authored-by: balkan16 <57933796+balkan16@users.noreply.github.com>
* fix(bun): report the real runtime and enforce worker memory budgets on Windows
Under Bun, REA recorded Node/V8 identity it did not observe and its JavaScript helper processes ran without a memory bound, because Bun ignores the V8 heap flags REA passes. Source-map trace Evidence claimed runtime node-v8 with Bun's synthetic V8 heap limit (the decoder then rejected that limit, so trace_web_source_location always failed), analysis resource failures reported heap limits Bun does not enforce, the HAR decoder claimed a fixed 192 MiB heap, and doctor reported Bun's Node.js compatibility version as the Node version.
Identify the runtime once from process.versions. Source-map reports record id bun with the Bun and Node.js compatibility versions and a null v8_heap_limit_bytes; the decoder checks the heap budget only for V8 reports and rejects a report from a runtime other than the launching one. The analysis worker reports a null heap limit under Bun, HAR limitations and failures omit heap sizes under Bun, and the doctor node check reports Bun and passes when its Node.js compatibility version is supported.
On Windows under Bun, each helper's owned Job Object now carries a commit limit of its heap budget plus a measured 512 MiB Bun runtime reserve (704 MiB for the codec and HAR decoder, 1536 MiB for the default analyzer). The native addon accepts an optional page-aligned job memory limit on process_spawn, verifies it by readback, associates a private completion port before the child is created, and reports a sticky memoryLimitReached and peak job commit on each poll; inspect reports jobMemoryLimit. A requested limit with an artifact lacking the control refuses the launch, and non-Windows launchers refuse a limit.
Reaching the limit is classified by the job notification rather than Bun's exit status: the analyzer fails the current source with a memory resource failure reporting worker_process_memory_limit_bytes, the codec returns a memory resource failure, and the HAR decoder returns its memory failure with process_memory_limit_bytes. Bun source-map Evidence records process_memory_limit_bytes, verified against the launcher. Node.js launches and outputs are unchanged.
* fix(windows): drain memory notifications after observing exit
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
* feat(ghidra): configurable import language and analysis seeds
REA_GHIDRA_LANGUAGE_ID and REA_GHIDRA_COMPILER_SPEC_ID set the import
language when the header cannot identify the compiler (for example,
Borland C++ PE images).
REA_GHIDRA_SEED_FILE seeds functions, code and labels before
auto-analysis, for code reached only through computed jumps or data.
Both are validated before launch, recorded in the analysis profile and
verified in the bridge handshake.
* fix(ghidra): parse language XML and preserve seed ordering
* test(ghidra): use explicit platform paths for seed launch checks
* fix(javascript): retain cleanup failure reason in error causes
---------
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>