Files
rea/docs/verification/javascript-analysis-effects-2026-10-15.md
T
YsopwnableandKaoru0822 e9a71efa31 fix(javascript): declare owned analysis worker effects
Advertise internal worker launches and temporary source writes through the
canonical effects owner so MCP hints and session availability agree with
existing analysis behavior. Preserve non-destructive, idempotent semantics.

Verify public metadata boundaries and a real Obsidian CLI/MCP workflow,
retaining compact reproduction and cost records.

Fixes #3867

Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
2026-10-15 21:36:12 +08:00

5.6 KiB

JavaScript analysis effect metadata verification

Tracks #3867 under #4027. The canonical effect record omitted existing internal worker launches and source staging. CapabilityInventory and SDK registration already consume that owner directly; no adapter override is required. The worker creates a private runtime root, stages .source files and launches an owned REA worker. These are source-derived facts; the analyzed application code is not executed.

Executed results

Public stdio MCP before/after:

Surface Before After
tools/list openWorldHint false true
binary_session effects mutatesSession, idempotent also writesFilesystem, launchesProcess
Session annotation flags idempotent also open_world
Advertised tools 207 207

Regression assertions failed on the original contract: 2 failed, 18 passed. After correction and separating the target-free metadata case, 27 passed across canonical effects, public Electron/JavaScript MCP and SDK-converted catalog validity. The tests retain the non-destructive, idempotent hints and exact session effects; no foreign target execution is declared.

The existing real verifier analyzed official Obsidian 1.14.4 with package.json and main.js selected, then read the typed module references and verified exact public CLI/MCP parity. Both revisions returned the same parent/view Evidence identities and 23-row fact digest. Query replies remained 22,158 bytes and the selected-schema task remained 16,548 cl100k_base BPE tokens (204,093 with the full name/description/inputSchema catalog projection). These are static counts, not model billing; annotations, the separate metadata probe, host rendering/replay, reasoning and final answers are outside this projection. No hosted agent was run.

Complete real verifier Before After
Elapsed seconds 30.470 31.059
CPU seconds 29.939807 30.663163
Peak cgroup bytes 1,551,282,176 1,584,574,464

The scope includes shared analysis, temporary export, CLI parity and tokenizer. The metadata-only probe separately used 10.711/10.909 s wall, 10.503415/10.664997 s CPU and 842,891,264/853,958,656 B peak cgroup memory. All scopes used one CPU, an 8 GiB hard cap, 6 GiB early stop and no swap; cleanup was verified with no OOM. Memory includes charged file cache, not summed RSS. Counters were observed at payload exit while the observer remained alive. Fresh MCP sessions do not establish an OS-cold cache. Shared-host scheduling and filesystem/build warmness were uncontrolled; one pair establishes neither a performance improvement nor an equivalence bound. Linux x64 static ASAR analysis was executed; live Electron and other platforms were not exercised locally. Compact records and source hashes preserve these distinctions without archiving the downloadable application.

Reproduce

Use pinned Node/npm, npm ci, then npm run build:cached. Run the following as an ES module from the checkout root (node --input-type=module < probe.mjs):

import assert from "node:assert/strict";
import { Client } from "@modelcontextprotocol/client";
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
import { toolAvailabilityInventory } from "./dist/contracts/toolOutputSchemaPrimitives.js";
import { closeVerifierResources } from "./scripts/lib/verifier-cleanup.mjs";

const client = new Client({
  name: "javascript-effect-verification",
  version: "1",
});
const transport = new StdioClientTransport({
  command: process.execPath,
  args: ["scripts/rea.mjs", "mcp"],
  stderr: "pipe",
});
let primaryError;
try {
  await client.connect(transport);
  transport.stderr?.resume();
  const { tools } = await client.listTools();
  const tool = tools.find(
    ({ name }) => name === "analyze_javascript_application",
  );
  assert.ok(tool);
  const response = await client.callTool({
    name: "binary_session",
    arguments: {},
  });
  assert.notEqual(response.isError, true);
  const inventory = toolAvailabilityInventory.parse(
    response.structuredContent?.result?.tool_availability,
  );
  const group = inventory.groups.find(({ names }) => names.includes(tool.name));
  assert.ok(group);
  console.log(
    JSON.stringify({
      tool: tool.name,
      advertised_annotations: tool.annotations,
      session_effects: group.effects,
      session_annotations: group.annotations,
      catalog_tool_count: tools.length,
    }),
  );
} catch (cause) {
  primaryError = cause;
  throw cause;
} finally {
  await closeVerifierResources(
    [() => client.close(), () => transport.close()],
    primaryError,
  );
}

For the real workflow, follow the artifact acquisition/digest instructions in module-reference verification. Run its existing command with --mode references --rounds 1 --cli-parity and the same selected source paths and tokenizer. That verifier is unchanged by this fix. The preserved 8 GiB cgroup observer and its source hashes are documented in the same guide. The machine-readable records separate metadata-probe resources from the complete real-workflow resources.