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>
122 lines
5.6 KiB
Markdown
122 lines
5.6 KiB
Markdown
# 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](../../src/javascript/analysis/JavaScriptAnalysisWorker.ts) 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](javascript-analysis-effects-2026-10-15.json)
|
|
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`):
|
|
|
|
```javascript
|
|
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](javascript-module-references-2026-10-15.md).
|
|
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.
|