[GH-ISSUE #3352] [Bug] Managed graph projection rejects inspector Evidence with an empty module name #1219

Closed
opened 2026-10-16 21:02:57 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

inspect-managed-members successfully returns authenticated Evidence for a PE/CLI Module metadata row whose name is the empty string. Passing that unmodified Evidence to project-managed-application-graph exits with status 1 and returns invalid_request at observations.0.label. No graph is returned, so the workflow loses the otherwise readable type, method, and field observations.

The ordinary-name control projects successfully with exit status 0 and five nodes: artifact, module, type, method, and field. After the metadata change, inspection still exits with status 0, reports an empty module name, coverage: {"state":"complete","issues":[]}, and one method. The Evidence ID, subject digest, normalized artifact digest, and MVID scope come from fresh inspection after the change; the supplied Evidence is not an edited record with a stale commitment.

Reproduction

  1. Start from a clean checkout of https://github.com/morluto/rea at 8dde6370d0809ad04cda3342d4e6f290f48aa063, using the runtime described below. From the repository root, install the locked dependencies and build the CLI:
npm ci
npm run build:cached
  1. Run this inline script from the repository root. It creates every input file, first records a successful projection control, then sets the Module row's Name index to the string heap's empty entry, obtains fresh Evidence through the production inspector, and projects that exact Evidence. The script isolates the CLI home in sample-home.
node --input-type=module <<'NODE'
import { mkdirSync, writeFileSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
import { buildManagedPeFixture } from './scripts/fixtures/managed/pe.mjs';
mkdirSync('sample-home', { recursive: true });
const run = (...args) => {
  const result = spawnSync(process.execPath, ['scripts/rea.mjs', ...args, '--format', 'json', '--full-output'], {
    encoding: 'utf8', env: { ...process.env, HOME: `${process.cwd()}/sample-home` }
  });
  return { exit: result.status, output: JSON.parse(result.stdout) };
};
const bytes = buildManagedPeFixture({ ilBody: Buffer.from([0x06, 0x2a]) });
writeFileSync('sample.dll', bytes);
const control = run('inspect-managed-members', 'sample.dll').output.data;
writeFileSync('sample-control.json', JSON.stringify({ managed_members: control }));
console.log('control projection exit', run('project-managed-application-graph', 'sample-control.json').exit);
bytes.writeUInt16LE(0, control.normalized_result.module.row_offset + 2);
writeFileSync('sample.dll', bytes);
const inspection = run('inspect-managed-members', 'sample.dll');
const evidence = inspection.output.data;
console.log('inspection', JSON.stringify({ exit: inspection.exit, module_name: evidence.normalized_result.module.name,
  coverage: evidence.normalized_result.coverage, methods: evidence.normalized_result.methods.length }));
writeFileSync('sample-empty.json', JSON.stringify({ managed_members: evidence }));
const projection = run('project-managed-application-graph', 'sample-empty.json');
console.log('projection', JSON.stringify({ exit: projection.exit, error: projection.output.error }));
NODE
  1. Observe that the control projection exits with status 0, inspection of the changed bytes exits with status 0, and projection of the fresh changed-input Evidence exits with status 1 and the nested-label validation error below.

The dependency installation and build commands are clean-checkout preparation instructions. The reported reproduction used the built CLI; it does not establish that those preparation commands were rerun during reproduction.

Expected behavior

src/contracts/managed/managedWorkflowToolContracts.ts:156-163 defines projection of authenticated managed inspection Evidence while preserving managed static observations. src/domain/managed/managedArtifact.ts:33-41 admits the module name as a string without a nonempty restriction. Projection should preserve the readable observations and the original source value, with appropriate uncertainty or malformed-data coverage if needed. A display-label constraint should not reclassify the inspector's accepted Evidence as an invalid caller request or discard all other observations.

The Architecture and Cleanup requirements in AGENTS.md:19 and AGENTS.md:29 require preservation of partial facts, source values, omission, and uncertainty across boundaries, and separation of identity and lookup values from display formatting.

Impact and scope

P2, supported by the reproduced loss of the graph for a complete inspector-produced Evidence record. The graph returns none of the readable type, method, or field observations. The demonstrated trigger is an empty module-name metadata entry; the ordinary-name control remains unaffected. The changed metadata is deliberately unusual, and the reproduction does not establish that a CLR would load it.

A workaround is available: inspect-managed-members remains usable and retains the type, field, and method facts. Callers can inspect that Evidence directly, although graph projection remains unavailable for this input.

REA version

6.4.0 (main at 8dde6370d0)

Runtime and platform

Node.js v26.10.0; macOS 27.0.1; arm64.

Target and artifact context

An ordinary byte-built PE/CLI fixture from the repository-owned scripts/fixtures/managed/pe.mjs, with ilBody: Buffer.from([0x06, 0x2a]). The changed input sets the two-byte Module row Name index at control.normalized_result.module.row_offset + 2 to zero. Both control and changed-input Evidence come from the production inspector. The workflow uses the built CLI without a .NET runtime or external analysis engine.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

The observed control projection exits with status 0 and returns five nodes. The changed-input inspection exits with status 0 and reports:

{"module_name":"","coverage":{"state":"complete","issues":[]},"methods":1}

Projection of the exact fresh Evidence exits with status 1 and returns this error, with no graph:

{
  "code": "invalid_request",
  "category": "invalid_input",
  "details": {
    "operation": "project_managed_application_graph",
    "issues": [{
      "path": [],
      "reason": "invalid_value",
      "message": "A nested value failed validation at observations.0.label: Too small: expected string to have >=1 characters"
    }]
  }
}

Typed outcome or recovery expected

Run the control and changed-input workflows. The changed input must retain a usable graph containing the readable member observations and a truthful representation of the empty or invalid module-name fact, rather than an invalid caller-request error caused by the label. Preserve Evidence authentication and the original name value. Do not obtain success by editing the supplied Evidence without updating its commitment or silently inventing a module name. The ordinary-name control must continue to project successfully.

Analysis or suspected cause

Source-derived reasoning: src/domain/managed/managedApplicationGraphNodes.ts:112-124 passes the source module name into the graph observation label. src/domain/javascript/javascriptApplicationGraphSchemas.ts:81-85 rejects an empty label. Together with the accepted module-name string schema in src/domain/managed/managedArtifact.ts:33-41, these constraints explain why a source value admitted by inspection fails the graph's display-label validation. The CLI reproduction establishes the nested-label failure; this analysis does not establish repaired behavior.

Additional context

  • Related closed issue #861 reports an empty-label schema failure in JavaScript application analysis of a Vite/SheetJS bundle; this report concerns the separate managed-module graph constructor consuming fresh accepted managed Evidence.
  • Related open issue #3201 reports false managed/native module contradictions for missing native identity or an empty ModuleRef import scope; this report concerns the Module row name and graph observation-label validation.
  • Related closed issue #2121 reports empty or repeated caller-supplied --type filters failing managed inspection; this report uses no type filter, successfully completes inspection, and fails during graph projection.
Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3352 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `inspect-managed-members` successfully returns authenticated Evidence for a PE/CLI Module metadata row whose name is the empty string. Passing that unmodified Evidence to `project-managed-application-graph` exits with status 1 and returns `invalid_request` at `observations.0.label`. No graph is returned, so the workflow loses the otherwise readable type, method, and field observations. The ordinary-name control projects successfully with exit status 0 and five nodes: artifact, module, type, method, and field. After the metadata change, inspection still exits with status 0, reports an empty module name, `coverage: {"state":"complete","issues":[]}`, and one method. The Evidence ID, subject digest, normalized artifact digest, and MVID scope come from fresh inspection after the change; the supplied Evidence is not an edited record with a stale commitment. ### Reproduction 1. Start from a clean checkout of `https://github.com/morluto/rea` at `8dde6370d0809ad04cda3342d4e6f290f48aa063`, using the runtime described below. From the repository root, install the locked dependencies and build the CLI: ```sh npm ci npm run build:cached ``` 2. Run this inline script from the repository root. It creates every input file, first records a successful projection control, then sets the Module row's Name index to the string heap's empty entry, obtains fresh Evidence through the production inspector, and projects that exact Evidence. The script isolates the CLI home in `sample-home`. ```sh node --input-type=module <<'NODE' import { mkdirSync, writeFileSync } from 'node:fs'; import { spawnSync } from 'node:child_process'; import { buildManagedPeFixture } from './scripts/fixtures/managed/pe.mjs'; mkdirSync('sample-home', { recursive: true }); const run = (...args) => { const result = spawnSync(process.execPath, ['scripts/rea.mjs', ...args, '--format', 'json', '--full-output'], { encoding: 'utf8', env: { ...process.env, HOME: `${process.cwd()}/sample-home` } }); return { exit: result.status, output: JSON.parse(result.stdout) }; }; const bytes = buildManagedPeFixture({ ilBody: Buffer.from([0x06, 0x2a]) }); writeFileSync('sample.dll', bytes); const control = run('inspect-managed-members', 'sample.dll').output.data; writeFileSync('sample-control.json', JSON.stringify({ managed_members: control })); console.log('control projection exit', run('project-managed-application-graph', 'sample-control.json').exit); bytes.writeUInt16LE(0, control.normalized_result.module.row_offset + 2); writeFileSync('sample.dll', bytes); const inspection = run('inspect-managed-members', 'sample.dll'); const evidence = inspection.output.data; console.log('inspection', JSON.stringify({ exit: inspection.exit, module_name: evidence.normalized_result.module.name, coverage: evidence.normalized_result.coverage, methods: evidence.normalized_result.methods.length })); writeFileSync('sample-empty.json', JSON.stringify({ managed_members: evidence })); const projection = run('project-managed-application-graph', 'sample-empty.json'); console.log('projection', JSON.stringify({ exit: projection.exit, error: projection.output.error })); NODE ``` 3. Observe that the control projection exits with status 0, inspection of the changed bytes exits with status 0, and projection of the fresh changed-input Evidence exits with status 1 and the nested-label validation error below. The dependency installation and build commands are clean-checkout preparation instructions. The reported reproduction used the built CLI; it does not establish that those preparation commands were rerun during reproduction. ### Expected behavior `src/contracts/managed/managedWorkflowToolContracts.ts:156-163` defines projection of authenticated managed inspection Evidence while preserving managed static observations. `src/domain/managed/managedArtifact.ts:33-41` admits the module name as a string without a nonempty restriction. Projection should preserve the readable observations and the original source value, with appropriate uncertainty or malformed-data coverage if needed. A display-label constraint should not reclassify the inspector's accepted Evidence as an invalid caller request or discard all other observations. The Architecture and Cleanup requirements in `AGENTS.md:19` and `AGENTS.md:29` require preservation of partial facts, source values, omission, and uncertainty across boundaries, and separation of identity and lookup values from display formatting. ### Impact and scope P2, supported by the reproduced loss of the graph for a complete inspector-produced Evidence record. The graph returns none of the readable type, method, or field observations. The demonstrated trigger is an empty module-name metadata entry; the ordinary-name control remains unaffected. The changed metadata is deliberately unusual, and the reproduction does not establish that a CLR would load it. A workaround is available: `inspect-managed-members` remains usable and retains the type, field, and method facts. Callers can inspect that Evidence directly, although graph projection remains unavailable for this input. ### REA version 6.4.0 (main at 8dde6370d0809ad04cda3342d4e6f290f48aa063) ### Runtime and platform Node.js v26.10.0; macOS 27.0.1; arm64. ### Target and artifact context An ordinary byte-built PE/CLI fixture from the repository-owned `scripts/fixtures/managed/pe.mjs`, with `ilBody: Buffer.from([0x06, 0x2a])`. The changed input sets the two-byte Module row Name index at `control.normalized_result.module.row_offset + 2` to zero. Both control and changed-input Evidence come from the production inspector. The workflow uses the built CLI without a .NET runtime or external analysis engine. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence The observed control projection exits with status 0 and returns five nodes. The changed-input inspection exits with status 0 and reports: ```text {"module_name":"","coverage":{"state":"complete","issues":[]},"methods":1} ``` Projection of the exact fresh Evidence exits with status 1 and returns this error, with no graph: ```text { "code": "invalid_request", "category": "invalid_input", "details": { "operation": "project_managed_application_graph", "issues": [{ "path": [], "reason": "invalid_value", "message": "A nested value failed validation at observations.0.label: Too small: expected string to have >=1 characters" }] } } ``` ### Typed outcome or recovery expected Run the control and changed-input workflows. The changed input must retain a usable graph containing the readable member observations and a truthful representation of the empty or invalid module-name fact, rather than an invalid caller-request error caused by the label. Preserve Evidence authentication and the original name value. Do not obtain success by editing the supplied Evidence without updating its commitment or silently inventing a module name. The ordinary-name control must continue to project successfully. ### Analysis or suspected cause Source-derived reasoning: `src/domain/managed/managedApplicationGraphNodes.ts:112-124` passes the source module name into the graph observation label. `src/domain/javascript/javascriptApplicationGraphSchemas.ts:81-85` rejects an empty label. Together with the accepted module-name string schema in `src/domain/managed/managedArtifact.ts:33-41`, these constraints explain why a source value admitted by inspection fails the graph's display-label validation. The CLI reproduction establishes the nested-label failure; this analysis does not establish repaired behavior. ### Additional context - Related closed issue [#861](https://github.com/morluto/rea/issues/861) reports an empty-label schema failure in JavaScript application analysis of a Vite/SheetJS bundle; this report concerns the separate managed-module graph constructor consuming fresh accepted managed Evidence. - Related open issue [#3201](https://github.com/morluto/rea/issues/3201) reports false managed/native module contradictions for missing native identity or an empty ModuleRef import scope; this report concerns the Module row name and graph observation-label validation. - Related closed issue [#2121](https://github.com/morluto/rea/issues/2121) reports empty or repeated caller-supplied `--type` filters failing managed inspection; this report uses no type filter, successfully completes inspection, and fails during graph projection.
Author
Owner

@jiatianzhao commented on GitHub (Oct 15, 2026):

I reproduced this on main at 4692bb3: inspection accepts an empty module name, but graph projection rejects the fresh Evidence at observations.0.label. I would like to take this on, preserving the original name and Evidence and adding regression coverage for empty and ordinary names.

<!-- gh-comment-id:6184185547 --> @jiatianzhao commented on GitHub (Oct 15, 2026): I reproduced this on `main` at `4692bb3`: inspection accepts an empty module name, but graph projection rejects the fresh Evidence at `observations.0.label`. I would like to take this on, preserving the original name and Evidence and adding regression coverage for empty and ordinary names.
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#1219
No description provided.