[GH-ISSUE #6061] [Bug] Captured scripts without a mapping are reported as high-confidence unmatched #3704

Closed
opened 2026-10-31 00:43:13 +00:00 by bsakaguchi · 1 comment
Owner

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

Originally assigned to: @kaoru0822-kitauji on GitHub.

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

reconcile-javascript-runtime classifies a captured script as high-confidence unmatched when its location has no automatic or explicit mapping into any supplied static layer and its bytes match no static candidate. The item has basis: "none", reason: "no-static-content-match", and zero candidates. The aggregate summary.unmatched includes it.

The documented matching rule requires missing mappings to remain unknown. In an otherwise identical control, exact captured bytes correctly establish a unique content-only match without a mapping.

Reproduction

Using the source revision below with locked dependencies and its existing compiled runtime, I ran one focused test containing these two cases. It calls the real CLI, obtains static Evidence through the production application analyzer, and supplies synthetic passive Electron Evidence using the repository's existing fixture. It does not start Electron, contact the declared CDP endpoint, or execute the analyzed source.

Save the following as tests/boundary/filesystem/javascript-applications/runtimeMappingFallback.test.ts and run:

node node_modules/vitest/vitest.mjs run tests/boundary/filesystem/javascript-applications/runtimeMappingFallback.test.ts --maxWorkers 1

The assertions characterize the current incorrect classification and the positive control; both passed.

import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import { SOURCE, analyzeFixture, applicationFixture, electronRuntimeEvidence } from "../../../fixtures/javascriptRuntimeReconciliation.js";
import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js";
const run = promisify(execFile);
it.each([false, true])("CLI no-mapping content correspondence: equal=%s", async (equal) => {
  const app = await applicationFixture();
  const live = await createTestTempDirectory("rea-runtime-outside-");
  const request = join(live, "request.json");
  await writeFile(request, JSON.stringify({
    static_layers: [{ role: "application", analysis: await analyzeFixture(app), runtime_mappings: [] }],
    runtime_observations: [electronRuntimeEvidence(live, equal ? SOURCE : "export const unrelated = 17;\n", { includeWorker: false })],
  }));
  const { stdout } = await run(process.execPath, ["scripts/rea.mjs", "reconcile-javascript-runtime", request, "--json"], { maxBuffer: 16 * 1024 * 1024 });
  const evidence = JSON.parse(stdout);
  const result = evidence.normalized_result;
  const item = result.reconciliations.find((v: { entity_kind: string }) => v.entity_kind === "script");
  console.log(JSON.stringify({ equal, operation: evidence.operation, summary: result.summary, item }));
  expect(item).toMatchObject(equal ? { status: "matched", basis: "content-sha256", confidence: "high", reason: "unique-content-match", candidate_static_count: 1 } : { status: "unmatched", basis: "none", confidence: "high", reason: "no-static-content-match", candidate_static_count: 0 });
});

The runtime root is separate from the analyzed application root. The empty runtime_mappings array therefore has no implicit directory-root correspondence either. Merely omitting explicit mappings while keeping the runtime beneath the application would not reproduce this case.

Expected behavior

When captured bytes have no static match and the location has no applicable mapping, return status: "unknown", confidence: "unknown", and reason: "no-authorized-location-mapping"; do not increment the unmatched count for that script. Preserve unique content-only matches, as demonstrated by the equal-bytes control.

Matching rule 6 states that missing authorization mappings remain unknown rather than becoming absence claims. The source-free branch already applies this distinction. A known digest disagreement at a mapped static candidate should retain its separate explicit mismatch behavior.

Impact and scope

P2: accepted reconciliation input produces an unsupported negative correspondence, with high confidence, and repeats it in the summary. This can mislead consumers interpreting supplied static/runtime Evidence. The original Evidence and zero-candidate result remain available for manual cross-checking; no automated workaround preserving the desired typed result was tested.

Observed scope is one out-of-root Electron script with captured bytes and one application layer, plus the equal-bytes control, through the CLI on one platform. No data mutation, security boundary crossing, downstream incident, or real-world frequency was established. Browser and Inspector observations use the same matcher according to source, but were not separately executed.

REA version

6.7.0 source build; revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

macOS 27.0.1 arm64; Node.js v24.18.0; locked Vitest v5.0.3. Existing locked dependencies and compiled runtime; no rebuild was required.

Target and artifact context

The repository's inert JavaScript application fixture contains package.json, index.html, app.js, and worker.js. Synthetic Electron inspection Evidence identifies a script under a separate canonical root. The negative case captures export const unrelated = 17; followed by a newline; the positive control captures the fixture's exact app.js source. Neither case declares a runtime mapping.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

Both CLI calls exited 0. Reduced observed fields:

{
  "different_bytes": {
    "summary": { "matched": 0, "unmatched": 1, "unknown": 2 },
    "script": {
      "status": "unmatched",
      "basis": "none",
      "confidence": "high",
      "reason": "no-static-content-match",
      "candidate_static_count": 0,
      "candidate_static_nodes": [],
      "static_layer_id": null,
      "static_node_id": null
    }
  },
  "equal_bytes_control": {
    "summary": { "matched": 1, "unmatched": 0, "unknown": 2 },
    "script": {
      "status": "matched",
      "basis": "content-sha256",
      "confidence": "high",
      "reason": "unique-content-match",
      "candidate_static_count": 1
    }
  }
}

The two other unknown items are the runtime target and frame; they do not make the script's own negative classification conservative.

Typed outcome or recovery expected

Retain the captured source and location, return an unknown correspondence for the negative case, and keep a unique digest match for the control. No new capture authority or external I/O is needed.

Analysis or suspected cause

Source-derived: reconcileEntity dispatches captured sources before computing the mapping-presence fallback. reconcileCapturedSource returns high-confidence unmatched unconditionally after exhausting location and digest candidates. It receives no layer mapping information with which to distinguish an unmapped script from a mapped script absent from the supplied candidates.

The CLI adapter reaches the shared reconciliation service. MCP uses that same service according to source; MCP transport was not exercised.

Additional context

Related #3316 concerns an alternate digest match hiding a disagreement with a known mapped candidate. This case has no mapped candidate and no digest match. #5884 and closed #3192 concern static load-state absence after incomplete worker coverage or ambiguous correspondence. #5878 concerns encoded URL separators. #5973, #5983, and #5995 concern expression-depth coverage, summary caveat counts, and invalid-UTF-8 semantic gaps. The source-map reports #5469, #5466, #5952, and closed #3217 involve parsing or fetching maps. None requires the zero-mapping captured-source fallback correction described here.

Fetched upstream main at d4c637f4cfcb7ae3b48d0c3047f0e9171d43b26d; the matching, mapping, parsing, service, CLI/MCP registration, and reconciliation-guide files are unchanged from the tested revision. This was a source freshness check, not a runtime execution of that newer revision. No repair or last-known-good version was established.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6061 Originally assigned to: @kaoru0822-kitauji on GitHub. ### 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 `reconcile-javascript-runtime` classifies a captured script as high-confidence `unmatched` when its location has no automatic or explicit mapping into any supplied static layer and its bytes match no static candidate. The item has `basis: "none"`, `reason: "no-static-content-match"`, and zero candidates. The aggregate `summary.unmatched` includes it. The documented matching rule requires missing mappings to remain unknown. In an otherwise identical control, exact captured bytes correctly establish a unique content-only match without a mapping. ### Reproduction Using the source revision below with locked dependencies and its existing compiled runtime, I ran one focused test containing these two cases. It calls the real CLI, obtains static Evidence through the production application analyzer, and supplies synthetic passive Electron Evidence using the repository's existing fixture. It does not start Electron, contact the declared CDP endpoint, or execute the analyzed source. Save the following as `tests/boundary/filesystem/javascript-applications/runtimeMappingFallback.test.ts` and run: ```sh node node_modules/vitest/vitest.mjs run tests/boundary/filesystem/javascript-applications/runtimeMappingFallback.test.ts --maxWorkers 1 ``` The assertions characterize the current incorrect classification and the positive control; both passed. ```ts import { execFile } from "node:child_process"; import { promisify } from "node:util"; import { writeFile } from "node:fs/promises"; import { join } from "node:path"; import { expect, it } from "vitest"; import { SOURCE, analyzeFixture, applicationFixture, electronRuntimeEvidence } from "../../../fixtures/javascriptRuntimeReconciliation.js"; import { createTestTempDirectory } from "../../../fixtures/temporaryDirectory.js"; const run = promisify(execFile); it.each([false, true])("CLI no-mapping content correspondence: equal=%s", async (equal) => { const app = await applicationFixture(); const live = await createTestTempDirectory("rea-runtime-outside-"); const request = join(live, "request.json"); await writeFile(request, JSON.stringify({ static_layers: [{ role: "application", analysis: await analyzeFixture(app), runtime_mappings: [] }], runtime_observations: [electronRuntimeEvidence(live, equal ? SOURCE : "export const unrelated = 17;\n", { includeWorker: false })], })); const { stdout } = await run(process.execPath, ["scripts/rea.mjs", "reconcile-javascript-runtime", request, "--json"], { maxBuffer: 16 * 1024 * 1024 }); const evidence = JSON.parse(stdout); const result = evidence.normalized_result; const item = result.reconciliations.find((v: { entity_kind: string }) => v.entity_kind === "script"); console.log(JSON.stringify({ equal, operation: evidence.operation, summary: result.summary, item })); expect(item).toMatchObject(equal ? { status: "matched", basis: "content-sha256", confidence: "high", reason: "unique-content-match", candidate_static_count: 1 } : { status: "unmatched", basis: "none", confidence: "high", reason: "no-static-content-match", candidate_static_count: 0 }); }); ``` The runtime root is separate from the analyzed application root. The empty `runtime_mappings` array therefore has no implicit directory-root correspondence either. Merely omitting explicit mappings while keeping the runtime beneath the application would not reproduce this case. ### Expected behavior When captured bytes have no static match and the location has no applicable mapping, return `status: "unknown"`, `confidence: "unknown"`, and `reason: "no-authorized-location-mapping"`; do not increment the unmatched count for that script. Preserve unique content-only matches, as demonstrated by the equal-bytes control. [Matching rule 6](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/javascript-runtime-reconciliation.md#L87-L109) states that missing authorization mappings remain unknown rather than becoming absence claims. The [source-free branch](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeReconciliationMatching.ts#L106-L117) already applies this distinction. A known digest disagreement at a mapped static candidate should retain its separate explicit mismatch behavior. ### Impact and scope P2: accepted reconciliation input produces an unsupported negative correspondence, with high confidence, and repeats it in the summary. This can mislead consumers interpreting supplied static/runtime Evidence. The original Evidence and zero-candidate result remain available for manual cross-checking; no automated workaround preserving the desired typed result was tested. Observed scope is one out-of-root Electron script with captured bytes and one application layer, plus the equal-bytes control, through the CLI on one platform. No data mutation, security boundary crossing, downstream incident, or real-world frequency was established. Browser and Inspector observations use the same matcher according to source, but were not separately executed. ### REA version 6.7.0 source build; revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform macOS 27.0.1 arm64; Node.js v24.18.0; locked Vitest v5.0.3. Existing locked dependencies and compiled runtime; no rebuild was required. ### Target and artifact context The repository's inert JavaScript application fixture contains `package.json`, `index.html`, `app.js`, and `worker.js`. Synthetic Electron inspection Evidence identifies a script under a separate canonical root. The negative case captures `export const unrelated = 17;` followed by a newline; the positive control captures the fixture's exact `app.js` source. Neither case declares a runtime mapping. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence Both CLI calls exited 0. Reduced observed fields: ```json { "different_bytes": { "summary": { "matched": 0, "unmatched": 1, "unknown": 2 }, "script": { "status": "unmatched", "basis": "none", "confidence": "high", "reason": "no-static-content-match", "candidate_static_count": 0, "candidate_static_nodes": [], "static_layer_id": null, "static_node_id": null } }, "equal_bytes_control": { "summary": { "matched": 1, "unmatched": 0, "unknown": 2 }, "script": { "status": "matched", "basis": "content-sha256", "confidence": "high", "reason": "unique-content-match", "candidate_static_count": 1 } } } ``` The two other unknown items are the runtime target and frame; they do not make the script's own negative classification conservative. ### Typed outcome or recovery expected Retain the captured source and location, return an unknown correspondence for the negative case, and keep a unique digest match for the control. No new capture authority or external I/O is needed. ### Analysis or suspected cause Source-derived: [reconcileEntity dispatches captured sources before computing the mapping-presence fallback](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeReconciliationMatching.ts#L68-L117). [reconcileCapturedSource returns high-confidence unmatched unconditionally after exhausting location and digest candidates](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeReconciliationMatching.ts#L127-L185). It receives no layer mapping information with which to distinguish an unmapped script from a mapped script absent from the supplied candidates. The [CLI adapter](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/cli/electronCommands.ts#L165-L192) reaches the [shared reconciliation service](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptRuntimeReconciliationService.ts#L20-L83). MCP uses that same service according to source; MCP transport was not exercised. ### Additional context Related #3316 concerns an alternate digest match hiding a disagreement with a known mapped candidate. This case has no mapped candidate and no digest match. #5884 and closed #3192 concern static load-state absence after incomplete worker coverage or ambiguous correspondence. #5878 concerns encoded URL separators. #5973, #5983, and #5995 concern expression-depth coverage, summary caveat counts, and invalid-UTF-8 semantic gaps. The source-map reports #5469, #5466, #5952, and closed #3217 involve parsing or fetching maps. None requires the zero-mapping captured-source fallback correction described here. Fetched upstream main at `d4c637f4cfcb7ae3b48d0c3047f0e9171d43b26d`; the matching, mapping, parsing, service, CLI/MCP registration, and reconciliation-guide files are unchanged from the tested revision. This was a source freshness check, not a runtime execution of that newer revision. No repair or last-known-good version was established.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 22, 2026):

Reproduced on latest main (719d56ebf) at the matcher boundary: an Electron capture with captured bytes export const unrelated = 17;\n at a script under a root with no automatic or explicit mapping into the single application layer (runtime_mappings: []) produced status: "unmatched", confidence: "high", reason: "no-static-content-match", basis: "none", candidate_static_count: 0, via reconcileJavaScriptRuntime in a focused vitest case (npm run test:focused, macOS arm64, Node v26.5.0). The same result appeared with two unmapped layers, and for a URL-located script outside the declared url-prefix mapping.

Source-derived: reconcileCapturedSource in src/domain/javascript/javascriptRuntimeReconciliationMatching.ts returns high-confidence unmatched after exhausting location and digest candidates without knowing whether any layer mapped the location. The source-free branch already makes that distinction. Working on a fix in that classifier.

<!-- gh-comment-id:6331082335 --> @kaoru0822-kitauji commented on GitHub (Oct 22, 2026): Reproduced on latest `main` (719d56ebf) at the matcher boundary: an Electron capture with captured bytes `export const unrelated = 17;\n` at a script under a root with no automatic or explicit mapping into the single application layer (`runtime_mappings: []`) produced `status: "unmatched"`, `confidence: "high"`, `reason: "no-static-content-match"`, `basis: "none"`, `candidate_static_count: 0`, via `reconcileJavaScriptRuntime` in a focused vitest case (`npm run test:focused`, macOS arm64, Node v26.5.0). The same result appeared with two unmapped layers, and for a URL-located script outside the declared `url-prefix` mapping. Source-derived: `reconcileCapturedSource` in `src/domain/javascript/javascriptRuntimeReconciliationMatching.ts` returns high-confidence `unmatched` after exhausting location and digest candidates without knowing whether any layer mapped the location. The source-free branch already makes that distinction. Working on a fix in that classifier.
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#3704
No description provided.