[GH-ISSUE #1462] [Bug] JavaScript analysis blocks MCP ping and cancellation during synchronous computation #497

Closed
opened 2026-10-15 18:25:35 +00:00 by bsakaguchi · 10 comments
Owner

Originally created by @N0zoM1z0 on GitHub (Oct 10, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1462

Observed on current main

Main c89c8f53187aac02e87f0ca11e3dd120b8c7efef, including merged #1390, #1433, #1437, #1445 and #1444, independently built with Node 24.18.0 and the pinned MCP SDK 2.3.1. Two CPUs, reduced priority, one heavy lane, guarded family memory. No native provider is required.

A source-owned 67,469-byte application containing 1,200 ordinary exported functions still blocks the MCP control path during analysis. After warming discovery/output validators, aborting the ordinary call at 200 ms ends the client wait at 201.5 ms, but a ping sent immediately after abort waits a further 786.3 ms. Earlier frozen main e09cfe9b measured 929.8 ms; the reviewed #1444 head measured 800.0 ms. These are individual observations, not percentile guarantees.

Cancellation eventually takes effect correctly in these runs: get_evidence_bundle contains zero records, a subsequent small application analysis succeeds on the same connection, close succeeds, and target bytes are unchanged. Thus this issue concerns responsiveness while computation is running; these observations do not establish a late retained-Evidence or cleanup leak. The SDK labels explicit signal aborts REQUEST_TIMEOUT with message AbortError: This operation was aborted; the probe records the actual abort signal instead of interpreting that code as a provider deadline.

The same final #1444 runtime on a real Notion ASAR produced a 17,742-ms maximum ping wait during a successful 87,763-ms analysis. Frozen latest main e09cfe9b measured 18,172 ms/95,577 ms, with exact same Evidence and input SHA-256. That workflow uses an explicit 210-second request deadline and preserves complete retained Evidence when the ordinary full response exceeds the SDK receive budget. Completion and typed response-budget recovery do not satisfy the responsiveness part of #1065.

Minimal public MCP reproduction

Run from a built repository with the pinned Node/dependencies. Create a temporary application and warm the ordinary SDK client before timing the analysis:

import { Client } from '@modelcontextprotocol/client';
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
import { mkdtempSync, writeFileSync } from 'node:fs';
import { join, resolve } from 'node:path';
import { tmpdir } from 'node:os';

const root = mkdtempSync(join(tmpdir(), 'rea-cancel-'));
writeFileSync(join(root, 'package.json'),
  JSON.stringify({ name: 'rea-cancel-fixture', version: '1.0.0', main: 'index.js' }));
writeFileSync(join(root, 'index.js'), Array.from({ length: 1200 }, (_, i) =>
  `export function f${i}(){return {name:'f${i}',value:${i}};}`
).join('\n'));
const client = new Client({ name: 'cancellation-probe', version: '1' });
const transport = new StdioClientTransport({
  command: process.execPath, args: [resolve('scripts/rea.mjs'), 'mcp'],
  stderr: 'pipe',
});
transport.stderr?.on('data', () => {});
await client.connect(transport);
await client.listTools();
await client.callTool({ name: 'binary_session', arguments: {} });
const controller = new AbortController();
let ping;
const started = performance.now();
const timer = setTimeout(() => {
  controller.abort();
  const pingStarted = performance.now();
  ping = client.ping().then(() => console.log({
    ping_after_abort_ms: performance.now() - pingStarted,
  }));
}, 200);
try {
  await client.callTool({
    name: 'analyze_javascript_application', arguments: { input_path: root },
  }, { signal: controller.signal });
} catch (error) {
  console.log({ client_wait_ms: performance.now() - started, message: error.message });
} finally {
  clearTimeout(timer);
  await ping;
  console.log(await client.callTool({ name: 'get_evidence_bundle', arguments: {} }));
  await client.close();
  await transport.close();
}

The owned latest-main fixture source SHA-256 is 1c6cafcaa7221e56ae3c61c90129192ff4be4baebe34e310b57e9d7283ad7711. Keep client/server timers separate; progress notifications are coalesced, so an individual first-file notification is not guaranteed.

Owning regions and expected outcome

Source inspection identifies synchronous per-file work in JavaScriptArtifactAnalysis.analyzeArtifactFile, JavaScriptSemanticGraphBuilder.projectFile, and the initial capture/normalization performed before cooperative graph-sealing steps. The real ASAR also pauses during semantic graph capture. Attribution of every pause is a follow-up; this issue does not assume one parser is the whole cause.

Establish usable cancellation/control-path checkpoints or an owned execution boundary around those regions. Preserve source evidence, graph validation/ownership, deterministic identities, existing coverage/limits and cleanup guarantees. Validate busy-file cancellation and ping through the real CLI/stdio MCP flows, then rerun a real ASAR under the same CPU/memory constraints. Avoid addressing the delay with additional arbitrary traversal caps or discarded observations.

Refs #1065 (T2 responsiveness). #1401 is closed by #1390, and #1444 fixes a distinct repeated-write complexity problem; this residual survives both.

Originally created by @N0zoM1z0 on GitHub (Oct 10, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1462 ### Observed on current main Main `c89c8f53187aac02e87f0ca11e3dd120b8c7efef`, including merged #1390, #1433, #1437, #1445 and #1444, independently built with Node 24.18.0 and the pinned MCP SDK 2.3.1. Two CPUs, reduced priority, one heavy lane, guarded family memory. No native provider is required. A source-owned 67,469-byte application containing 1,200 ordinary exported functions still blocks the MCP control path during analysis. After warming discovery/output validators, aborting the ordinary call at 200 ms ends the **client** wait at 201.5 ms, but a ping sent immediately after abort waits a further **786.3 ms**. Earlier frozen main `e09cfe9b` measured 929.8 ms; the reviewed #1444 head measured 800.0 ms. These are individual observations, not percentile guarantees. Cancellation eventually takes effect correctly in these runs: `get_evidence_bundle` contains zero records, a subsequent small application analysis succeeds on the same connection, close succeeds, and target bytes are unchanged. Thus this issue concerns responsiveness while computation is running; these observations do not establish a late retained-Evidence or cleanup leak. The SDK labels explicit signal aborts `REQUEST_TIMEOUT` with message `AbortError: This operation was aborted`; the probe records the actual abort signal instead of interpreting that code as a provider deadline. The same final #1444 runtime on a real Notion ASAR produced a **17,742-ms maximum ping wait** during a successful 87,763-ms analysis. Frozen latest main `e09cfe9b` measured 18,172 ms/95,577 ms, with exact same Evidence and input SHA-256. That workflow uses an explicit 210-second request deadline and preserves complete retained Evidence when the ordinary full response exceeds the SDK receive budget. Completion and typed response-budget recovery do not satisfy the responsiveness part of #1065. ### Minimal public MCP reproduction Run from a built repository with the pinned Node/dependencies. Create a temporary application and warm the ordinary SDK client before timing the analysis: ```js import { Client } from '@modelcontextprotocol/client'; import { StdioClientTransport } from '@modelcontextprotocol/client/stdio'; import { mkdtempSync, writeFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { tmpdir } from 'node:os'; const root = mkdtempSync(join(tmpdir(), 'rea-cancel-')); writeFileSync(join(root, 'package.json'), JSON.stringify({ name: 'rea-cancel-fixture', version: '1.0.0', main: 'index.js' })); writeFileSync(join(root, 'index.js'), Array.from({ length: 1200 }, (_, i) => `export function f${i}(){return {name:'f${i}',value:${i}};}` ).join('\n')); const client = new Client({ name: 'cancellation-probe', version: '1' }); const transport = new StdioClientTransport({ command: process.execPath, args: [resolve('scripts/rea.mjs'), 'mcp'], stderr: 'pipe', }); transport.stderr?.on('data', () => {}); await client.connect(transport); await client.listTools(); await client.callTool({ name: 'binary_session', arguments: {} }); const controller = new AbortController(); let ping; const started = performance.now(); const timer = setTimeout(() => { controller.abort(); const pingStarted = performance.now(); ping = client.ping().then(() => console.log({ ping_after_abort_ms: performance.now() - pingStarted, })); }, 200); try { await client.callTool({ name: 'analyze_javascript_application', arguments: { input_path: root }, }, { signal: controller.signal }); } catch (error) { console.log({ client_wait_ms: performance.now() - started, message: error.message }); } finally { clearTimeout(timer); await ping; console.log(await client.callTool({ name: 'get_evidence_bundle', arguments: {} })); await client.close(); await transport.close(); } ``` The owned latest-main fixture source SHA-256 is `1c6cafcaa7221e56ae3c61c90129192ff4be4baebe34e310b57e9d7283ad7711`. Keep client/server timers separate; progress notifications are coalesced, so an individual first-file notification is not guaranteed. ### Owning regions and expected outcome Source inspection identifies synchronous per-file work in `JavaScriptArtifactAnalysis.analyzeArtifactFile`, `JavaScriptSemanticGraphBuilder.projectFile`, and the initial capture/normalization performed before cooperative graph-sealing steps. The real ASAR also pauses during semantic graph capture. Attribution of every pause is a follow-up; this issue does not assume one parser is the whole cause. Establish usable cancellation/control-path checkpoints or an owned execution boundary around those regions. Preserve source evidence, graph validation/ownership, deterministic identities, existing coverage/limits and cleanup guarantees. Validate busy-file cancellation and ping through the real CLI/stdio MCP flows, then rerun a real ASAR under the same CPU/memory constraints. Avoid addressing the delay with additional arbitrary traversal caps or discarded observations. Refs #1065 (T2 responsiveness). #1401 is closed by #1390, and #1444 fixes a distinct repeated-write complexity problem; this residual survives both.
Author
Owner

@CassieFox23 commented on GitHub (Oct 10, 2026):

TL;DR: I see the same thing on Linux. The abort ends the client wait at once. A ping sent then still waits for the block to end. At 1,200 functions that is about half a second here. It grows with the function count. Two open-source apps show pings stuck for 5 to 6 s.

I ran your repro shape on main c89c8f53 (your 1,200-function file, same SHA). The client aborts at 200 ms and sends one ping right away. Each cell is the median of 3 runs (6 for 1,200 on Node 24).

Ping wait after the abort, ms:

Functions Node 22 Node 24 Node 26
300 143 39 25
1,200 780 517 501
2,400 1,569 1,129 1,037
  • The client wait ended at 201 to 206 ms in all 39 runs.
  • The server logged its stop within 6 ms of each ping reply.
  • Cancel worked in every run, as in your report. The Evidence bundle was empty. The next call and close worked.

Before and after #1444 (1,200 functions, Node 24, 3 interleaved runs each):

Tree Ping after abort, ms
66863b60, just before #1444 515
c89c8f53, main 526
6.3.0 release 513

So #1444 does not change this case here.

Real apps, one full analysis with a ping every 250 ms (Node 24, 2 runs each):

App Analysis Max ping p95 Median
Beyond All Reason launcher 49.7 / 54.5 s 5.7 / 6.4 s 3.4 / 3.9 s 28 / 41 ms
Hermes Desktop vendor chunk 9.2 / 9.2 s 5.7 / 5.5 s 5.5 / 5.2 s 1.2 / 1.0 s
  • Both runs of each app gave the same reply and Evidence hash. No ping failed.
  • In the launcher, the long wait starts after the last file parse. It ends when graph sealing starts. Edit: the profile shows that gap is the app graph build.
  • The Hermes chunk is one file, so its parse is one block of about 6 s.

My earlier T2 fixture now stops at 2,096 ms, down from 2,842 ms on 8550913c. Load, heap and priority differ, so I can't credit a code change. At 1,200 functions it blocks about 3.7 times longer than yours.

Not run

Edit: results are in the follow-up, on a less busy machine. The real-app waits here ran high because the machine was busy. Still not run: the closed-source app, the #1444 head commit, Windows and macOS.

  • The closed-source app from your report. It is not on this box.
  • e09cfe9b and the #1444 head commit. e09cfe9b ran; the head commit did not.
  • Before and after #1444 at other sizes, or on the real apps.
  • The real apps on Node 22 and 26.
  • A CPU profile of where the block sits.
  • Windows and macOS.
  • How busy the box was: Linux's load number counts programs running or waiting for a CPU, averaged over a minute. This box has 24 CPU threads.
    • Small runs: 2 to 4. So about 2 to 4 of the 24 threads were busy. The box was mostly idle.
    • App runs: up to 5.5. Other tests shared the box then. So treat the app numbers as rough.

Thanks, N0zoM1z0, for the clear repro and the fixture SHA. It made the match easy to check.

Full abort table (median [min–max] of 3 runs, ms)

Times count from the tool call. "Server stop" is REA's own tool-done log line.

Case Client wait Ping after abort Server stop Next call
300, Node 22 202 [201–202] 142.8 [140.8–169.6] 347.1 [342.4–372.0] ok 3/3
300, Node 24 202 [201–202] 38.5 [21.5–59.1] 240.3 [223.5–261.0] ok 3/3
300, Node 26 202 [201–202] 24.9 [21.8–41.3] 226.3 [223.6–243.2] ok 3/3
1,200, Node 22 203 [202–206] 780.2 [756.4–969.4] 982.2 [959.0–1,173.3] ok 3/3
1,200, Node 24 (6 runs) 202.5 [201–204] 517.1 [507.2–572.0] 720.4 [708.0–775.4] ok 6/6
1,200, Node 26 201 [201–202] 500.8 [489.2–620.8] 701.5 [690.8–822.1] ok 3/3
2,400, Node 22 204 [204–205] 1,569.0 [1,522.0–1,620.7] 1,772.0 [1,730.9–1,824.3] ok 3/3
2,400, Node 24 202 [201–206] 1,129.0 [1,119.5–1,155.7] 1,330.7 [1,320.8–1,363.3] ok 3/3
2,400, Node 26 202 [201–202] 1,037.0 [1,034.8–1,048.2] 1,239.1 [1,237.0–1,251.0] ok 3/3
1,200, 66863b60, Node 24 203 [202–203] 514.6 [506.5–545.3] 717.3 [708.4–748.4] ok 3/3
1,200, 6.3.0, Node 24 202 [201–204] 512.6 [501.9–541.2] 713.7 [706.2–743.3] ok 3/3
T2 fixture, 1,200, Node 24 205 [205–206] 1,891.0 [1,859.6–1,919.6] 2,096.0 [2,065.0–2,125.6] ok 3/3
  • Each aborted call got the SDK's REQUEST_TIMEOUT abort error, as you saw.
  • The server log said status: error for every cancelled call.
  • No server, child process or temp file was left. The server quit 31 to 55 ms after close.
  • The #1444 rows ran interleaved with main in one batch.
  • The T2 row cancels 200 ms after the first progress note, as T2 did.
Real-app details
  • Launcher: app.asar, 26,870,695 bytes, sha256 595810df…5d83ad6f03, format asar.

  • Hermes Desktop: vendor-react-C4pS_tun.js from a v0.21.6 build, 258,268 bytes, sha256 8e7a4c3b…0b7f93. It sits alone in a folder, format directory. The tool rejects a bare .js path.

  • Evidence went out through export_evidence_bundle. Launcher: 245,794,850 bytes, 32d33aa4… both runs. Hermes: 44,944,475 bytes, d71721d3… both runs.

  • Launcher stage starts, run 1, in ms:

    Stage Start
    Parse files 1,347
    Last file parse 27,633
    App graph seal 33,471
    Semantic seal 35,912
    Validate 44,066
    Hash 46,513
    Done 49,628
  • The max ping went out at 27,801 ms and came back at the seal step.

  • Pings sent during semantic sealing came back in 81 ms at most.

  • Over 1 s: 31 and 37 of about 200 launcher pings. For Hermes: 19 and 18 of 36.

  • The server logged ok for every app call. The reply was the typed resource_constraint notice.

  • The semantic seal stage is the longest gap, but pings stay fast there.

  • Peak memory for client and server together: about 2,340 MiB launcher, about 990 MiB Hermes.

How I measured
  • One stdio MCP session per run, SDK 2.3.1 client from the tree under test.
  • Server: node --max-old-space-size=3072 scripts/rea.mjs mcp (4,096 for the real apps).
  • Warm-up: list tools, one binary_session call, three pings.
  • Abort runs: no background pings. abort() with no reason at 200 ms, then one ping at once. Format left at the default, as in your repro.
  • After the server went idle: get_evidence_bundle, then a 3-function app analysis, then a ping and close.
  • App runs: a ping every 250 ms with a 45 s deadline each, and a 210 s call deadline.
  • Each run: env -i, its own HOME and short TMPDIR, taskset -c 2,3, nice -n 10.
  • A side process capped family memory. It never fired.
Commands
git -C rea.git archive c89c8f53187aac02e87f0ca11e3dd120b8c7efef | tar -x -C main
cd main && npm ci && npm run build:cached
( ulimit -c 0; env -i HOME=$PWD/home TMPDIR=/tmp/r1462/t PATH=$NODE_BIN:/usr/bin:/bin \
  timeout 600 taskset -c 2,3 nice -n 10 node client.mjs --root main \
  --fixture f1200 --mode at-offset --cancel-ms 200 --ping-ms 0 \
  --retained-check --next-small f3 \
  --server-node-args --max-old-space-size=3072 --out result.json )
# real apps: --mode none --ping-ms 250 --ping-timeout-ms 45000
#   --call-timeout-ms 210000 --format asar --export-evidence <tmp>/ev.json
Test setup
  • Box: Nobara 44 (Fedora 44 base), Linux 7.2.9
  • CPU: AMD Ryzen 9 5900X, 12 cores / 24 threads (runs pinned to 2)
  • RAM: 32 GB DDR4-3600
  • Node: 22.23.1, 24.18.0, 26.11.1 (built on 24.18.0)
  • Head / base: c89c8f53 / 66863b60, plus the 6.3.0 release
  • Other: MCP SDK 2.3.1
  • Other: the Beyond All Reason launcher (launcher code MIT; Flathub package GPL-2.0-or-later)
  • Other: Hermes Desktop (MIT)

🤖 Generated with Claude Code (Opus 5.5) 🦊

<!-- gh-comment-id:6094736071 --> @CassieFox23 commented on GitHub (Oct 10, 2026): **TL;DR:** I see the same thing on Linux. The abort ends the client wait at once. A ping sent then still waits for the block to end. At 1,200 functions that is about half a second here. It grows with the function count. Two open-source apps show pings stuck for 5 to 6 s. I ran your repro shape on main `c89c8f53` (your 1,200-function file, same SHA). The client aborts at 200 ms and sends one ping right away. Each cell is the median of 3 runs (6 for 1,200 on Node 24). Ping wait after the abort, ms: | Functions | Node 22 | Node 24 | Node 26 | | --- | --- | --- | --- | | 300 | 143 | 39 | 25 | | 1,200 | 780 | 517 | 501 | | 2,400 | 1,569 | 1,129 | 1,037 | - The client wait ended at 201 to 206 ms in all 39 runs. - The server logged its stop within 6 ms of each ping reply. - Cancel worked in every run, as in your report. The Evidence bundle was empty. The next call and close worked. Before and after #1444 (1,200 functions, Node 24, 3 interleaved runs each): | Tree | Ping after abort, ms | | --- | --- | | `66863b60`, just before #1444 | 515 | | `c89c8f53`, main | 526 | | 6.3.0 release | 513 | So #1444 does not change this case here. Real apps, one full analysis with a ping every 250 ms (Node 24, 2 runs each): | App | Analysis | Max ping | p95 | Median | | --- | --- | --- | --- | --- | | Beyond All Reason launcher | 49.7 / 54.5 s | 5.7 / 6.4 s | 3.4 / 3.9 s | 28 / 41 ms | | Hermes Desktop vendor chunk | 9.2 / 9.2 s | 5.7 / 5.5 s | 5.5 / 5.2 s | 1.2 / 1.0 s | - Both runs of each app gave the same reply and Evidence hash. No ping failed. - In the launcher, the long wait starts after the last file parse. It ends when graph sealing starts. Edit: the profile shows that gap is the app graph build. - The Hermes chunk is one file, so its parse is one block of about 6 s. My [earlier T2 fixture](https://github.com/morluto/rea/issues/1065#issuecomment-6093389881) now stops at 2,096 ms, down from 2,842 ms on `8550913c`. Load, heap and priority differ, so I can't credit a code change. At 1,200 functions it blocks about 3.7 times longer than yours. **Not run** Edit: results are in [the follow-up](https://github.com/morluto/rea/issues/1462#issuecomment-6095665800), on a less busy machine. The real-app waits here ran high because the machine was busy. Still not run: the closed-source app, the #1444 head commit, Windows and macOS. - The closed-source app from your report. It is not on this box. - ~~`e09cfe9b`~~ and the #1444 head commit. `e09cfe9b` ran; the head commit did not. - ~~Before and after #1444 at other sizes, or on the real apps.~~ - ~~The real apps on Node 22 and 26.~~ - ~~A CPU profile of where the block sits.~~ - Windows and macOS. - How busy the box was: Linux's load number counts programs running or waiting for a CPU, averaged over a minute. This box has 24 CPU threads. - Small runs: 2 to 4. So about 2 to 4 of the 24 threads were busy. The box was mostly idle. - App runs: up to 5.5. Other tests shared the box then. So treat the app numbers as rough. Thanks, N0zoM1z0, for the clear repro and the fixture SHA. It made the match easy to check. <details> <summary>Full abort table (median [min–max] of 3 runs, ms)</summary> Times count from the tool call. "Server stop" is REA's own tool-done log line. | Case | Client wait | Ping after abort | Server stop | Next call | | --- | --- | --- | --- | --- | | 300, Node 22 | 202 [201–202] | 142.8 [140.8–169.6] | 347.1 [342.4–372.0] | ok 3/3 | | 300, Node 24 | 202 [201–202] | 38.5 [21.5–59.1] | 240.3 [223.5–261.0] | ok 3/3 | | 300, Node 26 | 202 [201–202] | 24.9 [21.8–41.3] | 226.3 [223.6–243.2] | ok 3/3 | | 1,200, Node 22 | 203 [202–206] | 780.2 [756.4–969.4] | 982.2 [959.0–1,173.3] | ok 3/3 | | 1,200, Node 24 (6 runs) | 202.5 [201–204] | 517.1 [507.2–572.0] | 720.4 [708.0–775.4] | ok 6/6 | | 1,200, Node 26 | 201 [201–202] | 500.8 [489.2–620.8] | 701.5 [690.8–822.1] | ok 3/3 | | 2,400, Node 22 | 204 [204–205] | 1,569.0 [1,522.0–1,620.7] | 1,772.0 [1,730.9–1,824.3] | ok 3/3 | | 2,400, Node 24 | 202 [201–206] | 1,129.0 [1,119.5–1,155.7] | 1,330.7 [1,320.8–1,363.3] | ok 3/3 | | 2,400, Node 26 | 202 [201–202] | 1,037.0 [1,034.8–1,048.2] | 1,239.1 [1,237.0–1,251.0] | ok 3/3 | | 1,200, `66863b60`, Node 24 | 203 [202–203] | 514.6 [506.5–545.3] | 717.3 [708.4–748.4] | ok 3/3 | | 1,200, 6.3.0, Node 24 | 202 [201–204] | 512.6 [501.9–541.2] | 713.7 [706.2–743.3] | ok 3/3 | | T2 fixture, 1,200, Node 24 | 205 [205–206] | 1,891.0 [1,859.6–1,919.6] | 2,096.0 [2,065.0–2,125.6] | ok 3/3 | - Each aborted call got the SDK's `REQUEST_TIMEOUT` abort error, as you saw. - The server log said `status: error` for every cancelled call. - No server, child process or temp file was left. The server quit 31 to 55 ms after close. - The #1444 rows ran interleaved with main in one batch. - The T2 row cancels 200 ms after the first progress note, as T2 did. </details> <details> <summary>Real-app details</summary> - Launcher: `app.asar`, 26,870,695 bytes, sha256 `595810df…5d83ad6f03`, format `asar`. - Hermes Desktop: `vendor-react-C4pS_tun.js` from a v0.21.6 build, 258,268 bytes, sha256 `8e7a4c3b…0b7f93`. It sits alone in a folder, format `directory`. The tool rejects a bare `.js` path. - Evidence went out through `export_evidence_bundle`. Launcher: 245,794,850 bytes, `32d33aa4…` both runs. Hermes: 44,944,475 bytes, `d71721d3…` both runs. - Launcher stage starts, run 1, in ms: | Stage | Start | | --- | --- | | Parse files | 1,347 | | Last file parse | 27,633 | | App graph seal | 33,471 | | Semantic seal | 35,912 | | Validate | 44,066 | | Hash | 46,513 | | Done | 49,628 | - The max ping went out at 27,801 ms and came back at the seal step. - Pings sent during semantic sealing came back in 81 ms at most. - Over 1 s: 31 and 37 of about 200 launcher pings. For Hermes: 19 and 18 of 36. - The server logged `ok` for every app call. The reply was the typed `resource_constraint` notice. - The semantic seal stage is the longest gap, but pings stay fast there. - Peak memory for client and server together: about 2,340 MiB launcher, about 990 MiB Hermes. </details> <details> <summary>How I measured</summary> - One stdio MCP session per run, SDK 2.3.1 client from the tree under test. - Server: `node --max-old-space-size=3072 scripts/rea.mjs mcp` (4,096 for the real apps). - Warm-up: list tools, one `binary_session` call, three pings. - Abort runs: no background pings. `abort()` with no reason at 200 ms, then one ping at once. Format left at the default, as in your repro. - After the server went idle: `get_evidence_bundle`, then a 3-function app analysis, then a ping and close. - App runs: a ping every 250 ms with a 45 s deadline each, and a 210 s call deadline. - Each run: `env -i`, its own HOME and short TMPDIR, `taskset -c 2,3`, `nice -n 10`. - A side process capped family memory. It never fired. </details> <details> <summary>Commands</summary> ```sh git -C rea.git archive c89c8f53187aac02e87f0ca11e3dd120b8c7efef | tar -x -C main cd main && npm ci && npm run build:cached ( ulimit -c 0; env -i HOME=$PWD/home TMPDIR=/tmp/r1462/t PATH=$NODE_BIN:/usr/bin:/bin \ timeout 600 taskset -c 2,3 nice -n 10 node client.mjs --root main \ --fixture f1200 --mode at-offset --cancel-ms 200 --ping-ms 0 \ --retained-check --next-small f3 \ --server-node-args --max-old-space-size=3072 --out result.json ) # real apps: --mode none --ping-ms 250 --ping-timeout-ms 45000 # --call-timeout-ms 210000 --format asar --export-evidence <tmp>/ev.json ``` </details> <details> <summary>Test setup</summary> - Box: Nobara 44 (Fedora 44 base), Linux 7.2.9 - CPU: AMD Ryzen 9 5900X, 12 cores / 24 threads (runs pinned to 2) - RAM: 32 GB DDR4-3600 - Node: 22.23.1, 24.18.0, 26.11.1 (built on 24.18.0) - Head / base: `c89c8f53` / `66863b60`, plus the 6.3.0 release - Other: MCP SDK 2.3.1 - Other: the [Beyond All Reason launcher](https://flathub.org/apps/info.beyondallreason.bar) (launcher code [MIT](https://github.com/beyond-all-reason/spring-launcher/blob/master/LICENSE); Flathub package [GPL-2.0-or-later](https://github.com/flathub/info.beyondallreason.bar/blob/60445fcc28ede165cd2977a869e29e25da01353b/info.beyondallreason.bar.metainfo.xml#L7)) - Other: [Hermes Desktop](https://github.com/NousResearch/hermes-agent) ([MIT](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE)) </details> 🤖 Generated with Claude Code (Opus 5.5) 🦊
Author
Owner

@N0zoM1z0 commented on GitHub (Oct 10, 2026):

Follow-up after merged #1457/#1460 on b118f044 (the probe build includes only documentation/comment changes from #1466): same 67,469-byte/1,200-function fixture and actual warmed SDK stdio flow still reproduce the control-path delay. Explicit abort at 203.8 ms ends the client wait at 205.2 ms; the subsequent ping waits 572.7 ms. Zero cancelled analysis records are retained; the same follow-up Evidence identity, successful close and unchanged source bytes are preserved. Guard exit 0, 811,786,240-byte peak sampled family RSS.

This is a single narrow observation. The context-hash optimization can reduce computation, but the synchronous computation/capture path and this residual remain. No claim that the full ASAR or a response percentile is now fixed.

<!-- gh-comment-id:6094770114 --> @N0zoM1z0 commented on GitHub (Oct 10, 2026): Follow-up after merged #1457/#1460 on `b118f044` (the probe build includes only documentation/comment changes from #1466): same 67,469-byte/1,200-function fixture and actual warmed SDK stdio flow still reproduce the control-path delay. Explicit abort at 203.8 ms ends the client wait at 205.2 ms; the subsequent ping waits **572.7 ms**. Zero cancelled analysis records are retained; the same follow-up Evidence identity, successful close and unchanged source bytes are preserved. Guard exit 0, 811,786,240-byte peak sampled family RSS. This is a single narrow observation. The context-hash optimization can reduce computation, but the synchronous computation/capture path and this residual remain. No claim that the full ASAR or a response percentile is now fixed.
Author
Owner

@N0zoM1z0 commented on GitHub (Oct 10, 2026):

Real full-ASAR follow-up through the rebuilt local integration 214ebf33: production sources/scripts/package are identical to main 934ffd28 after #1457/#1458 (the intervening #1469 is website-only). The actual pinned SDK stdio workflow still observes a 13,078 ms maximum ping wait. The supplied operation progress token, longer explicit client deadline and the successful complete analysis do not remove that control-path pause.

Notion ASAR SHA-256 remains 97c41bc14fc0ea8c91cd34f502660963dfdf294d5eb35165ccac9d30963069d4; complete retained Evidence remains exactly ev_8b49aebfa361929c6c2b206271260bf2851a55e729884215b8f87fbb4ad8b490. The typed 10 MiB framing constraint returns that reference; real summary/module paging, feature trace, distinct-input validation, ping, close and expired-reference checks pass. Default discovery remains all 139 tools. Guard exit 0, 171.62-second whole harness, 1,897,279,488-byte peak sampled family RSS, input unchanged.

Analysis measured 163.45 s in this observation. A frozen earlier-build control is being checked in the same current environment because wall-time variance is substantial; this value is not assigned causally to any one merge or presented as a throughput regression. The longest observed pause starts during per-file analysis/projection; later graph construction/capture/verification still has multi-second control waits. The residual requires actual usable scheduling/cancellation at those owning boundaries, preserving full validation, Evidence and lifecycle guarantees.

<!-- gh-comment-id:6095051834 --> @N0zoM1z0 commented on GitHub (Oct 10, 2026): Real full-ASAR follow-up through the rebuilt local integration `214ebf33`: production sources/scripts/package are identical to main `934ffd28` after #1457/#1458 (the intervening #1469 is website-only). The actual pinned SDK stdio workflow still observes a **13,078 ms maximum ping wait**. The supplied operation progress token, longer explicit client deadline and the successful complete analysis do not remove that control-path pause. Notion ASAR SHA-256 remains `97c41bc14fc0ea8c91cd34f502660963dfdf294d5eb35165ccac9d30963069d4`; complete retained Evidence remains exactly `ev_8b49aebfa361929c6c2b206271260bf2851a55e729884215b8f87fbb4ad8b490`. The typed 10 MiB framing constraint returns that reference; real summary/module paging, feature trace, distinct-input validation, ping, close and expired-reference checks pass. Default discovery remains all 139 tools. Guard exit 0, 171.62-second whole harness, 1,897,279,488-byte peak sampled family RSS, input unchanged. Analysis measured 163.45 s in this observation. A frozen earlier-build control is being checked in the same current environment because wall-time variance is substantial; this value is not assigned causally to any one merge or presented as a throughput regression. The longest observed pause starts during per-file analysis/projection; later graph construction/capture/verification still has multi-second control waits. The residual requires actual usable scheduling/cancellation at those owning boundaries, preserving full validation, Evidence and lifecycle guarantees.
Author
Owner

@N0zoM1z0 commented on GitHub (Oct 10, 2026):

Latest rebuilt main 7296f2b5 (including #1474's explicit semantic representation change) still reproduces the small-source control delay with the unchanged 67,469-byte / 1,200-function fixture. Actual warmed default-SDK stdio: explicit abort at 203.86 ms ends the client wait at 204.91 ms; ping then waits 595.53 ms. Zero cancelled records are retained, the follow-up analysis/ping/close works, and source SHA-256 remains 1c6cafcaa7221e56ae3c61c90129192ff4be4baebe34e310b57e9d7283ad7711. Guard exit 0, 7.23 s, 805,130,240-byte sampled peak family RSS.

The follow-up Evidence ID changes with the documented #1474 relation/strict-schema change; the earlier exact-ID ASAR pair is explicitly frozen before that merge. This latest check proves the residual after payload cleanup without claiming that the full ASAR has been remeasured at 7296f2b5, or conflating immediate client abort with immediate server cancellation handling.

<!-- gh-comment-id:6095115475 --> @N0zoM1z0 commented on GitHub (Oct 10, 2026): Latest rebuilt main `7296f2b5` (including #1474's explicit semantic representation change) still reproduces the small-source control delay with the unchanged 67,469-byte / 1,200-function fixture. Actual warmed default-SDK stdio: explicit abort at 203.86 ms ends the client wait at 204.91 ms; ping then waits **595.53 ms**. Zero cancelled records are retained, the follow-up analysis/ping/close works, and source SHA-256 remains `1c6cafcaa7221e56ae3c61c90129192ff4be4baebe34e310b57e9d7283ad7711`. Guard exit 0, 7.23 s, 805,130,240-byte sampled peak family RSS. The follow-up Evidence ID changes with the documented #1474 relation/strict-schema change; the earlier exact-ID ASAR pair is explicitly frozen before that merge. This latest check proves the residual after payload cleanup without claiming that the full ASAR has been remeasured at `7296f2b5`, or conflating immediate client abort with immediate server cancellation handling.
Author
Owner

@CassieFox23 commented on GitHub (Oct 10, 2026):

TL;DR: A CPU profile shows where the long app pause sits. On the launcher, the worst block (4.4 to 4.5 s) builds the whole app graph in one go, just after the last file. Main cuts the 1,200-function wait from 507 ms to 427 ms here, and #1444 changes nothing.

I tested main cbcba290 today. Its JavaScript code is the same as in your 7296f2b5. The asar reader differs, from #1480. The two open-source apps are the Beyond All Reason launcher (MIT) and Hermes Desktop (MIT). The launcher's Flathub build is out under GPL-2.0-or-later, as its own metadata file says.

Ping wait after the abort at 200 ms, in ms. Each cell is the median of 3 runs on main.

Functions Node 22 Node 24 Node 26
300 113 156 * 16 *
1,200 597 427 356
2,400 1,161 879 859

* At 300 the runs split in two: 13, 156 and 159 ms on Node 24, then 14, 16 and 160 ms on Node 26. The file block ends close to 200 ms, and a second block of about 170 ms follows. So the wait hangs on which side of that gap the abort lands.

  • By commit (in a fold below), 1ec490f3 has the same code as c89c8f53 from my last post. It gives 507 ms now, and 517 ms then. So the drop to 427 ms on main comes from new code, not from the box. I did not bisect #1457, #1458 and #1474.
  • You saw 595.53 ms on 7296f2b5. Here main gives 427 ms on Node 24. Last time it was 786 vs 517, so our boxes keep about the same ratio.
  • All 54 cancels worked as before. No reply was sent for the cancelled call. No Evidence was kept, and the next call and close worked.

Longest ping wait in one full app run, in seconds. Each cell shows two runs, with a ping every 250 ms.

App on main Node 22 Node 24 Node 26
Launcher 5.0 / 5.2 4.5 / 4.1 4.0 / 3.9
Hermes chunk 4.2 / 4.1 3.7 / 3.7 3.4 / 3.3
  • My last post said 5.7 / 6.4 s for the launcher, and 5.7 / 5.5 s for Hermes. 1ec490f3 runs that same code. Today it gives 5.2 / 4.8 and 4.2 / 4.2 s, and the launcher Evidence bytes match. So the gap comes from the busier box back then.
  • No ping failed in any of the 24 app runs.

Where the event loop stops, on main with Node 24. A timer in the server logs each gap. The CPU profile shows what runs in it. Times are in seconds, with two launcher runs.

Block Launcher Hermes chunk Your 1,200 file
Parse and project one file 2.6 / 2.5, one file 3.9 0.61 to 0.64
Build the app graph 4.5 / 4.4 under 0.1 0.58, only with no cancel
Build the semantic graph 1.6 / 1.5 0.37 under 0.1
Seal, check and hash 0.18 at most under 0.1 under 0.1
  • The launcher's worst block is the app graph build. It runs in one go, right after the last file. It is not file parsing.
  • From the client it looks like parsing, since the note for that step never comes through. REA drops any progress note sent within 100 ms of the one before.
  • In that block, about 30% of the time makes canonical JSON for IDs. About 30% more goes to zod checks. The parser takes under 1%.
  • In the file blocks, the Babel parser takes only 3 to 6%. The rest is REA's own work on the tree: walks, ID hashing and zod checks.
  • You saw the longest pause start in the per-file work. On the launcher, it starts just after the last file. I can't check your app here.

Still not run

  • The closed-source app from your report. It is not on this box.
  • The #1444 head commit 439bc1a5.
  • Which of #1457, #1458 or #1474 made main faster.
  • The older trees on Node 22 and 26.
  • Profiles on Node 22 and 26.
  • Windows and macOS.

Thanks, N0zoM1z0, for the full-app numbers. They showed me where to point the profiler.

By commit, Node 24

Ping wait after the abort, ms, median of 3:

Functions e09cfe9b 66863b60, before #1444 1ec490f3, #1444 cbcba290, main
300 29 23 23 156 *
1,200 491 504 507 427
2,400 1,035 1,108 1,080 879

Longest ping wait in a full app run, s, two runs:

App on Node 24 e09cfe9b 66863b60 1ec490f3 cbcba290
Launcher 4.9 / 5.6 5.1 / 5.2 5.2 / 4.8 4.5 / 4.1
Hermes chunk 4.3 / 4.3 4.4 / 4.4 4.2 / 4.2 3.7 / 3.7
Profile detail

How I measured:

  • The server ran with --cpu-prof, sampling every 1 ms.
  • A small preload in the server ran a 10 ms timer. It logged each gap over 50 ms. A gap means the event loop did not turn.
  • The profile, the gap log and the client all use the same clock. I checked that first.
  • I cut the profile to each gap. Then I split its samples by the REA step on the stack.

Measured: gap start and end, ping times, samples per function, and when each progress note came in. Inferred: which REA step a function belongs to, and the file name below.

Launcher run 1, gaps over 600 ms, in ms from the call:

Gap Length Where the samples are
6,797 to 7,723 926 one file, parse and project
12,975 to 15,591 2,616 one file, parse and project
18,947 to 19,624 676 one file, parse and project
19,711 to 20,516 805 one file, parse and project
23,205 to 27,655 4,450 app graph: build 2,576, then clone and check 1,613
27,915 to 29,517 1,602 semantic graph build 1,409
  • Run 2 shows the same shape. Its biggest gaps are 4,385, 2,528 and 1,547 ms.
  • Run 1 has 88 file gaps over 50 ms, for 14.9 s in all.
  • The sealing steps yield every 8 ms. They never stopped the loop for more than 177 ms.
  • Check and hash steps never stopped it for more than 50 ms.
  • The 2.6 s file is number 896 of 2,027. The asar lists jimp/browser/lib/jimp.js (588,235 bytes) at that spot, so I think that is the file. REA did not name it.

Self time in the 4.45 s app graph gap:

Code ms Share
dist/domain/canonicalDigest.js 1,361 31%
zod/v4/core/schemas.js 1,350 30%
native, mostly ID regex checks 506 11%
hash 323 7%
garbage collector 247 6%
@babel/parser 1 0%
  • On the stack: buildJavaScriptArtifactGraphInput 2,576 ms. Under it, addJavaScriptModuleRelationships takes 1,546 ms, mostly addExportRelationship.
  • createJavaScriptApplicationGraph takes 1,613 ms. Its own doc comment says it clones and checks in one go.
  • digestCanonicalValue sits under both, for 1,691 ms.

Self time in the 2.6 s file gap:

Code ms Share
javascriptSemanticTraversal.js 805 31%
javascriptSemanticAnalysis.js 370 14%
javascriptSemanticProjection.js 219 8%
garbage collector 159 6%
@babel/parser 147 6%

Your 1,200 file, abort at 200 ms, three runs with the profiler on:

  • The loop stopped for 641, 606 and 607 ms. The abort ping waited 445, 411 and 420 ms.
  • Of those samples, 92 to 94% sit in the parse and project step for index.js.
  • In the ping window, zod takes 21% and canonicalize takes 16%. canonicalDigest.js takes 11%.
  • Over a whole gap, the Babel parser takes about 5%.
  • With no cancel, a second gap of 585 ms follows. That is the app graph build again.

Hermes chunk: one gap of 3,887 ms for its one file. In that gap, zod takes 12% and canonicalDigest.js 11%. Then canonicalize takes 10%, and the Babel parser 3%.

At 300 functions, main's file gap ran from 13 to 206 ms. The app graph gap ran from 206 to 378 ms. On 66863b60 the file gap ran to 233 ms, so a 200 ms abort always landed inside it.

The profiler cost little here. With it, the launcher's longest ping was 4.37 / 4.32 s. Without it, the same was 4.46 / 4.14 s.

Full abort table (median [min–max] of 3 runs, ms)

Times count from the tool call. "Server stop" is REA's own tool-done log line.

Case Client wait Ping after abort Server stop
main, 300, Node 22 202 [201–206] 112.8 [88.7–113.4] 314.3 [290.2–315.9]
main, 300, Node 24 202 [201–203] 156.0 [12.8–158.7] 357.5 [215.3–362.2]
main, 300, Node 26 201 [200–202] 15.7 [13.6–160.1] 217.4 [214.3–360.6]
main, 1,200, Node 22 204 [203–205] 596.8 [561.8–631.4] 802.2 [763.8–833.9]
main, 1,200, Node 24 202 [202–203] 426.8 [386.8–456.7] 629.9 [588.8–658.3]
main, 1,200, Node 26 202 [201–203] 356.3 [352.5–429.6] 558.1 [553.7–632.8]
main, 2,400, Node 22 203 [202–209] 1,160.8 [1,149.3–1,177.7] 1,363.2 [1,354.4–1,380.7]
main, 2,400, Node 24 201 [201–202] 879.3 [869.0–896.1] 1,080.4 [1,070.1–1,097.6]
main, 2,400, Node 26 202 [202–203] 859.3 [824.5–880.5] 1,062.8 [1,026.4–1,084.9]
e09cfe9b, 300 202 [201–202] 29.4 [18.3–39.8] 231.0 [220.0–241.1]
e09cfe9b, 1,200 202 [201–204] 490.5 [470.5–516.9] 692.0 [674.1–719.0]
e09cfe9b, 2,400 202 [202–203] 1,034.9 [1,017.5–1,036.2] 1,237.1 [1,219.5–1,239.3]
66863b60, 300 202 [202–203] 22.5 [18.1–24.5] 224.2 [220.1–226.5]
66863b60, 1,200 202 [202–202] 504.1 [486.7–513.7] 706.5 [688.5–716.1]
66863b60, 2,400 201 [201–202] 1,108.0 [1,097.7–1,110.6] 1,310.5 [1,299.1–1,311.6]
1ec490f3, 300 201 [201–204] 23.2 [20.0–23.8] 224.4 [224.1–224.7]
1ec490f3, 1,200 202 [201–202] 507.3 [497.7–526.1] 709.1 [699.2–727.5]
1ec490f3, 2,400 202 [201–203] 1,080.1 [1,060.7–1,081.3] 1,281.3 [1,262.2–1,283.0]
  • The tree rows ran on Node 24.
  • All 18 cases ran mixed together in each of 3 rounds.
  • No server, child process or temp file was left. The server quit 29 to 57 ms after close.
Real-app details
  • Launcher: app.asar, 26,870,695 bytes, sha256 595810df…5d83ad6f03, format asar.
  • Hermes Desktop: vendor-react-C4pS_tun.js, 258,268 bytes, sha256 8e7a4c3b…0b7f93. It sits alone in a folder, format directory.
  • Full analysis time for the launcher on Node 24 was 39.9 / 38.7 s on main. The older trees took 43.8 to 45.8 s.
  • The server logged ok for every app call. The reply was the typed resource_constraint notice.
  • Launcher Evidence on main: 227,822,770 bytes, ce9edf38…, the same in all 6 runs. On the three older trees it is 245,794,850 bytes, 32d33aa4…, as in my last post.
  • On the launcher, the longest ping went out 22.5 to 27.1 s into the call. It came back when the "Sealing the validated application graph" note came in.
How I measured
  • One stdio MCP session per run, with the SDK 2.3.1 client from the tree under test.
  • Server: node --max-old-space-size=3072 scripts/rea.mjs mcp, or 4,096 for the apps.
  • Abort runs: one ping right after abort(), as in your repro, and no other pings.
  • App runs: a ping every 250 ms, then an Evidence export, a small call and close.
  • Each run used env -i, its own HOME and temp folder, taskset -c 2,3 and nice -n 10.
  • Load is the count of programs that run on, or wait for, one of this box's 24 CPU threads. Linux takes the average over one minute.
  • Before each set I waited for load to drop under 4. It never had to wait. Load was 1.0 to 2.5 at the start of every run.
Commands
git -C rea.git archive cbcba2902dd8caa206d2c5858d73449b87700da0 | tar -x -C main
cd main && npm ci && npm run build
# abort runs
node client.mjs --root main --fixture f1200 --mode at-offset --cancel-ms 200 \
  --ping-ms 0 --retained-check --next-small f3 \
  --server-node-args --max-old-space-size=3072
# app runs
node client.mjs --root main --fixture app.asar --format asar --mode none \
  --ping-ms 250 --ping-timeout-ms 45000 --call-timeout-ms 210000 \
  --export-evidence "$TMPDIR/ev.json" --next-small f3 \
  --server-node-args --max-old-space-size=4096
# profile runs add to the server
--cpu-prof --cpu-prof-dir=prof --import=file:///…/stall-preload.mjs
Test setup
  • Box: Nobara 44 (Fedora 44 base), Linux 7.2.9
  • CPU: AMD Ryzen 9 5900X, 12 cores / 24 threads (runs pinned to 2)
  • RAM: 32 GB DDR4-3600
  • Node: 22.23.1, 24.18.0, 26.11.1 (built on 24.18.0)
  • Head: cbcba290, plus e09cfe9b, 66863b60 and 1ec490f3
  • Other: MCP SDK 2.3.1
  • Other: the Beyond All Reason launcher (MIT)
  • Other: the launcher's Flathub build, which is out under GPL-2.0-or-later
  • Other: Hermes Desktop (MIT)

🤖 Generated with Claude Code (Opus 5.5) 🦊

<!-- gh-comment-id:6095665800 --> @CassieFox23 commented on GitHub (Oct 10, 2026): **TL;DR:** A CPU profile shows where the long app pause sits. On the launcher, the worst block (4.4 to 4.5 s) builds the whole app graph in one go, just after the last file. Main cuts the 1,200-function wait from 507 ms to 427 ms here, and #1444 changes nothing. I tested main `cbcba290` today. Its JavaScript code is the same as in your `7296f2b5`. The asar reader differs, from #1480. The two open-source apps are the [Beyond All Reason launcher](https://flathub.org/apps/info.beyondallreason.bar) ([MIT](https://github.com/beyond-all-reason/spring-launcher/blob/master/LICENSE)) and [Hermes Desktop](https://github.com/NousResearch/hermes-agent) ([MIT](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE)). The launcher's Flathub build is out under [GPL-2.0-or-later](https://github.com/flathub/info.beyondallreason.bar/blob/60445fcc28ede165cd2977a869e29e25da01353b/info.beyondallreason.bar.metainfo.xml#L7), as its own metadata file says. Ping wait after the abort at 200 ms, in ms. Each cell is the median of 3 runs on main. | Functions | Node 22 | Node 24 | Node 26 | | --- | --- | --- | --- | | 300 | 113 | 156 \* | 16 \* | | 1,200 | 597 | 427 | 356 | | 2,400 | 1,161 | 879 | 859 | \* At 300 the runs split in two: 13, 156 and 159 ms on Node 24, then 14, 16 and 160 ms on Node 26. The file block ends close to 200 ms, and a second block of about 170 ms follows. So the wait hangs on which side of that gap the abort lands. - By commit (in a fold below), `1ec490f3` has the same code as `c89c8f53` from my last post. It gives 507 ms now, and 517 ms then. So the drop to 427 ms on main comes from new code, not from the box. I did not bisect #1457, #1458 and #1474. - You saw 595.53 ms on `7296f2b5`. Here main gives 427 ms on Node 24. Last time it was 786 vs 517, so our boxes keep about the same ratio. - All 54 cancels worked as before. No reply was sent for the cancelled call. No Evidence was kept, and the next call and close worked. Longest ping wait in one full app run, in seconds. Each cell shows two runs, with a ping every 250 ms. | App on main | Node 22 | Node 24 | Node 26 | | --- | --- | --- | --- | | Launcher | 5.0 / 5.2 | 4.5 / 4.1 | 4.0 / 3.9 | | Hermes chunk | 4.2 / 4.1 | 3.7 / 3.7 | 3.4 / 3.3 | - My last post said 5.7 / 6.4 s for the launcher, and 5.7 / 5.5 s for Hermes. `1ec490f3` runs that same code. Today it gives 5.2 / 4.8 and 4.2 / 4.2 s, and the launcher Evidence bytes match. So the gap comes from the busier box back then. - No ping failed in any of the 24 app runs. Where the event loop stops, on main with Node 24. A timer in the server logs each gap. The CPU profile shows what runs in it. Times are in seconds, with two launcher runs. | Block | Launcher | Hermes chunk | Your 1,200 file | | --- | --- | --- | --- | | Parse and project one file | 2.6 / 2.5, one file | 3.9 | 0.61 to 0.64 | | Build the app graph | 4.5 / 4.4 | under 0.1 | 0.58, only with no cancel | | Build the semantic graph | 1.6 / 1.5 | 0.37 | under 0.1 | | Seal, check and hash | 0.18 at most | under 0.1 | under 0.1 | - The launcher's worst block is the app graph build. It runs in one go, right after the last file. It is not file parsing. - From the client it looks like parsing, since the note for that step never comes through. REA drops any progress note sent within 100 ms of the one before. - In that block, about 30% of the time makes canonical JSON for IDs. About 30% more goes to zod checks. The parser takes under 1%. - In the file blocks, the Babel parser takes only 3 to 6%. The rest is REA's own work on the tree: walks, ID hashing and zod checks. - You saw the longest pause start in the per-file work. On the launcher, it starts just after the last file. I can't check your app here. ### Still not run - The closed-source app from your report. It is not on this box. - The #1444 head commit `439bc1a5`. - Which of #1457, #1458 or #1474 made main faster. - The older trees on Node 22 and 26. - Profiles on Node 22 and 26. - Windows and macOS. Thanks, N0zoM1z0, for the full-app numbers. They showed me where to point the profiler. <details> <summary>By commit, Node 24</summary> Ping wait after the abort, ms, median of 3: | Functions | `e09cfe9b` | `66863b60`, before #1444 | `1ec490f3`, #1444 | `cbcba290`, main | | --- | --- | --- | --- | --- | | 300 | 29 | 23 | 23 | 156 \* | | 1,200 | 491 | 504 | 507 | 427 | | 2,400 | 1,035 | 1,108 | 1,080 | 879 | Longest ping wait in a full app run, s, two runs: | App on Node 24 | `e09cfe9b` | `66863b60` | `1ec490f3` | `cbcba290` | | --- | --- | --- | --- | --- | | Launcher | 4.9 / 5.6 | 5.1 / 5.2 | 5.2 / 4.8 | 4.5 / 4.1 | | Hermes chunk | 4.3 / 4.3 | 4.4 / 4.4 | 4.2 / 4.2 | 3.7 / 3.7 | </details> <details> <summary>Profile detail</summary> How I measured: - The server ran with `--cpu-prof`, sampling every 1 ms. - A small preload in the server ran a 10 ms timer. It logged each gap over 50 ms. A gap means the event loop did not turn. - The profile, the gap log and the client all use the same clock. I checked that first. - I cut the profile to each gap. Then I split its samples by the REA step on the stack. Measured: gap start and end, ping times, samples per function, and when each progress note came in. Inferred: which REA step a function belongs to, and the file name below. Launcher run 1, gaps over 600 ms, in ms from the call: | Gap | Length | Where the samples are | | --- | --- | --- | | 6,797 to 7,723 | 926 | one file, parse and project | | 12,975 to 15,591 | 2,616 | one file, parse and project | | 18,947 to 19,624 | 676 | one file, parse and project | | 19,711 to 20,516 | 805 | one file, parse and project | | 23,205 to 27,655 | 4,450 | app graph: build 2,576, then clone and check 1,613 | | 27,915 to 29,517 | 1,602 | semantic graph build 1,409 | - Run 2 shows the same shape. Its biggest gaps are 4,385, 2,528 and 1,547 ms. - Run 1 has 88 file gaps over 50 ms, for 14.9 s in all. - The sealing steps yield every 8 ms. They never stopped the loop for more than 177 ms. - Check and hash steps never stopped it for more than 50 ms. - The 2.6 s file is number 896 of 2,027. The asar lists `jimp/browser/lib/jimp.js` (588,235 bytes) at that spot, so I think that is the file. REA did not name it. Self time in the 4.45 s app graph gap: | Code | ms | Share | | --- | --- | --- | | `dist/domain/canonicalDigest.js` | 1,361 | 31% | | `zod/v4/core/schemas.js` | 1,350 | 30% | | native, mostly ID regex checks | 506 | 11% | | `hash` | 323 | 7% | | garbage collector | 247 | 6% | | `@babel/parser` | 1 | 0% | - On the stack: `buildJavaScriptArtifactGraphInput` 2,576 ms. Under it, `addJavaScriptModuleRelationships` takes 1,546 ms, mostly `addExportRelationship`. - `createJavaScriptApplicationGraph` takes 1,613 ms. Its own doc comment says it clones and checks in one go. - `digestCanonicalValue` sits under both, for 1,691 ms. Self time in the 2.6 s file gap: | Code | ms | Share | | --- | --- | --- | | `javascriptSemanticTraversal.js` | 805 | 31% | | `javascriptSemanticAnalysis.js` | 370 | 14% | | `javascriptSemanticProjection.js` | 219 | 8% | | garbage collector | 159 | 6% | | `@babel/parser` | 147 | 6% | Your 1,200 file, abort at 200 ms, three runs with the profiler on: - The loop stopped for 641, 606 and 607 ms. The abort ping waited 445, 411 and 420 ms. - Of those samples, 92 to 94% sit in the parse and project step for `index.js`. - In the ping window, zod takes 21% and `canonicalize` takes 16%. `canonicalDigest.js` takes 11%. - Over a whole gap, the Babel parser takes about 5%. - With no cancel, a second gap of 585 ms follows. That is the app graph build again. Hermes chunk: one gap of 3,887 ms for its one file. In that gap, zod takes 12% and `canonicalDigest.js` 11%. Then `canonicalize` takes 10%, and the Babel parser 3%. At 300 functions, main's file gap ran from 13 to 206 ms. The app graph gap ran from 206 to 378 ms. On `66863b60` the file gap ran to 233 ms, so a 200 ms abort always landed inside it. The profiler cost little here. With it, the launcher's longest ping was 4.37 / 4.32 s. Without it, the same was 4.46 / 4.14 s. </details> <details> <summary>Full abort table (median [min–max] of 3 runs, ms)</summary> Times count from the tool call. "Server stop" is REA's own tool-done log line. | Case | Client wait | Ping after abort | Server stop | | --- | --- | --- | --- | | main, 300, Node 22 | 202 [201–206] | 112.8 [88.7–113.4] | 314.3 [290.2–315.9] | | main, 300, Node 24 | 202 [201–203] | 156.0 [12.8–158.7] | 357.5 [215.3–362.2] | | main, 300, Node 26 | 201 [200–202] | 15.7 [13.6–160.1] | 217.4 [214.3–360.6] | | main, 1,200, Node 22 | 204 [203–205] | 596.8 [561.8–631.4] | 802.2 [763.8–833.9] | | main, 1,200, Node 24 | 202 [202–203] | 426.8 [386.8–456.7] | 629.9 [588.8–658.3] | | main, 1,200, Node 26 | 202 [201–203] | 356.3 [352.5–429.6] | 558.1 [553.7–632.8] | | main, 2,400, Node 22 | 203 [202–209] | 1,160.8 [1,149.3–1,177.7] | 1,363.2 [1,354.4–1,380.7] | | main, 2,400, Node 24 | 201 [201–202] | 879.3 [869.0–896.1] | 1,080.4 [1,070.1–1,097.6] | | main, 2,400, Node 26 | 202 [202–203] | 859.3 [824.5–880.5] | 1,062.8 [1,026.4–1,084.9] | | `e09cfe9b`, 300 | 202 [201–202] | 29.4 [18.3–39.8] | 231.0 [220.0–241.1] | | `e09cfe9b`, 1,200 | 202 [201–204] | 490.5 [470.5–516.9] | 692.0 [674.1–719.0] | | `e09cfe9b`, 2,400 | 202 [202–203] | 1,034.9 [1,017.5–1,036.2] | 1,237.1 [1,219.5–1,239.3] | | `66863b60`, 300 | 202 [202–203] | 22.5 [18.1–24.5] | 224.2 [220.1–226.5] | | `66863b60`, 1,200 | 202 [202–202] | 504.1 [486.7–513.7] | 706.5 [688.5–716.1] | | `66863b60`, 2,400 | 201 [201–202] | 1,108.0 [1,097.7–1,110.6] | 1,310.5 [1,299.1–1,311.6] | | `1ec490f3`, 300 | 201 [201–204] | 23.2 [20.0–23.8] | 224.4 [224.1–224.7] | | `1ec490f3`, 1,200 | 202 [201–202] | 507.3 [497.7–526.1] | 709.1 [699.2–727.5] | | `1ec490f3`, 2,400 | 202 [201–203] | 1,080.1 [1,060.7–1,081.3] | 1,281.3 [1,262.2–1,283.0] | - The tree rows ran on Node 24. - All 18 cases ran mixed together in each of 3 rounds. - No server, child process or temp file was left. The server quit 29 to 57 ms after close. </details> <details> <summary>Real-app details</summary> - Launcher: `app.asar`, 26,870,695 bytes, sha256 `595810df…5d83ad6f03`, format `asar`. - Hermes Desktop: `vendor-react-C4pS_tun.js`, 258,268 bytes, sha256 `8e7a4c3b…0b7f93`. It sits alone in a folder, format `directory`. - Full analysis time for the launcher on Node 24 was 39.9 / 38.7 s on main. The older trees took 43.8 to 45.8 s. - The server logged `ok` for every app call. The reply was the typed `resource_constraint` notice. - Launcher Evidence on main: 227,822,770 bytes, `ce9edf38…`, the same in all 6 runs. On the three older trees it is 245,794,850 bytes, `32d33aa4…`, as in my last post. - On the launcher, the longest ping went out 22.5 to 27.1 s into the call. It came back when the "Sealing the validated application graph" note came in. </details> <details> <summary>How I measured</summary> - One stdio MCP session per run, with the SDK 2.3.1 client from the tree under test. - Server: `node --max-old-space-size=3072 scripts/rea.mjs mcp`, or 4,096 for the apps. - Abort runs: one ping right after `abort()`, as in your repro, and no other pings. - App runs: a ping every 250 ms, then an Evidence export, a small call and close. - Each run used `env -i`, its own HOME and temp folder, `taskset -c 2,3` and `nice -n 10`. - Load is the count of programs that run on, or wait for, one of this box's 24 CPU threads. Linux takes the average over one minute. - Before each set I waited for load to drop under 4. It never had to wait. Load was 1.0 to 2.5 at the start of every run. </details> <details> <summary>Commands</summary> ```sh git -C rea.git archive cbcba2902dd8caa206d2c5858d73449b87700da0 | tar -x -C main cd main && npm ci && npm run build # abort runs node client.mjs --root main --fixture f1200 --mode at-offset --cancel-ms 200 \ --ping-ms 0 --retained-check --next-small f3 \ --server-node-args --max-old-space-size=3072 # app runs node client.mjs --root main --fixture app.asar --format asar --mode none \ --ping-ms 250 --ping-timeout-ms 45000 --call-timeout-ms 210000 \ --export-evidence "$TMPDIR/ev.json" --next-small f3 \ --server-node-args --max-old-space-size=4096 # profile runs add to the server --cpu-prof --cpu-prof-dir=prof --import=file:///…/stall-preload.mjs ``` </details> <details> <summary>Test setup</summary> - Box: Nobara 44 (Fedora 44 base), Linux 7.2.9 - CPU: AMD Ryzen 9 5900X, 12 cores / 24 threads (runs pinned to 2) - RAM: 32 GB DDR4-3600 - Node: 22.23.1, 24.18.0, 26.11.1 (built on 24.18.0) - Head: `cbcba290`, plus `e09cfe9b`, `66863b60` and `1ec490f3` - Other: MCP SDK 2.3.1 - Other: the [Beyond All Reason launcher](https://flathub.org/apps/info.beyondallreason.bar) ([MIT](https://github.com/beyond-all-reason/spring-launcher/blob/master/LICENSE)) - Other: the launcher's Flathub build, which is out under [GPL-2.0-or-later](https://github.com/flathub/info.beyondallreason.bar/blob/60445fcc28ede165cd2977a869e29e25da01353b/info.beyondallreason.bar.metainfo.xml#L7) - Other: [Hermes Desktop](https://github.com/NousResearch/hermes-agent) ([MIT](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE)) </details> 🤖 Generated with Claude Code (Opus 5.5) 🦊
Author
Owner

@N0zoM1z0 commented on GitHub (Oct 10, 2026):

#1525 is now merged as 5fdb0636b4734cabfa3147e8fcc94976c3bd8aa4; this is a measured partial improvement, and #1462 remains open.

Independent paired default-SDK stdio MCP runs on the same full ASAR (SHA-256 97c41bc14fc0ea8c91cd34f502660963dfdf294d5eb35165ccac9d30963069d4) preserved the complete Evidence ID ev_fbe07b5de34746c9191fadb98a2bf6a33d00c9073baa690c75db5c4df3618d98 and passed retained summary/module page/trace, close/expiry, ping and input-identity checks.

Single controlled observation main 46c9cba0 #1525 integrated with that main
Analysis latency 104,791.89 ms 116,486.00 ms
Longest sampled ping wait 30,822.44 ms 9,703.79 ms
Guard peak family RSS 1,728,884,736 B 1,639,112,704 B

Separately, after warming SDK schema preparation and aborting a 1,200-function analysis at 200 ms, the first subsequent ping waited 1,175.40 ms on the control and 131.40 ms on the candidate. Both runs retained no cancelled-analysis Evidence, accepted a later small analysis and closed cleanly.

These are single paired observations, not throughput or percentile claims. Single analyzer stages still run synchronously; the remaining 9.7-second wait rules out calling this a full responsiveness/cancellation fix. A roughly 1.43-second wait also occurred after the last semantic-sealing progress notification; that notification establishes an observed phase marker, not a CPU-stack attribution. Next work must address the remaining blocking stages and validation/normalization, while preserving exact evidence and lifecycle behavior.

An additional bounded-input receiver-expansion failure is tracked separately in #1538, with public CLI/stdio MCP reproduction and a focused fix under verification. It is not the private exit-134 failure in #1387.

<!-- gh-comment-id:6096743168 --> @N0zoM1z0 commented on GitHub (Oct 10, 2026): #1525 is now merged as `5fdb0636b4734cabfa3147e8fcc94976c3bd8aa4`; this is a measured partial improvement, and #1462 remains open. Independent paired default-SDK stdio MCP runs on the same full ASAR (SHA-256 `97c41bc14fc0ea8c91cd34f502660963dfdf294d5eb35165ccac9d30963069d4`) preserved the complete Evidence ID `ev_fbe07b5de34746c9191fadb98a2bf6a33d00c9073baa690c75db5c4df3618d98` and passed retained summary/module page/trace, close/expiry, ping and input-identity checks. | Single controlled observation | main `46c9cba0` | #1525 integrated with that main | |---|---:|---:| | Analysis latency | 104,791.89 ms | 116,486.00 ms | | Longest sampled ping wait | 30,822.44 ms | 9,703.79 ms | | Guard peak family RSS | 1,728,884,736 B | 1,639,112,704 B | Separately, after warming SDK schema preparation and aborting a 1,200-function analysis at 200 ms, the first subsequent ping waited 1,175.40 ms on the control and 131.40 ms on the candidate. Both runs retained no cancelled-analysis Evidence, accepted a later small analysis and closed cleanly. These are single paired observations, not throughput or percentile claims. Single analyzer stages still run synchronously; the remaining 9.7-second wait rules out calling this a full responsiveness/cancellation fix. A roughly 1.43-second wait also occurred after the last semantic-sealing progress notification; that notification establishes an observed phase marker, not a CPU-stack attribution. Next work must address the remaining blocking stages and validation/normalization, while preserving exact evidence and lifecycle behavior. An additional bounded-input receiver-expansion failure is tracked separately in #1538, with public CLI/stdio MCP reproduction and a focused fix under verification. It is not the private exit-134 failure in #1387.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 10, 2026):

Status update from the REA side, on an M-series Mac with Node 26, measured in-process with a 1 ms event-loop gap monitor around reconstructJavaScriptArtifact. Absolute times will differ on your constrained Linux setup; the ratios should carry over.

Merged: #1525.

  • Graph construction and sealing after the last file are now cooperative steps. That covers the app-graph build in CassieFox23's launcher profile (≈4.4 s) and the whole-graph schema parses.
  • Per-file work is split into parse, static analysis, semantic analysis and each projection pass.
  • On the 1,200-function fixture (1c6cafca…7711), the worst ping after abort fell from 286 ms to 56 ms here. N0zoM1z0 independently measured 1,175 ms to 131 ms on the Linux setup.

In review: #1542, for the remaining single-stage blocks on very large files.

  • analyzeParsedJavaScriptSemantics now yields between its phases and its eight derived collectors. On Obsidian's 3.7 MB app.js that stage was one 5.8 s step.
  • Semantic node creation, definitions and references, and the object and frontier projection passes yield every 64 items. The objects pass alone took 1.8 s on app.js.
  • Obsidian obsidian.asar (23 MB): the longest block falls from 5,355 ms to 907 ms, and total time goes from 40.6 s to 39.5 s.
  • Graph IDs and complete result digests are byte-identical to main on five inputs, including that ASAR.

What remains after #1542: blocks of up to about 0.9 s here. Each is a single AST traversal inside one analyzer: member mutations ~1.0 s, fingerprints ~1.0 s, static analysis ~1.0 s and open-receiver classification ~0.6 s on app.js. Splitting those needs a stepwise traverseJavaScriptAst threaded through those collectors, which I'm looking at next.

If you can rerun the Notion ASAR and the Beyond All Reason launcher and Hermes cases on #1542's head, the before/after ping-wait profile would be the most useful confirmation.

<!-- gh-comment-id:6096837109 --> @kaoru0822-kitauji commented on GitHub (Oct 10, 2026): Status update from the REA side, on an M-series Mac with Node 26, measured in-process with a 1 ms event-loop gap monitor around `reconstructJavaScriptArtifact`. Absolute times will differ on your constrained Linux setup; the ratios should carry over. **Merged: #1525.** - Graph construction and sealing after the last file are now cooperative steps. That covers the app-graph build in CassieFox23's launcher profile (≈4.4 s) and the whole-graph schema parses. - Per-file work is split into parse, static analysis, semantic analysis and each projection pass. - On the 1,200-function fixture (`1c6cafca…7711`), the worst ping after abort fell from 286 ms to 56 ms here. N0zoM1z0 independently measured 1,175 ms to 131 ms on the Linux setup. **In review: #1542**, for the remaining single-stage blocks on very large files. - `analyzeParsedJavaScriptSemantics` now yields between its phases and its eight derived collectors. On Obsidian's 3.7 MB `app.js` that stage was one 5.8 s step. - Semantic node creation, definitions and references, and the object and frontier projection passes yield every 64 items. The objects pass alone took 1.8 s on `app.js`. - Obsidian `obsidian.asar` (23 MB): the longest block falls from **5,355 ms to 907 ms**, and total time goes from 40.6 s to 39.5 s. - Graph IDs and complete result digests are byte-identical to `main` on five inputs, including that ASAR. **What remains after #1542:** blocks of up to about 0.9 s here. Each is a single AST traversal inside one analyzer: member mutations ~1.0 s, fingerprints ~1.0 s, static analysis ~1.0 s and open-receiver classification ~0.6 s on `app.js`. Splitting those needs a stepwise `traverseJavaScriptAst` threaded through those collectors, which I'm looking at next. If you can rerun the Notion ASAR and the Beyond All Reason launcher and Hermes cases on #1542's head, the before/after ping-wait profile would be the most useful confirmation.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 10, 2026):

#1542 is merged. The next step, #1545, splits the largest remaining single AST traversals (member mutations with their fixpoint, static source analysis, function fingerprints) using a stepwise traverseJavaScriptAst. Results are unchanged: graph IDs and complete result digests match main.

On Obsidian obsidian.asar against current main (two runs each, M-series Mac):

  • longest event-loop block: 936/911 ms → 758/736 ms;
  • second-longest: 866/862 ms → 599/591 ms;
  • blocks over 250 ms: 28/26 → 19/18;
  • total time: within 1.5%.

Remaining blocks after that are about 0.5–0.75 s: smaller synchronous traversals (definitions, open receivers, references, data-effect helpers), Babel's unsplittable parse, and what look like GC pauses on a heap of about 1.6 GB. Rerunning your constrained Linux probes on #1545's head would show whether those residuals matter on slower hosts.

<!-- gh-comment-id:6097045028 --> @kaoru0822-kitauji commented on GitHub (Oct 10, 2026): #1542 is merged. The next step, #1545, splits the largest remaining single AST traversals (member mutations with their fixpoint, static source analysis, function fingerprints) using a stepwise `traverseJavaScriptAst`. Results are unchanged: graph IDs and complete result digests match `main`. On Obsidian `obsidian.asar` against current `main` (two runs each, M-series Mac): - longest event-loop block: 936/911 ms → 758/736 ms; - second-longest: 866/862 ms → 599/591 ms; - blocks over 250 ms: 28/26 → 19/18; - total time: within 1.5%. Remaining blocks after that are about 0.5–0.75 s: smaller synchronous traversals (definitions, open receivers, references, data-effect helpers), Babel's unsplittable parse, and what look like GC pauses on a heap of about 1.6 GB. Rerunning your constrained Linux probes on #1545's head would show whether those residuals matter on slower hosts.
Author
Owner

@N0zoM1z0 commented on GitHub (Oct 10, 2026):

Independent constrained Linux x64 review of final author head fe5650bd57ccbaf75f8311047e811207695ead42, integrated with main 539a0f95 as 4e507f29:

  • 202 focused tests passed across 8 files: semantic steps, mutation/reference behavior, static member depth, application/composition cancellation, actual CLI SIGINT, SDK MCP cancellation, and public wide-object/array regressions. npm run check:fast passed.
  • 30 complete serialized domain-IR comparisons matched current main, including duplicate static names, trailing computed properties, both spread orders, getters, lexical captures and dynamic selection.
  • Four complete real ASAR SDK stdio MCP workflows, ordered A1/B1/B2/A2, preserved the exact complete Evidence ID ev_fbe07b5de34746c9191fadb98a2bf6a33d00c9073baa690c75db5c4df3618d98 on unchanged input SHA-256 97c41bc14fc0ea8c91cd34f502660963dfdf294d5eb35165ccac9d30963069d4. Each passed retained summary/module-page/feature trace, identity rejection, ping, close and expired-reference checks.
Observation Analysis latency Longest sampled 1-second ping wait
main first 77.33 s 1242.21 ms
candidate first 92.89 s 549.97 ms
candidate repeat 89.71 s 936.30 ms
main repeat 98.19 s 4710.66 ms

Node 24.18.0; CPU affinity 13/15 verified on actual child processes; one heavy lane at a time; each process family remained below the unchanged 2304 MiB budget (peaks 1,829,740,544–1,881,440,256 bytes). These are two observations per revision, not a latency percentile or general throughput claim. The initially apparent 20% slowdown was not stable: the repeated main control was slower than both candidate runs. Candidate control waits stayed under a second in these two runs, while main's observed maximum varied considerably.

Warmed-SDK 1,200-function cancellation at about 200 ms also passed on both revisions: the following ping waited 17.96 ms on main and 36.11 ms on the candidate, cancelled analyses retained zero Evidence, subsequent small analysis and cleanup succeeded. This is correctness/recovery evidence, not an improvement claim for that small cancellation fixture.

This is a useful partial #1462 improvement. Remaining synchronous passes/parsing and unsampled stalls are not ruled out; #1462 should stay open. No real Hopper/Ghidra verification was performed for this JavaScript-only change.

<!-- gh-comment-id:6097475211 --> @N0zoM1z0 commented on GitHub (Oct 10, 2026): Independent constrained Linux x64 review of final author head `fe5650bd57ccbaf75f8311047e811207695ead42`, integrated with main `539a0f95` as `4e507f29`: - 202 focused tests passed across 8 files: semantic steps, mutation/reference behavior, static member depth, application/composition cancellation, actual CLI SIGINT, SDK MCP cancellation, and public wide-object/array regressions. `npm run check:fast` passed. - 30 complete serialized domain-IR comparisons matched current main, including duplicate static names, trailing computed properties, both spread orders, getters, lexical captures and dynamic selection. - Four complete real ASAR SDK stdio MCP workflows, ordered A1/B1/B2/A2, preserved the exact complete Evidence ID `ev_fbe07b5de34746c9191fadb98a2bf6a33d00c9073baa690c75db5c4df3618d98` on unchanged input SHA-256 `97c41bc14fc0ea8c91cd34f502660963dfdf294d5eb35165ccac9d30963069d4`. Each passed retained summary/module-page/feature trace, identity rejection, ping, close and expired-reference checks. | Observation | Analysis latency | Longest sampled 1-second ping wait | |---|---:|---:| | main first | 77.33 s | 1242.21 ms | | candidate first | 92.89 s | 549.97 ms | | candidate repeat | 89.71 s | 936.30 ms | | main repeat | 98.19 s | 4710.66 ms | Node 24.18.0; CPU affinity 13/15 verified on actual child processes; one heavy lane at a time; each process family remained below the unchanged 2304 MiB budget (peaks 1,829,740,544–1,881,440,256 bytes). These are two observations per revision, not a latency percentile or general throughput claim. The initially apparent 20% slowdown was not stable: the repeated main control was slower than both candidate runs. Candidate control waits stayed under a second in these two runs, while main's observed maximum varied considerably. Warmed-SDK 1,200-function cancellation at about 200 ms also passed on both revisions: the following ping waited 17.96 ms on main and 36.11 ms on the candidate, cancelled analyses retained zero Evidence, subsequent small analysis and cleanup succeeded. This is correctness/recovery evidence, not an improvement claim for that small cancellation fixture. This is a useful partial #1462 improvement. Remaining synchronous passes/parsing and unsampled stalls are not ruled out; #1462 should stay open. No real Hopper/Ghidra verification was performed for this JavaScript-only change.
Author
Owner

@N0zoM1z0 commented on GitHub (Oct 10, 2026):

#1557 merged as 8c47a9ce, final head a310f190, all20 checks passed. Definition gathering, open/Electron receiver classification and lexical-reference traversal now yield through the shared analysis checkpoints. Post-current-main integration:162 tests and30 complete-IR digest comparisons passed; real121-file ASAR retains the exact original complete Evidence ID, including typed oversized-response recovery and lifecycle checks. Real warmed SDK cancellation produces zero partial Evidence and allows subsequent analysis/ping/cleanup.

This does not close #1462: parsing and other semantic collectors still have long steps. The separate large public Bun module memory failure has been reproduced on exact merged main and tracked in #1563; adding yield points alone does not provide bounded allocation or containment of a V8 fatal OOM.

<!-- gh-comment-id:6098310428 --> @N0zoM1z0 commented on GitHub (Oct 10, 2026): #1557 merged as `8c47a9ce`, final head `a310f190`, all20 checks passed. Definition gathering, open/Electron receiver classification and lexical-reference traversal now yield through the shared analysis checkpoints. Post-current-main integration:162 tests and30 complete-IR digest comparisons passed; real121-file ASAR retains the exact original complete Evidence ID, including typed oversized-response recovery and lifecycle checks. Real warmed SDK cancellation produces zero partial Evidence and allows subsequent analysis/ping/cleanup. This does not close #1462: parsing and other semantic collectors still have long steps. The separate large public Bun module memory failure has been reproduced on exact merged main and tracked in #1563; adding yield points alone does not provide bounded allocation or containment of a V8 fatal OOM.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#497
No description provided.