* feat(artifacts): make ASAR header admission configurable
ASAR header/index admission was a fixed 16 MiB with no override, so
operators with large Electron indexes could only extract the archive.
REA_ASAR_MAX_HEADER_BYTES now sets it (default 16777216, maximum
268435456). One owner resolves the effective admission for the
classification probe, inventory, ASAR reader and Electron file scope,
including the Electron header cache budget. Startup and doctor validate
the setting; admission refuses an invalid value instead of falling back.
Recovery and error details name the effective value and its source.
Fixes#6176
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(artifacts): resolve ASAR header admission from the caller's environment
The admission read process.env, so composition roots that select their own
environment (createDirectAnalysis, createServer, CLI, optional observation
factories) could not raise or lower it, and an ambient value leaked into
callers that left it unset.
Nothing reads process.env now. ArtifactProvider and extraction resolve the
admission from their environment; JavaScript analysis parses it from the
environment its server or CLI caller passes and refuses an invalid value;
the Electron and V8 providers receive it from their factories. Inventory,
nested ASAR readers, classification probes and Electron page authorization
carry that one value. A header cached by Electron under a larger admission
is refused for a smaller one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
* 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 <[email protected]>
Copilot-Session: 35b247e9-c793-4b8f-979a-807c27112cf5
---------
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 35b247e9-c793-4b8f-979a-807c27112cf5
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* style: format worker-reuse close and launch helpers
Co-authored-by: morluto <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
* 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 <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
* fix(javascript): preserve selected path host resolution reasons
Classify ELOOP and ENAMETOOLONG while resolving the caller-selected input so the path and host code stay on the invalid-request issue.
Refs #5623
Co-authored-by: morluto <[email protected]>
* fix(javascript): count summary coverage in module units
Use the module population for both examined and total counts. Non-module graph nodes remain in the application coverage section.
Refs #5464
Co-authored-by: morluto <[email protected]>
* fix(javascript): connect direct property reads to return and argument flow
Record the unwrapped value expression and alias the object projection's read occurrence so a direct member read stays in backward provenance.
Refs #5585, #5648
Co-authored-by: morluto <[email protected]>
* fix(javascript): count return wrappers against expression depth
Evaluate the original return expression so erased TypeScript and Flow wrappers stay inside the expression-depth budget. Keep the unwrapped node for identity and value ranges.
Co-authored-by: morluto <[email protected]>
* fix(javascript): describe ELOOP as unresolved symlink traversal
A host can return ELOOP for a cycle or for a chain past its traversal limit. Keep the selected path and code without asserting that a cycle exists.
Co-authored-by: morluto <[email protected]>
* test(javascript): skip symlink traversal fixtures on Windows
Keep the overlong-name case portable. Windows does not produce ELOOP for these fixtures, matching the other path-failure tests.
Co-authored-by: morluto <[email protected]>
* fix(javascript): describe ENAMETOOLONG as a path or component limit
realpath reports that code for a long component and for a long full path. Keep the selected path and host code without claiming only a filename was too long.
Co-authored-by: morluto <[email protected]>
* style(javascript): format return-depth and object-read changes
oxfmt rejected the return-depth test and the object-read index. No behavior change.
Co-authored-by: morluto <[email protected]>
* test(ida): expect unchanged invalid requests to be nonretryable
The shared projector no longer marks invalid_request retryable. This lookup assertion was not updated with that contract.
Co-authored-by: morluto <[email protected]>
---------
Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: morluto <[email protected]>
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
* fix(javascript): mark resource-skipped files parse_status skipped
Files above ~5 MB exhaust the worker heap during static analysis (or exceed
the 8 MB static-checkpoint budget with a larger heap). They were inventoried
with text included but never parsed, leaving parse_status null and no
counter, so the summary read as 'nothing there' instead of 'not analyzed'.
Report them as skipped: parse_status 'skipped' on the file observation and a
skipped_javascript_files statistics counter. The analysis-failure reason keeps
surfacing as a limitation entry.
Fixes#3670
* fix(javascript): default skipped_javascript_files when reading old saved evidence
Saved analysis evidence written before skipped_javascript_files existed failed validation against the strict reconstruction statistics schema, so users could not reuse old results for comparisons or runtime reconciliation. Accept the field's absence on read (defaulting to 0) while continuing to write it for new results.
* fix(javascript): preserve unknown skipped count for legacy evidence
The .default(0) gate fix fabricated a measured zero for saved
pre-change evidence, so comparisons would receive a definitive
"no files skipped" fact the producer never established. Use the
codebase's exactOptional idiom instead: legacy reads accept absence
and keep omission (unknown), while the producer still always writes
the field (required by JavaScriptArtifactReconstructionResult).
Tests: legacy payload now asserts the key stays absent/undefined;
current-output test keeps asserting the producer-written counter.
* fix(javascript): add required failure scope and status to graph fixture
---------
Co-authored-by: Saim Shafique <[email protected]>
Preserve applicable artifact processing phases and entered/unvisited status after interruption. Centralize JavaScript semantic applicability for full and incremental builders; retain native byte identity, actual JavaScript unknowns and structured-file provenance.
Fixes#3948. Part of #4027.
Validation:78 distinct focused cases across10files, full static/docs, and real Joplin timeout/default public CLI/MCP controls passed. Source pins, every attempt/outlier and compact resource/token projections are retained. No target/native provider execution or speedup claim.
Co-authored-by: Kaoru0822 <[email protected]>
Preserve missing ASAR companion occurrence identity, declared size and unknown content in graph nodes and resolution limitations. Apply URL text semantics once for ESM lookup while preserving literal CommonJS paths and original specifiers. Keep CJS wrapper var bindings and assignment history, recognizing only untouched wrapper redeclarations.
Validation: real ASAR producer workflow and CLI/MCP path/coverage cases; semantic reassignment controls. Context7 Node documentation and direct Node wrapper execution confirm wrapper behavior.
Fixes#3213Fixes#3214Fixes#3223
Related: #3278, #3254
Co-authored-by: Geronimo <[email protected]>
Co-authored-by: Paolo Valletta <[email protected]>
Preserve CommonJS literal paths and confined ESM URL semantics, including package main fallback, directory intent, Unicode identity, and present opaque modules. Parse extraction inputs at their AST/source owner, retain skipped HTML and source-map coverage, and distinguish endpoint candidates from proven receiver facts. Version structural fingerprints with computed literal contents and propagate them through worker contracts.
Reviewed fixes include #1810, #1840, #2642, #2700, #2702, #2714, #2803, #2960, #2968, #2986, #3035, and #3036.
Validation: 158 resolver tests passed; public CLI/MCP module lookup controls, package-main/Unicode workflows, and six builtin workflows passed in the current compiled lane. Worker schema/fingerprint regressions passed. Large public pdf.js completion and real Electron analysis remain unverified.
Analyze exact selected sources in first-request order before unrelated
static scopes, preserving full artifact identity and byte verification.
Retain selection in CLI/MCP Evidence and summaries, with explicit unknowns
and partial coverage for unselected sources. Keep default full analysis.
Fixes#1848
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Kaoru0822 <[email protected]>
Require the caller artifact resource scope when reading JavaScript artifacts. Transfer failed nested ASAR cleanup to that scope so later work retries the same owner before admission. Preserve traversal failures and attempt every remaining iterator during unwind.
Validation: reconstruction, integrity, content identity, cancellation and nested-reader cleanup boundary checks.
BREAKING CHANGE: readJavaScriptArtifactFiles now requires ArtifactResourceScope as its third argument; the optional abort signal is fourth.
Keep failed reader, root descriptor, and output-tree cleanup with the caller. Drain admitted work before close, retry the same retained owners, and block new resource work while cleanup is incomplete. Preserve primary failures and complete inventory observations.
Thread ownership through JavaScript reconstruction, the CLI's one-shot scope, MCP server shutdown, verifier scripts, and test fixtures. Remove redundant ownership flags and the unused validated test wrapper.
Validate with 850 passing focused tests across 90 suites (two skipped), targeted classification and cleanup retries, static and unused-code checks, and real macOS CLI/MCP directory, ZIP, and DMG workflows. Native Windows and deep-analysis providers were not verified.
BREAKING CHANGE: Direct artifact inventory/extraction and JavaScript analysis APIs require an explicit caller-owned ArtifactResourceScope. CLI and MCP input contracts are unchanged.
analyze_javascript_application ran several long phases with no event-loop
turn, so MCP ping and cancellation waited: each file's parse, analysis and
semantic projection; building every application node and relationship
before the application graph's first sealing step; and whole-graph schema
parses inside both immutable graph factories.
- Each file runs as steps (parse, static analysis, semantic analysis, then
each projection pass), driven by the existing time-sliced checkpoint.
- Application graph input construction yields between phases, per module
link and per file of findings.
- The pipeline transfers its privately built graph inputs to new sealing
steps that validate the graph's own fields synchronously and elements,
content checks and the digest in steps. The public copying factories
keep their synchronous capture.
Results are unchanged: graph IDs and the complete result digest match main
on five inputs including Obsidian's 23 MB obsidian.asar. On the issue's
1,200-function fixture the longest event-loop block falls from about
290 ms to 90 ms, and ping after abort from up to 286 ms to at most 56 ms.
On obsidian.asar it falls from 10.9 s to 5.4 s; the rest is one analyzer
stage of a single very large file.
Refs #1462
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: N0zoM1z0 <[email protected]>
analyze_javascript_application reported every input-selection problem as
an artifact fault:
- a missing input path: "Artifact could not be read or written", with no
path or reason;
- an unreadable selected directory: the same generic io failure;
- a regular file that is neither a directory nor an .asar, and a
--artifact-format that contradicts the selection: "Artifact is invalid
or has changed. Get a fresh copy and try again."
Report a missing path as an invalid input_path, an unreadable selection
as access_denied, a non-directory non-.asar file as unsupported_target
with the accepted inputs as remediation, and a contradicting format as an
invalid format with the observed kind as expected value. Failures inside
a selected artifact keep their existing classification.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Move whole-graph commitment and batched integrity checks into owned domain steps while retaining eager input capture, canonical IDs, full validation and completion-only immutable proofs.
Verified complete real Notion identity parity and actual stdio MCP cancellation, Evidence retention and connection reuse.
Refs #1065.