[GH-ISSUE #2587] fix(scripts): launch Hopper verifier CLI from encoded checkout names #906

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

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

Summary

The real-Hopper verification lane passes an encoded URL pathname as a filesystem script path. In a checkout directory containing a space or non-ASCII character, Node cannot find the CLI dispatcher, so the lane cannot perform its CLI/MCP parity checks. This failure is established from the launch path in source and a neutral path-conversion probe; the full real-Hopper lane was not executed.

Steps to reproduce

For the full supported workflow, place the checkout in a directory named rea checkout, supply a supported Hopper installation and the lane's required fixture/build artifacts, and run node scripts/verify-real-hopper.mjs. Allow its valid-provider and fixture checks to reach the lifecycle/CLI block. These full-provider steps were not run locally.

The following standalone boundary probe was run with Node.js. It creates a harmless dispatcher in a space-containing directory and uses the same URL conversion and process-launch operation as the verifier.

import { execFileSync } from 'node:child_process';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { pathToFileURL, fileURLToPath } from 'node:url';
const fixture = mkdtempSync(join(tmpdir(), 'dispatcher space '));
try {
  mkdirSync(join(fixture, 'scripts', 'lib'), { recursive: true });
  writeFileSync(join(fixture, 'scripts', 'rea.mjs'), "console.log('dispatcher reached');\n");
  const moduleUrl = pathToFileURL(join(fixture, 'scripts', 'lib', 'real-hopper-boundaries.mjs'));
  const dispatcher = new URL('../rea.mjs', moduleUrl);
  for (const [label, path] of [['pathname', dispatcher.pathname], ['filesystem', fileURLToPath(dispatcher)]]) {
    try {
      const output = execFileSync(process.execPath, [path], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
      console.log(label, output.trim());
    } catch (error) {
      console.log(label, 'exit', error.status, 'module missing', String(error.stderr).includes('MODULE_NOT_FOUND'));
    }
  }
} finally {
  rmSync(fixture, { recursive: true, force: true });
}

Expected behavior

The lane must launch its dispatcher using the checkout's actual filesystem path so a valid checkout name does not prevent the promised CLI/MCP verification. Supported macOS and Linux checkout names containing spaces or non-ASCII characters should receive the same verification as ordinary names.

Actual behavior

The source passes percent-encoded path characters unchanged to Node. The neutral probe observed exit 1 with MODULE_NOT_FOUND for space, hash and non-ASCII directory names, while decoded-path controls reached the dispatcher. Both representations worked for a plain directory name. Full-lane failure is established from source, not a real-Hopper run: the macOS CLI parity launch has no decoding guard, and Linux supplies the same path to its earlier launch-isolation check.

Evidence

  • Expected source: AGENTS.md, Architecture and Cleanup, distinguishes filesystem paths from file URLs; scripts/verify-real-hopper.mjs:495-502 invokes the supported lifecycle/CLI verification; scripts/lib/real-ghidra-entry-aliases.mjs:20 converts a fixture source URL to the filesystem path passed to its compiler.
  • Failure source: scripts/lib/real-hopper-boundaries.mjs:345 and :371 use URL.pathname, then :318-325 and :380 launch it unchanged; scripts/lib/real-hopper-session-isolation.mjs:17-28 consumes the earlier Linux value unchanged.
  • Evidence provenance: static
  • Local verification: static-proof
  • Reproduction completeness: complete

Runtime reproduction of the real-Hopper lane was not run. Reachability requires successful normal provider/fixture checks, which do not restrict or decode checkout names. The lane then invokes the affected CLI calls with the computed pathname. The neutral process-launch probe separately confirms the filesystem consequence of that exact conversion.

Related closed, unmerged PR #2113 explicitly excludes this verifier file from its similar test-helper path corrections. It supplies context rather than evidence of restoration here.

Restoration check

From a space-containing checkout, the lane must reach its CLI parity and Linux launch-isolation assertions without a script-resolution failure. Preserve the same assertions in a plain checkout. At the neutral boundary, both checkout names must reach the dispatcher when represented as filesystem paths; an intentionally encoded pathname control must continue demonstrating why the representations differ.

Runtime or environment

Source baseline 8b181716ac, Node.js 26.10.0 on macOS for the neutral probe. The full lane requires a supported real Hopper host and existing fixture/build artifacts; no real-provider result is claimed.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Valid checkout names prevent a real-provider verification lane from launching its CLI subprocesses. Product analysis behavior is not shown to fail, and real-provider execution was not measured locally.
  • Workaround status: available
  • Workaround basis: Running the checkout from a plain filesystem directory avoids the encoded-name condition; both pathname and filesystem-path controls launched from such a directory in the neutral probe.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2587 ## Summary The real-Hopper verification lane passes an encoded URL pathname as a filesystem script path. In a checkout directory containing a space or non-ASCII character, Node cannot find the CLI dispatcher, so the lane cannot perform its CLI/MCP parity checks. This failure is established from the launch path in source and a neutral path-conversion probe; the full real-Hopper lane was not executed. ## Steps to reproduce For the full supported workflow, place the checkout in a directory named `rea checkout`, supply a supported Hopper installation and the lane's required fixture/build artifacts, and run `node scripts/verify-real-hopper.mjs`. Allow its valid-provider and fixture checks to reach the lifecycle/CLI block. These full-provider steps were not run locally. The following standalone boundary probe was run with Node.js. It creates a harmless dispatcher in a space-containing directory and uses the same URL conversion and process-launch operation as the verifier. ```javascript import { execFileSync } from 'node:child_process'; import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { pathToFileURL, fileURLToPath } from 'node:url'; const fixture = mkdtempSync(join(tmpdir(), 'dispatcher space ')); try { mkdirSync(join(fixture, 'scripts', 'lib'), { recursive: true }); writeFileSync(join(fixture, 'scripts', 'rea.mjs'), "console.log('dispatcher reached');\n"); const moduleUrl = pathToFileURL(join(fixture, 'scripts', 'lib', 'real-hopper-boundaries.mjs')); const dispatcher = new URL('../rea.mjs', moduleUrl); for (const [label, path] of [['pathname', dispatcher.pathname], ['filesystem', fileURLToPath(dispatcher)]]) { try { const output = execFileSync(process.execPath, [path], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); console.log(label, output.trim()); } catch (error) { console.log(label, 'exit', error.status, 'module missing', String(error.stderr).includes('MODULE_NOT_FOUND')); } } } finally { rmSync(fixture, { recursive: true, force: true }); } ``` ## Expected behavior The lane must launch its dispatcher using the checkout's actual filesystem path so a valid checkout name does not prevent the promised CLI/MCP verification. Supported macOS and Linux checkout names containing spaces or non-ASCII characters should receive the same verification as ordinary names. ## Actual behavior The source passes percent-encoded path characters unchanged to Node. The neutral probe observed exit 1 with MODULE_NOT_FOUND for space, hash and non-ASCII directory names, while decoded-path controls reached the dispatcher. Both representations worked for a plain directory name. Full-lane failure is established from source, not a real-Hopper run: the macOS CLI parity launch has no decoding guard, and Linux supplies the same path to its earlier launch-isolation check. ## Evidence - Expected source: AGENTS.md, Architecture and Cleanup, distinguishes filesystem paths from file URLs; scripts/verify-real-hopper.mjs:495-502 invokes the supported lifecycle/CLI verification; scripts/lib/real-ghidra-entry-aliases.mjs:20 converts a fixture source URL to the filesystem path passed to its compiler. - Failure source: scripts/lib/real-hopper-boundaries.mjs:345 and :371 use URL.pathname, then :318-325 and :380 launch it unchanged; scripts/lib/real-hopper-session-isolation.mjs:17-28 consumes the earlier Linux value unchanged. - Evidence provenance: static - Local verification: static-proof - Reproduction completeness: complete Runtime reproduction of the real-Hopper lane was not run. Reachability requires successful normal provider/fixture checks, which do not restrict or decode checkout names. The lane then invokes the affected CLI calls with the computed pathname. The neutral process-launch probe separately confirms the filesystem consequence of that exact conversion. Related closed, unmerged PR [#2113](https://github.com/morluto/rea/pull/2113) explicitly excludes this verifier file from its similar test-helper path corrections. It supplies context rather than evidence of restoration here. ## Restoration check From a space-containing checkout, the lane must reach its CLI parity and Linux launch-isolation assertions without a script-resolution failure. Preserve the same assertions in a plain checkout. At the neutral boundary, both checkout names must reach the dispatcher when represented as filesystem paths; an intentionally encoded pathname control must continue demonstrating why the representations differ. ## Runtime or environment Source baseline 8b181716aca2cb467be499cba226abfb5ae19141, Node.js 26.10.0 on macOS for the neutral probe. The full lane requires a supported real Hopper host and existing fixture/build artifacts; no real-provider result is claimed. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Valid checkout names prevent a real-provider verification lane from launching its CLI subprocesses. Product analysis behavior is not shown to fail, and real-provider execution was not measured locally. - Workaround status: available - Workaround basis: Running the checkout from a plain filesystem directory avoids the encoded-name condition; both pathname and filesystem-path controls launched from such a directory in the neutral probe.
bsakaguchi 2026-10-15 18:29:27 +00:00
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#906
No description provided.