[GH-ISSUE #2746] [Bug] Spread argv arrays produce false exact child-process argument counts #988

Closed
opened 2026-10-15 18:30:09 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @xu91102 on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2746

Observed behavior

On source revision d13c9f840d36a321a56917e75c48afcb8d72920e, the real compiled CLI and production stdio MCP both report argv_count: 1 and a resolved supplies-argv relation with argument_count: 1 for spawn("tool", [...args]). An actual Node child receives two arguments when args = ["a", "b"]. Mixed arrays and fork/execFile are affected too.

Reproduction

  1. Build with the pinned toolchain: npm ci && npm run build:cached.
  2. Put this inert source in fixture/entry.mjs:
import { spawn, execFile, fork } from "node:child_process";
const args = ["a", "b"];
spawn("spread-spawn", [...args]);
execFile("spread-exec", ["prefix", ...args]);
fork("spread-fork", [...args, "suffix"]);
spawn("fixed", ["a", "b"]);
execFile("empty", []);
  1. Run node scripts/rea.mjs analyze-javascript-application ./fixture --format json, or call analyze_javascript_application over production stdio MCP with input_path: "./fixture", format: "directory".
  2. Inspect normalized_result.semantic_graph: spread calls receive exact counts 1/2/2, although these arrays expand to 2/3/3 elements.

The committed regression will exercise both public adapters and first run a test-owned Node child to verify counts [2,3,3,2,0]. Both public cases currently fail with spread-spawn: expected 1 to be null, after the runtime control passed.

Expected behavior

Do not turn AST array-element count into exact runtime argv length when an element is spread. If spread expansion is not statically proved, retain argv_count: null and omit the exact supplies-argv count. Keep literal and empty arrays exact (2 and 0).

Impact and scope

Incorrect resolved argument-count facts can mislead child-process semantic tracing. No target execution, provider, or CLI schema change is needed to correct this. A single spread can expand to zero, one, or many arguments, so counting it as one is unsound.

Runtime and evidence

  • REA source d13c9f840d36a321a56917e75c48afcb8d72920e.
  • Node 24.18.0, TypeScript 7.0.2, macOS arm64.
  • Verified public CLI and production stdio MCP; Node executes only test-owned controls.
  • Suspected source boundary: spawnArgvCount currently returns ArrayExpression.elements.length without checking spread elements. This helper's result is projected as resolved supplies-argv evidence.
  • Searched open/closed issues and PRs for argv counts and spread child arguments; found no existing matching report.
Originally created by @xu91102 on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2746 ### Observed behavior On source revision `d13c9f840d36a321a56917e75c48afcb8d72920e`, the real compiled CLI and production stdio MCP both report `argv_count: 1` and a resolved `supplies-argv` relation with `argument_count: 1` for `spawn("tool", [...args])`. An actual Node child receives two arguments when `args = ["a", "b"]`. Mixed arrays and fork/execFile are affected too. ### Reproduction 1. Build with the pinned toolchain: `npm ci && npm run build:cached`. 2. Put this inert source in `fixture/entry.mjs`: ```js import { spawn, execFile, fork } from "node:child_process"; const args = ["a", "b"]; spawn("spread-spawn", [...args]); execFile("spread-exec", ["prefix", ...args]); fork("spread-fork", [...args, "suffix"]); spawn("fixed", ["a", "b"]); execFile("empty", []); ``` 3. Run `node scripts/rea.mjs analyze-javascript-application ./fixture --format json`, or call `analyze_javascript_application` over production stdio MCP with `input_path: "./fixture", format: "directory"`. 4. Inspect `normalized_result.semantic_graph`: spread calls receive exact counts 1/2/2, although these arrays expand to 2/3/3 elements. The committed regression will exercise both public adapters and first run a test-owned Node child to verify counts `[2,3,3,2,0]`. Both public cases currently fail with `spread-spawn: expected 1 to be null`, after the runtime control passed. ### Expected behavior Do not turn AST array-element count into exact runtime argv length when an element is spread. If spread expansion is not statically proved, retain `argv_count: null` and omit the exact `supplies-argv` count. Keep literal and empty arrays exact (2 and 0). ### Impact and scope Incorrect resolved argument-count facts can mislead child-process semantic tracing. No target execution, provider, or CLI schema change is needed to correct this. A single spread can expand to zero, one, or many arguments, so counting it as one is unsound. ### Runtime and evidence - REA source `d13c9f840d36a321a56917e75c48afcb8d72920e`. - Node 24.18.0, TypeScript 7.0.2, macOS arm64. - Verified public CLI and production stdio MCP; Node executes only test-owned controls. - Suspected source boundary: `spawnArgvCount` currently returns `ArrayExpression.elements.length` without checking spread elements. This helper's result is projected as resolved `supplies-argv` evidence. - Searched open/closed issues and PRs for argv counts and spread child arguments; found no existing matching report.
bsakaguchi 2026-10-15 18:30:09 +00:00
  • closed this issue
  • added the
    bug
    label
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#988
No description provided.