[GH-ISSUE #5973] [Bug] Provenance-only expression-depth limits are missing from application coverage #3642

Closed
opened 2026-10-31 00:42:38 +00:00 by bsakaguchi · 0 comments
Owner

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

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

analyze-javascript-application reports complete application coverage without an expression-depth limit for a source whose binding provenance hits the documented 256-level budget. A direct call to the production semantic analyzer confirms that the bound was reached: the binding's provenance is unknown with an expression-depth reason, while its source-local IR coverage is still complete with no resource-limit classification.

The public CLI succeeds with zero parse failures, complete graph.coverage, and empty limit lists. Its separate semantic_graph.coverage.status is unknown because assignment values are independently unsupported; this report does not claim that field is complete. The public result omits the depth-limit reason and classification.

Reproduction

Using the revision below with its existing locked dependencies and built runtime, I ran this script from the repository root with REPRO_DIR set to a disposable absolute directory. It executes two real CLI analyses and directly reads the production semantic IR for the same source. No analyzed JavaScript executes and no external provider is required.

import assert from 'node:assert/strict';
import { execFileSync } from 'node:child_process';
import { mkdirSync, writeFileSync } from 'node:fs';
import { join, resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
const load = p => import(pathToFileURL(resolve('dist', p)));
const { analyzeJavaScriptSemantics } = await load('domain/javascript/javascriptSemanticAnalysis.js');
assert(process.env.REPRO_DIR, 'Set REPRO_DIR to a disposable absolute directory.');
for (const count of [10, 300]) {
  const source = 'const deep = ' + 'a = '.repeat(count) + '"x";\n';
  const ir = analyzeJavaScriptSemantics(source);
  const binding = ir.bindings.find(b => b.name === 'deep');
  assert(binding);
  assert.equal(ir.coverage.status, 'complete');
  assert.deepEqual(ir.coverage.resourceLimits ?? [], []);
  if (count === 300) {
    assert.equal(binding.provenance.status, 'unknown');
    assert.match(binding.provenance.reason, /expression depth budget exceeded/i);
  } else assert.equal(binding.provenance.status, 'local');
  const root = join(process.env.REPRO_DIR, `depth-${count}`);
  mkdirSync(root, { recursive: true });
  writeFileSync(join(root, 'app.js'), source);
  const stdout = execFileSync(process.execPath,
    ['scripts/rea.mjs', 'analyze-javascript-application', root, '--json'],
    { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'] });
  const result = JSON.parse(stdout).normalized_result;
  assert.equal(result.statistics.parse_failures, 0);
  assert.equal(result.graph.coverage.status, 'complete');
  assert.deepEqual(result.graph.coverage.limits, []);
  assert.equal(JSON.stringify(result).includes('javascript_semantic_expression_depth'), false);
  console.log(JSON.stringify({count, provenance: binding.provenance,
    ir_coverage: ir.coverage, application_coverage: result.graph.coverage,
    semantic_graph_status: result.semantic_graph.coverage.status,
    semantic_graph_limits: result.semantic_graph.coverage.limits}));
}

The assertions describe the current incorrect coverage and the below-bound control. Both cases completed successfully. The 300-assignment case is ordinary parsed source, not a manually constructed AST. The script itself was replayed after the initial reproduction.

Expected behavior

When provenance reaches the expression-depth bound, record the encountered typed resource limit independently of whether value evaluation already reports an unsupported expression. Source-local IR coverage should become partial with an unknown omission extent and expression-depth classification. Public application coverage and graph evidence should preserve the encountered javascript_semantic_expression_depth limit and its diagnosis/location.

This is the explicit resource-bound contract. The coverage owner already maps an encountered expression-depth limit to partial coverage and the public limit name. The existing unsupported-assignment unknown can remain unknown.

Impact and scope

P2: an encountered analysis bound disappears from coverage and diagnostics for a bounded class of valid source inputs. Consumers cannot distinguish this provenance budget exhaustion from the shallower unsupported-expression control using the public limit lists, and the application graph claims complete coverage despite the documented omitted work.

The demonstrated scope is a 300-level assignment initializer. A 10-level control does not hit the provenance limit. Broader syntax, downstream classification loss, and real-application frequency were not measured. Original source and a generic unsupported-value unknown remain available; no automatic equivalent-output workaround was tested. No target mutation or security boundary crossing occurred.

REA version

6.7.0 source build; revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

macOS 27.0.1 arm64; Node.js v26.12.0. Used the existing locked dependencies and built runtime. The development pin, Node.js 24.18.0, was not exercised.

Target and artifact context

Two inert local application directories, each containing only app.js. The file declares const deep = followed by 10 or 300 repetitions of a = and the string literal "x". Both source files parse successfully. Runtime execution of these assignments is irrelevant to the static analysis.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Reduced output from the executed reproduction:

{"count":10,"provenance":{"status":"local","origins":[],"reason":null},"ir_coverage":{"status":"complete","omittedCount":0},"application_coverage":{"status":"complete","truncated":false,"omitted_count":0,"limits":[]},"semantic_graph_status":"unknown","semantic_graph_limits":[]}
{"count":300,"provenance":{"status":"unknown","origins":[],"reason":"Semantic expression depth budget exceeded (maximum 256 nested expressions)."},"ir_coverage":{"status":"complete","omittedCount":0},"application_coverage":{"status":"complete","truncated":false,"omitted_count":0,"limits":[]},"semantic_graph_status":"unknown","semantic_graph_limits":[]}

The deep public result contains neither javascript_semantic_expression_depth nor the depth-budget reason. Its retained value unknown describes Unsupported AssignmentExpression value. instead. The direct semantic-IR observation establishes that a separate provenance bound was encountered.

Typed outcome or recovery expected

Preserve a typed expression-depth limit, partial source-local/application coverage with an unknown omitted extent, and graph evidence identifying the affected source expression. Keep unrelated facts and the shallower control intact. Reporting another generic unknown without the limiting classification does not satisfy the documented bound contract.

Analysis or suspected cause

Source-derived explanation: the two provenance depth guards return an unresolved provenance value containing only a reason string. Assignments recurse through their right-hand sides, so the sample reaches that guard even though ordinary value evaluation stops at the unsupported assignment expression.

By contrast, value evaluation records tagged resource limits. The IR coverage calculation consumes the recorded value/getter limit sets, and application graph coverage reads those IR classifications. The provenance-only boundary never enters that recorded state. No repair was applied or tested.

Additional context

Related reports #2576 and #5904 concern validation of inconsistent incoming semantic graphs; #3370 concerns obligation-ledger projection. This case originates in ordinary source analysis before any imported graph or ledger operation. PR #1941 concerns closure-alias evaluation cost, and PR #3848 concerns getter expansion rather than this provenance guard.

Upstream main was fetched at 25e1a24a3ed3671a0148757555f18d16c29d936a. The relevant evaluator, coverage and projection code and the resource-bound contract are unchanged from the tested revision. This is a source freshness check, not a runtime execution of that newer revision. No last-known-good revision was established. MCP transport was not exercised.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5973 ### 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 `analyze-javascript-application` reports complete application coverage without an expression-depth limit for a source whose binding provenance hits the documented 256-level budget. A direct call to the production semantic analyzer confirms that the bound was reached: the binding's provenance is unknown with an expression-depth reason, while its source-local IR coverage is still complete with no resource-limit classification. The public CLI succeeds with zero parse failures, complete `graph.coverage`, and empty limit lists. Its separate `semantic_graph.coverage.status` is `unknown` because assignment values are independently unsupported; this report does not claim that field is complete. The public result omits the depth-limit reason and classification. ### Reproduction Using the revision below with its existing locked dependencies and built runtime, I ran this script from the repository root with `REPRO_DIR` set to a disposable absolute directory. It executes two real CLI analyses and directly reads the production semantic IR for the same source. No analyzed JavaScript executes and no external provider is required. ```js import assert from 'node:assert/strict'; import { execFileSync } from 'node:child_process'; import { mkdirSync, writeFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { pathToFileURL } from 'node:url'; const load = p => import(pathToFileURL(resolve('dist', p))); const { analyzeJavaScriptSemantics } = await load('domain/javascript/javascriptSemanticAnalysis.js'); assert(process.env.REPRO_DIR, 'Set REPRO_DIR to a disposable absolute directory.'); for (const count of [10, 300]) { const source = 'const deep = ' + 'a = '.repeat(count) + '"x";\n'; const ir = analyzeJavaScriptSemantics(source); const binding = ir.bindings.find(b => b.name === 'deep'); assert(binding); assert.equal(ir.coverage.status, 'complete'); assert.deepEqual(ir.coverage.resourceLimits ?? [], []); if (count === 300) { assert.equal(binding.provenance.status, 'unknown'); assert.match(binding.provenance.reason, /expression depth budget exceeded/i); } else assert.equal(binding.provenance.status, 'local'); const root = join(process.env.REPRO_DIR, `depth-${count}`); mkdirSync(root, { recursive: true }); writeFileSync(join(root, 'app.js'), source); const stdout = execFileSync(process.execPath, ['scripts/rea.mjs', 'analyze-javascript-application', root, '--json'], { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024, stdio: ['ignore', 'pipe', 'pipe'] }); const result = JSON.parse(stdout).normalized_result; assert.equal(result.statistics.parse_failures, 0); assert.equal(result.graph.coverage.status, 'complete'); assert.deepEqual(result.graph.coverage.limits, []); assert.equal(JSON.stringify(result).includes('javascript_semantic_expression_depth'), false); console.log(JSON.stringify({count, provenance: binding.provenance, ir_coverage: ir.coverage, application_coverage: result.graph.coverage, semantic_graph_status: result.semantic_graph.coverage.status, semantic_graph_limits: result.semantic_graph.coverage.limits})); } ``` The assertions describe the current incorrect coverage and the below-bound control. Both cases completed successfully. The 300-assignment case is ordinary parsed source, not a manually constructed AST. The script itself was replayed after the initial reproduction. ### Expected behavior When provenance reaches the expression-depth bound, record the encountered typed resource limit independently of whether value evaluation already reports an unsupported expression. Source-local IR coverage should become partial with an unknown omission extent and `expression-depth` classification. Public application coverage and graph evidence should preserve the encountered `javascript_semantic_expression_depth` limit and its diagnosis/location. This is the explicit [resource-bound contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/javascript-artifact-reconstruction.md#L515-L524). The [coverage owner](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptSemanticCoverage.ts#L45-L108) already maps an encountered expression-depth limit to partial coverage and the public limit name. The existing unsupported-assignment unknown can remain unknown. ### Impact and scope P2: an encountered analysis bound disappears from coverage and diagnostics for a bounded class of valid source inputs. Consumers cannot distinguish this provenance budget exhaustion from the shallower unsupported-expression control using the public limit lists, and the application graph claims complete coverage despite the documented omitted work. The demonstrated scope is a 300-level assignment initializer. A 10-level control does not hit the provenance limit. Broader syntax, downstream classification loss, and real-application frequency were not measured. Original source and a generic unsupported-value unknown remain available; no automatic equivalent-output workaround was tested. No target mutation or security boundary crossing occurred. ### REA version 6.7.0 source build; revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform macOS 27.0.1 arm64; Node.js v26.12.0. Used the existing locked dependencies and built runtime. The development pin, Node.js 24.18.0, was not exercised. ### Target and artifact context Two inert local application directories, each containing only `app.js`. The file declares `const deep = ` followed by 10 or 300 repetitions of `a = ` and the string literal `"x"`. Both source files parse successfully. Runtime execution of these assignments is irrelevant to the static analysis. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Reduced output from the executed reproduction: ```json {"count":10,"provenance":{"status":"local","origins":[],"reason":null},"ir_coverage":{"status":"complete","omittedCount":0},"application_coverage":{"status":"complete","truncated":false,"omitted_count":0,"limits":[]},"semantic_graph_status":"unknown","semantic_graph_limits":[]} {"count":300,"provenance":{"status":"unknown","origins":[],"reason":"Semantic expression depth budget exceeded (maximum 256 nested expressions)."},"ir_coverage":{"status":"complete","omittedCount":0},"application_coverage":{"status":"complete","truncated":false,"omitted_count":0,"limits":[]},"semantic_graph_status":"unknown","semantic_graph_limits":[]} ``` The deep public result contains neither `javascript_semantic_expression_depth` nor the depth-budget reason. Its retained value unknown describes `Unsupported AssignmentExpression value.` instead. The direct semantic-IR observation establishes that a separate provenance bound was encountered. ### Typed outcome or recovery expected Preserve a typed expression-depth limit, partial source-local/application coverage with an unknown omitted extent, and graph evidence identifying the affected source expression. Keep unrelated facts and the shallower control intact. Reporting another generic unknown without the limiting classification does not satisfy the documented bound contract. ### Analysis or suspected cause Source-derived explanation: the two [provenance depth guards](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptSemanticValues.ts#L1139-L1161) return an unresolved provenance value containing only a reason string. [Assignments recurse through their right-hand sides](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptSemanticValues.ts#L1167-L1177), so the sample reaches that guard even though ordinary value evaluation stops at the unsupported assignment expression. By contrast, [value evaluation records tagged resource limits](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptSemanticValues.ts#L619-L641). The [IR coverage calculation](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/javascript/javascriptSemanticAnalysis.ts#L429-L439) consumes the recorded value/getter limit sets, and [application graph coverage](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/javascript/JavaScriptArtifactGraphBuilder.ts#L300-L310) reads those IR classifications. The provenance-only boundary never enters that recorded state. No repair was applied or tested. ### Additional context Related reports #2576 and #5904 concern validation of inconsistent incoming semantic graphs; #3370 concerns obligation-ledger projection. This case originates in ordinary source analysis before any imported graph or ledger operation. PR #1941 concerns closure-alias evaluation cost, and PR #3848 concerns getter expansion rather than this provenance guard. Upstream main was fetched at `25e1a24a3ed3671a0148757555f18d16c29d936a`. The relevant evaluator, coverage and projection code and the resource-bound contract are unchanged from the tested revision. This is a source freshness check, not a runtime execution of that newer revision. No last-known-good revision was established. MCP transport was not exercised.
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#3642
No description provided.