[GH-ISSUE #5884] [Bug] Runtime reconciliation reports worker assets absent when worker inventory is unavailable #3565

Closed
opened 2026-10-31 00:41:55 +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/5884

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

rea reconcile-javascript-runtime INPUT --json assigns worker.js the static load state not-observed-in-capture when the supplied Electron inspection explicitly reports unavailable_sections: ["workers"]. The same result reports partial coverage and an unknown graph omission count. The worker asset is counted in summary.static_not_observed despite the missing worker inventory.

I reproduced this using synthetic Electron inspection Evidence and the built public CLI. A complete-capture control returned the same absence state. A control marking scripts unavailable instead correctly returned unknown for the same asset and zero static absence states.

Reproduction

The checkout already had installed dependencies and built artifacts. I ran one temporary focused Vitest test, using the repository's fixture to analyze a local application directory containing index.html, app.js, and worker.js. app.js declares new Worker(new URL("./worker.js", import.meta.url)). The test constructed synthetic Electron inspection Evidence without a worker entry and passed it to the real CLI. No live Electron instance or CDP endpoint was contacted.

To rerun, use the revision below with locked dependencies and built artifacts, save this test as tests/boundary/process/runtimeLoadStateWorkers.test.ts, and run:

node node_modules/vitest/vitest.mjs run tests/boundary/process/runtimeLoadStateWorkers.test.ts --maxWorkers 1

The assertions describe the current behavior; a passing test confirms the incorrect workers-unavailable result alongside the controls. This was one successful run containing three CLI calls.

import { execFile } from "node:child_process";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { promisify } from "node:util";
import { expect, it } from "vitest";
import { SOURCE, applicationFixture, analyzeFixture, electronRuntimeEvidence } from "../../fixtures/javascriptRuntimeReconciliation.js";

it("observes CLI load-state behavior for complete and incomplete worker coverage", async () => {
  const root = await applicationFixture();
  const analysis = await analyzeFixture(root);
  const graph = analysis.normalized_result.graph;
  expect(graph.coverage.status).toBe("complete");
  const worker = graph.nodes.find((node: any) => node.kind === "javascript-asset" && node.observations.some((o: any) => o.label === "worker.js" || o.evidence.location.value?.path === "worker.js"));
  expect(worker).toBeDefined();
  const execute = promisify(execFile);
  for (const [name, options] of [
    ["complete", {}],
    ["workers-unavailable", { workersUnavailable: true }],
    ["scripts-unavailable", { scriptsUnavailable: true }],
  ] as const) {
    const inputPath = join(root, `${name}.json`);
    await writeFile(inputPath, JSON.stringify({
      static_layers: [{ role: "application", analysis, runtime_mappings: [{ kind: "file-root", root, artifact_prefix: "" }] }],
      runtime_observations: [electronRuntimeEvidence(root, SOURCE, { includeWorker: false, ...options })],
    }));
    const { stdout } = await execute(process.execPath, ["scripts/rea.mjs", "reconcile-javascript-runtime", inputPath, "--json"], { maxBuffer: 16 * 1024 * 1024 });
    const evidence = JSON.parse(stdout);
    expect(evidence.operation).toBe("reconcile_javascript_runtime");
    const result = evidence.normalized_result;
    const state = result.static_load_states.find((s: any) => s.static_node_id === worker!.node_id);
    console.log(JSON.stringify({ name, worker_state: state, summary: result.summary, coverage: result.coverage, graph_coverage: result.graph.coverage, runtime_capture: result.runtime_captures[0] }));
    expect(state).toMatchObject(name === "scripts-unavailable" ? {
      status: "unknown", reason: "static-or-runtime-coverage-incomplete"
    } : {
      status: "not-observed-in-capture", reason: "not-observed-in-bounded-capture"
    });
    if (name === "workers-unavailable") {
      expect(result.coverage.status).toBe("partial");
      expect(result.graph.coverage.omitted_count).toBeNull();
      expect(result.summary.static_not_observed).toBeGreaterThan(0);
    }
  }
}, 30000);

Expected behavior

When workers could not be inventoried, a missing worker asset should remain unknown, with static-or-runtime-coverage-incomplete, rather than contributing to the definite static_not_observed count. Accepted positive script matches can remain loaded.

The matching and load-state contract requires incomplete coverage to remain unknown and limits not-observed-in-capture to complete authorized captures. The existing scripts-unavailable regression exercises the corresponding uncertainty rule for script collection.

Impact and scope

P2: callers receive a definite bounded absence classification for a worker asset when the capture could not enumerate workers. This can mislead static/runtime analysis, and the aggregate absence count repeats the unsupported classification. The observed scope is Electron inspection Evidence with unavailable workers and otherwise complete script collection.

The original Evidence and partial coverage remain available. A practical workaround is to inspect the retained capture completeness and treat absence states as unknown when worker coverage is unavailable. This does not require changing the analyzed files or discarding captured observations. Other unavailable sections and platforms were not tested. No security boundary crossing was observed.

REA version

6.7.0; source revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

macOS 27.0.1 arm64; Node.js v26.12.0; Vitest 5.0.3. The exact development pin, Node.js 24.18.0, was not exercised.

Target and artifact context

A local JavaScript application fixture with a page script and separate worker asset. Runtime input is synthetic, schema-valid passive Electron inspection Evidence built with the repository's Evidence constructors. Its scripts array contains app.js; its workers array is empty. Only the collection-completeness options change between the three cases.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

Selected fields observed from the three successful CLI calls:

complete:
  worker.js status: not-observed-in-capture
  worker.js reason: not-observed-in-bounded-capture
  scripts_complete_within_scope: true
  coverage.status: complete-within-inputs
  graph.coverage.status: complete
  graph.coverage.omitted_count: 0
  summary.static_not_observed: 2

workers-unavailable:
  worker.js status: not-observed-in-capture
  worker.js reason: not-observed-in-bounded-capture
  scripts_complete_within_scope: true
  coverage.status: partial
  graph.coverage.status: partial
  graph.coverage.omitted_count: null
  summary.static_not_observed: 2

scripts-unavailable:
  worker.js status: unknown
  worker.js reason: static-or-runtime-coverage-incomplete
  scripts_complete_within_scope: false
  coverage.status: partial
  graph.coverage.status: partial
  graph.coverage.omitted_count: null
  summary.static_not_observed: 0

The focused test passed once. That establishes the CLI projection for these simulated capture inputs; it does not establish how often a live Electron instance loses worker enumeration.

Typed outcome or recovery expected

For the workers-unavailable case, retain partial coverage and any accepted positive matches. Keep the unobserved worker asset unknown and exclude it from definite absence counts. Preserve the complete-capture and scripts-unavailable controls.

Analysis or suspected cause

Source-derived explanation: parseElectronCapture assigns scriptsCompleteWithinScope using scriptsComplete, which checks only script truncation, script unavailability, and dropped script events. The load-state classifier uses that predicate as its capture-completeness gate for all mapped code nodes.

The input is reachable through normal producer behavior: Electron worker collection explicitly marks workers unavailable when its optional enumeration command is unavailable. Meanwhile, graph coverage retains uncertainty from that marker. The load-state projection loses it.

Additional context

Related issue #3192 concerns ambiguous static candidates with complete captures, and #3378/#3379 concern malformed inventories at capture admission. This case starts with an explicit, retained workers-unavailable marker and loses its meaning during reconciliation.

Open PR #2068 adds a worker-discovery completeness check to browser capture parsing. Its patch leaves Electron capture parsing unchanged, so it does not address the Electron case above. The relevant baseline source and documentation were unchanged when compared with main at 5eebe2fdf87915dc3e4c604ad6945668dd1c6c50.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5884 ### 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 `rea reconcile-javascript-runtime INPUT --json` assigns `worker.js` the static load state `not-observed-in-capture` when the supplied Electron inspection explicitly reports `unavailable_sections: ["workers"]`. The same result reports partial coverage and an unknown graph omission count. The worker asset is counted in `summary.static_not_observed` despite the missing worker inventory. I reproduced this using synthetic Electron inspection Evidence and the built public CLI. A complete-capture control returned the same absence state. A control marking scripts unavailable instead correctly returned `unknown` for the same asset and zero static absence states. ### Reproduction The checkout already had installed dependencies and built artifacts. I ran one temporary focused Vitest test, using the repository's fixture to analyze a local application directory containing `index.html`, `app.js`, and `worker.js`. `app.js` declares `new Worker(new URL("./worker.js", import.meta.url))`. The test constructed synthetic Electron inspection Evidence without a worker entry and passed it to the real CLI. No live Electron instance or CDP endpoint was contacted. To rerun, use the revision below with locked dependencies and built artifacts, save this test as `tests/boundary/process/runtimeLoadStateWorkers.test.ts`, and run: ```sh node node_modules/vitest/vitest.mjs run tests/boundary/process/runtimeLoadStateWorkers.test.ts --maxWorkers 1 ``` The assertions describe the current behavior; a passing test confirms the incorrect workers-unavailable result alongside the controls. This was one successful run containing three CLI calls. ```ts import { execFile } from "node:child_process"; import { writeFile } from "node:fs/promises"; import { join } from "node:path"; import { promisify } from "node:util"; import { expect, it } from "vitest"; import { SOURCE, applicationFixture, analyzeFixture, electronRuntimeEvidence } from "../../fixtures/javascriptRuntimeReconciliation.js"; it("observes CLI load-state behavior for complete and incomplete worker coverage", async () => { const root = await applicationFixture(); const analysis = await analyzeFixture(root); const graph = analysis.normalized_result.graph; expect(graph.coverage.status).toBe("complete"); const worker = graph.nodes.find((node: any) => node.kind === "javascript-asset" && node.observations.some((o: any) => o.label === "worker.js" || o.evidence.location.value?.path === "worker.js")); expect(worker).toBeDefined(); const execute = promisify(execFile); for (const [name, options] of [ ["complete", {}], ["workers-unavailable", { workersUnavailable: true }], ["scripts-unavailable", { scriptsUnavailable: true }], ] as const) { const inputPath = join(root, `${name}.json`); await writeFile(inputPath, JSON.stringify({ static_layers: [{ role: "application", analysis, runtime_mappings: [{ kind: "file-root", root, artifact_prefix: "" }] }], runtime_observations: [electronRuntimeEvidence(root, SOURCE, { includeWorker: false, ...options })], })); const { stdout } = await execute(process.execPath, ["scripts/rea.mjs", "reconcile-javascript-runtime", inputPath, "--json"], { maxBuffer: 16 * 1024 * 1024 }); const evidence = JSON.parse(stdout); expect(evidence.operation).toBe("reconcile_javascript_runtime"); const result = evidence.normalized_result; const state = result.static_load_states.find((s: any) => s.static_node_id === worker!.node_id); console.log(JSON.stringify({ name, worker_state: state, summary: result.summary, coverage: result.coverage, graph_coverage: result.graph.coverage, runtime_capture: result.runtime_captures[0] })); expect(state).toMatchObject(name === "scripts-unavailable" ? { status: "unknown", reason: "static-or-runtime-coverage-incomplete" } : { status: "not-observed-in-capture", reason: "not-observed-in-bounded-capture" }); if (name === "workers-unavailable") { expect(result.coverage.status).toBe("partial"); expect(result.graph.coverage.omitted_count).toBeNull(); expect(result.summary.static_not_observed).toBeGreaterThan(0); } } }, 30000); ``` ### Expected behavior When workers could not be inventoried, a missing worker asset should remain `unknown`, with `static-or-runtime-coverage-incomplete`, rather than contributing to the definite `static_not_observed` count. Accepted positive script matches can remain loaded. The [matching and load-state contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/javascript-runtime-reconciliation.md#L109-L134) requires incomplete coverage to remain unknown and limits `not-observed-in-capture` to complete authorized captures. The existing [scripts-unavailable regression](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/tests/boundary/filesystem/javascript-applications/javascriptRuntimeReconciliation.test.ts#L194-L225) exercises the corresponding uncertainty rule for script collection. ### Impact and scope P2: callers receive a definite bounded absence classification for a worker asset when the capture could not enumerate workers. This can mislead static/runtime analysis, and the aggregate absence count repeats the unsupported classification. The observed scope is Electron inspection Evidence with unavailable workers and otherwise complete script collection. The original Evidence and partial coverage remain available. A practical workaround is to inspect the retained capture completeness and treat absence states as unknown when worker coverage is unavailable. This does not require changing the analyzed files or discarding captured observations. Other unavailable sections and platforms were not tested. No security boundary crossing was observed. ### REA version 6.7.0; source revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform macOS 27.0.1 arm64; Node.js v26.12.0; Vitest 5.0.3. The exact development pin, Node.js 24.18.0, was not exercised. ### Target and artifact context A local JavaScript application fixture with a page script and separate worker asset. Runtime input is synthetic, schema-valid passive Electron inspection Evidence built with the repository's Evidence constructors. Its scripts array contains `app.js`; its workers array is empty. Only the collection-completeness options change between the three cases. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence Selected fields observed from the three successful CLI calls: ```text complete: worker.js status: not-observed-in-capture worker.js reason: not-observed-in-bounded-capture scripts_complete_within_scope: true coverage.status: complete-within-inputs graph.coverage.status: complete graph.coverage.omitted_count: 0 summary.static_not_observed: 2 workers-unavailable: worker.js status: not-observed-in-capture worker.js reason: not-observed-in-bounded-capture scripts_complete_within_scope: true coverage.status: partial graph.coverage.status: partial graph.coverage.omitted_count: null summary.static_not_observed: 2 scripts-unavailable: worker.js status: unknown worker.js reason: static-or-runtime-coverage-incomplete scripts_complete_within_scope: false coverage.status: partial graph.coverage.status: partial graph.coverage.omitted_count: null summary.static_not_observed: 0 ``` The focused test passed once. That establishes the CLI projection for these simulated capture inputs; it does not establish how often a live Electron instance loses worker enumeration. ### Typed outcome or recovery expected For the workers-unavailable case, retain partial coverage and any accepted positive matches. Keep the unobserved worker asset unknown and exclude it from definite absence counts. Preserve the complete-capture and scripts-unavailable controls. ### Analysis or suspected cause Source-derived explanation: [parseElectronCapture](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.ts#L208-L247) assigns `scriptsCompleteWithinScope` using [scriptsComplete](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.ts#L504-L511), which checks only script truncation, script unavailability, and dropped script events. The [load-state classifier](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeLoadState.ts#L65-L108) uses that predicate as its capture-completeness gate for all mapped code nodes. The input is reachable through normal producer behavior: [Electron worker collection](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/browser/CdpElectronWorkers.ts#L24-L36) explicitly marks workers unavailable when its optional enumeration command is unavailable. Meanwhile, [graph coverage](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptRuntimeReconciliationGraph.ts#L139-L150) retains uncertainty from that marker. The load-state projection loses it. ### Additional context Related issue #3192 concerns ambiguous static candidates with complete captures, and #3378/#3379 concern malformed inventories at capture admission. This case starts with an explicit, retained workers-unavailable marker and loses its meaning during reconciliation. Open PR #2068 adds a worker-discovery completeness check to browser capture parsing. Its patch leaves Electron capture parsing unchanged, so it does not address the Electron case above. The relevant baseline source and documentation were unchanged when compared with main at `5eebe2fdf87915dc3e4c604ad6945668dd1c6c50`.
Author
Owner

@morluto commented on GitHub (Oct 23, 2026):

Fixed in 209c42c34. Runtime reconciliation preserves positive script matches while unavailable worker inventory keeps unmatched worker load states unknown and excludes them from static_not_observed. Complete-worker control still permits absence. Verified by tests/boundary/filesystem/javascript-applications/javascriptRuntimeReconciliation.test.ts. Verification used synthetic retained capture Evidence through the production application service; no live browser capture is claimed.

<!-- gh-comment-id:6376076950 --> @morluto commented on GitHub (Oct 23, 2026): Fixed in [209c42c34](https://github.com/morluto/rea/commit/209c42c34689252d402a8737459fe6ca00f82d4b). Runtime reconciliation preserves positive script matches while unavailable worker inventory keeps unmatched worker load states unknown and excludes them from static_not_observed. Complete-worker control still permits absence. Verified by `tests/boundary/filesystem/javascript-applications/javascriptRuntimeReconciliation.test.ts`. Verification used synthetic retained capture Evidence through the production application service; no live browser capture is claimed.
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#3565
No description provided.