[GH-ISSUE #6670] [Bug] Implicit object coercion leaves stale exported return literals #4048

Closed
opened 2026-10-31 00:46:21 +00:00 by bsakaguchi · 0 comments
Owner

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

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

The production JavaScript artifact analyzer and export-return projection retain state: "literal", value: 1 after computed-key conversion invokes a local object's toString() method and that method writes this.x = 2. Native execution returns 2. Calling the same method explicitly produces the expected conservative unknown. This is an executed source-boundary finding, not a released CLI/provider reproduction.

Reproduction

From the source checkout with the pinned Node runtime and locked dependencies available, run the following shell block. Its body was executed once in the final three-case run and exited zero. Earlier bounded production-boundary probes established the same failure and the variants described below; no fixture was called a minimized reproduction.

node --import ./node_modules/tsx/dist/loader.mjs --input-type=module <<'JS'
import { createHash } from 'node:crypto';
import { analyzeJavaScriptArtifactFiles } from './src/application/javascript/JavaScriptArtifactAnalysis.ts';
import { projectJavaScriptModuleSemantics } from './src/domain/javascript/javascriptModuleSemanticIr.ts';
import { projectJavaScriptExportReturnShapes } from './src/domain/javascript/javascriptExportReturnShapeProjection.ts';
import { completeApplicationCoverage } from './src/domain/javascript/javascriptApplicationEvidenceSchemas.ts';
const cases = {
  coercion: `export function read(){const state={x:1,toString(){this.x=2;return 'key';}};const obj={[state]:0};return state.x;}`,
  no_coercion: `export function read(){const state={x:1,toString(){this.x=2;return 'key';}};return state.x;}`,
  explicit_method: `export function read(){const state={x:1,toString(){this.x=2;return 'key';}};state.toString();return state.x;}`,
};
for (const [name, source] of Object.entries(cases)) {
  const sha = createHash('sha256').update(source).digest('hex');
  const analysis = analyzeJavaScriptArtifactFiles({
    files: [{path:'app.mjs', container_sha256:sha, sha256:sha,
      bytes:Buffer.byteLength(source), inventory_artifact_id:`art_${sha}`,
      kind:'javascript', unpacked:false, text:{included:true, value:source}}],
    containers:[], unavailable_relevant_files:[],
    text_bytes_read:Buffer.byteLength(source), invalid_utf8_files:0,
  });
  const ir = analysis.files[0]?.semantic?.ir;
  if (!ir) throw new Error('Missing semantic IR');
  const module = projectJavaScriptModuleSemantics(ir);
  const link = module.moduleLinks.find(l => l.exportedName === 'read');
  if (!link) throw new Error('Missing read export');
  const projection = projectJavaScriptExportReturnShapes({
    ir:module, link, modulePath:'app.mjs', baseCoverage:completeApplicationCoverage(),
  });
  if (!projection) throw new Error('Missing return projection');
  const shape = projection.properties.static_return_shapes[0];
  const native = Function(source.replace('export ', '') + '; return read();')();
  console.log(JSON.stringify({case:name, parse_failures:analysis.parse_failures,
    semantic_coverage:ir.coverage.status, field:shape.fields[0], native}));
}
JS

The Function call is an independent native-language reference control. REA analyzes the source string without executing it.

Expected behavior

Do not assert that the coercion receiver's old x value remains unchanged after its method is implicitly invoked. Return unknown, or an accurately justified post-call value. The documented contract keeps computed keys uncertain and treats mutable method receivers conservatively; the mutation contract avoids exact interpretation of callee bodies. The explicit-call control demonstrates the existing conservative treatment of this same receiver and method. Making the newly constructed object's key unknown does not establish that the separate coercion receiver stayed unchanged.

Impact and scope

A normal computed-property key produces a wrong retained exported return fact. The additional observed expression const ignored = state + ''; has the same result, so the issue also affects implicit primitive conversion by string concatenation. The no-coercion control returns the correct static/native 1. Real-application prevalence, downstream incidents, other coercion operations and other platforms were not measured.

REA version

Source checkout 5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26, whose package version is 6.7.0. The parent investigation identified rea-agents 6.7.0 as the latest published package; this newer source checkout was tested, not the published package.

Runtime and platform

Node.js v24.22.1; Linux x86_64; repository lockfile dependencies. No external analysis provider was started or mocked.

Target and artifact context

A self-authored JavaScript module supplied as decoded app.mjs text to the production artifact-analysis boundary. A separate native-JavaScript reference control executes only the small self-contained fixture.

Interface

Other

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Selected final-run output, with the unchanged field keys retained:

{"case":"coercion","parse_failures":0,"semantic_coverage":"complete","field":{"path":"","presence":"present","state":"literal","value":1,"reason":null},"native":2}
{"case":"no_coercion","parse_failures":0,"semantic_coverage":"complete","field":{"path":"","presence":"present","state":"literal","value":1,"reason":null},"native":1}
{"case":"explicit_method","parse_failures":0,"semantic_coverage":"complete","field":{"path":"","presence":"present","state":"unknown","value":null,"reason":"Own property x is unknown-coverage."},"native":2}

An earlier executed probe replaced const obj = {[state]:0}; with const ignored = state + ''; and likewise observed static literal 1 versus native 2. Both forms invoke conversion on the same local object; no prototype replacement or external dependency is involved. Complete coverage here describes retained syntax, not proof of runtime execution.

  • Expected source: The documented mutable-receiver/uncertain-computed-key contracts linked above and the executed explicit-method control.
  • Failure source: Executed analyzeJavaScriptArtifactFiles, module retention and projectJavaScriptExportReturnShapes calls shown inline; the projected field is the actual observed contrary result.
  • Evidence provenance: observed.
  • Local verification: reproduced.
  • Reproduction completeness: complete at the production analysis/projection boundary.

Public-path reachability was checked in source: the CLI registration accepts an ordinary readable directory; the shared service calls reconstruction; its source worker uses the same parser/semantic pass; and module relationships consume the same export-return projection. The inline file has a supported extension, valid UTF-8/module syntax and an exact exported-callable link, with no imports or source selection exclusions. This establishes applicability under normal successful worker/resource admission. CLI/MCP transport, the isolated worker and the released package were not executed.

Typed outcome or recovery expected

The computed-key and concatenation fixtures should stop publishing literal 1; unknown is sufficient without evaluating the conversion method. Preserve the no-coercion control's known 1 and the explicit-call control's uncertainty. This is a proposed restoration check; no fix was implemented.

Analysis or suspected cause

Source-derived: the mutation traversal records explicit invocation and tagged-template receiver exposure. Computed-key and operator conversion do not pass through those explicit invocation branches, leaving the conversion receiver's old literal available to return projection. This is a likely missing exposure boundary, not a request to execute arbitrary conversion methods or recover exact post-call values.

Additional context

The full 1,043-entry open-issue snapshot was reread before drafting. Fresh open/closed searches covered ToPrimitive, toString titles, coercion with stale/literal returns, implicit calls and accessor reports; no matching report was found. #3952 concerns structural-fingerprint literal retention, not coercion receiver mutation. Getter invocation is independently reachable without primitive conversion; a correction confined to getter reads would leave this fixture unchanged. NOT_ENOUGH_INFO: introducing revision, last known good release or released-package behavior.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: Valid bounded source yields an obsolete literal in exported return evidence after implicit method invocation; production parsing/projection and a discriminating explicit-call control were observed, with no severe downstream incident demonstrated.
  • Workaround status: unverified
  • Workaround basis: Explicitly calling the conversion method changes the analyzed artifact and is only a control. No practical route preserving an unchanged original artifact was verified.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6670 ## 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 The production JavaScript artifact analyzer and export-return projection retain `state: "literal", value: 1` after computed-key conversion invokes a local object's `toString()` method and that method writes `this.x = 2`. Native execution returns `2`. Calling the same method explicitly produces the expected conservative unknown. This is an executed source-boundary finding, not a released CLI/provider reproduction. ## Reproduction From the source checkout with the pinned Node runtime and locked dependencies available, run the following shell block. Its body was executed once in the final three-case run and exited zero. Earlier bounded production-boundary probes established the same failure and the variants described below; no fixture was called a minimized reproduction. ```sh node --import ./node_modules/tsx/dist/loader.mjs --input-type=module <<'JS' import { createHash } from 'node:crypto'; import { analyzeJavaScriptArtifactFiles } from './src/application/javascript/JavaScriptArtifactAnalysis.ts'; import { projectJavaScriptModuleSemantics } from './src/domain/javascript/javascriptModuleSemanticIr.ts'; import { projectJavaScriptExportReturnShapes } from './src/domain/javascript/javascriptExportReturnShapeProjection.ts'; import { completeApplicationCoverage } from './src/domain/javascript/javascriptApplicationEvidenceSchemas.ts'; const cases = { coercion: `export function read(){const state={x:1,toString(){this.x=2;return 'key';}};const obj={[state]:0};return state.x;}`, no_coercion: `export function read(){const state={x:1,toString(){this.x=2;return 'key';}};return state.x;}`, explicit_method: `export function read(){const state={x:1,toString(){this.x=2;return 'key';}};state.toString();return state.x;}`, }; for (const [name, source] of Object.entries(cases)) { const sha = createHash('sha256').update(source).digest('hex'); const analysis = analyzeJavaScriptArtifactFiles({ files: [{path:'app.mjs', container_sha256:sha, sha256:sha, bytes:Buffer.byteLength(source), inventory_artifact_id:`art_${sha}`, kind:'javascript', unpacked:false, text:{included:true, value:source}}], containers:[], unavailable_relevant_files:[], text_bytes_read:Buffer.byteLength(source), invalid_utf8_files:0, }); const ir = analysis.files[0]?.semantic?.ir; if (!ir) throw new Error('Missing semantic IR'); const module = projectJavaScriptModuleSemantics(ir); const link = module.moduleLinks.find(l => l.exportedName === 'read'); if (!link) throw new Error('Missing read export'); const projection = projectJavaScriptExportReturnShapes({ ir:module, link, modulePath:'app.mjs', baseCoverage:completeApplicationCoverage(), }); if (!projection) throw new Error('Missing return projection'); const shape = projection.properties.static_return_shapes[0]; const native = Function(source.replace('export ', '') + '; return read();')(); console.log(JSON.stringify({case:name, parse_failures:analysis.parse_failures, semantic_coverage:ir.coverage.status, field:shape.fields[0], native})); } JS ``` The `Function` call is an independent native-language reference control. REA analyzes the source string without executing it. ## Expected behavior Do not assert that the coercion receiver's old `x` value remains unchanged after its method is implicitly invoked. Return unknown, or an accurately justified post-call value. [The documented contract](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/docs/javascript-application-workflows.md#L368-L391) keeps computed keys uncertain and treats mutable method receivers conservatively; [the mutation contract](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/docs/javascript-application-workflows.md#L214-L221) avoids exact interpretation of callee bodies. The explicit-call control demonstrates the existing conservative treatment of this same receiver and method. Making the newly constructed object's key unknown does not establish that the separate coercion receiver stayed unchanged. ## Impact and scope A normal computed-property key produces a wrong retained exported return fact. The additional observed expression `const ignored = state + '';` has the same result, so the issue also affects implicit primitive conversion by string concatenation. The no-coercion control returns the correct static/native `1`. Real-application prevalence, downstream incidents, other coercion operations and other platforms were not measured. ## REA version Source checkout `5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26`, whose package version is 6.7.0. The parent investigation identified rea-agents 6.7.0 as the latest published package; this newer source checkout was tested, not the published package. ## Runtime and platform Node.js v24.22.1; Linux x86_64; repository lockfile dependencies. No external analysis provider was started or mocked. ## Target and artifact context A self-authored JavaScript module supplied as decoded `app.mjs` text to the production artifact-analysis boundary. A separate native-JavaScript reference control executes only the small self-contained fixture. ## Interface Other ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Selected final-run output, with the unchanged field keys retained: ```json {"case":"coercion","parse_failures":0,"semantic_coverage":"complete","field":{"path":"","presence":"present","state":"literal","value":1,"reason":null},"native":2} {"case":"no_coercion","parse_failures":0,"semantic_coverage":"complete","field":{"path":"","presence":"present","state":"literal","value":1,"reason":null},"native":1} {"case":"explicit_method","parse_failures":0,"semantic_coverage":"complete","field":{"path":"","presence":"present","state":"unknown","value":null,"reason":"Own property x is unknown-coverage."},"native":2} ``` An earlier executed probe replaced `const obj = {[state]:0};` with `const ignored = state + '';` and likewise observed static literal `1` versus native `2`. Both forms invoke conversion on the same local object; no prototype replacement or external dependency is involved. Complete coverage here describes retained syntax, not proof of runtime execution. - Expected source: The documented mutable-receiver/uncertain-computed-key contracts linked above and the executed explicit-method control. - Failure source: Executed `analyzeJavaScriptArtifactFiles`, module retention and `projectJavaScriptExportReturnShapes` calls shown inline; the projected field is the actual observed contrary result. - Evidence provenance: observed. - Local verification: reproduced. - Reproduction completeness: complete at the production analysis/projection boundary. Public-path reachability was checked in source: the [CLI registration](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/src/cli/electronCommands.ts#L302-L338) accepts an ordinary readable directory; the [shared service](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/src/application/javascript/JavaScriptApplicationService.ts#L41-L86) calls reconstruction; its [source worker](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/src/composition/javascriptAnalysisWorkerProcess.ts#L25-L54) uses the same parser/semantic pass; and [module relationships](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/src/application/javascript/JavaScriptModuleRelationships.ts#L156-L193) consume the same export-return projection. The inline file has a supported extension, valid UTF-8/module syntax and an exact exported-callable link, with no imports or source selection exclusions. This establishes applicability under normal successful worker/resource admission. CLI/MCP transport, the isolated worker and the released package were not executed. ## Typed outcome or recovery expected The computed-key and concatenation fixtures should stop publishing literal `1`; unknown is sufficient without evaluating the conversion method. Preserve the no-coercion control's known `1` and the explicit-call control's uncertainty. This is a proposed restoration check; no fix was implemented. ## Analysis or suspected cause Source-derived: [the mutation traversal](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/src/domain/javascript/javascriptSemanticMemberMutations.ts#L879-L923) records explicit invocation and tagged-template receiver exposure. Computed-key and operator conversion do not pass through those explicit invocation branches, leaving the conversion receiver's old literal available to [return projection](https://github.com/morluto/rea/blob/5a5bcb6b549cfdfba6dd3f02dd681e505ffd2a26/src/domain/javascript/javascriptExportReturnShapeProjection.ts#L90-L103). This is a likely missing exposure boundary, not a request to execute arbitrary conversion methods or recover exact post-call values. ## Additional context The full 1,043-entry open-issue snapshot was reread before drafting. Fresh open/closed searches covered `ToPrimitive`, `toString` titles, coercion with stale/literal returns, implicit calls and accessor reports; no matching report was found. [#3952](https://github.com/morluto/rea/issues/3952) concerns structural-fingerprint literal retention, not coercion receiver mutation. Getter invocation is independently reachable without primitive conversion; a correction confined to getter reads would leave this fixture unchanged. NOT_ENOUGH_INFO: introducing revision, last known good release or released-package behavior. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: Valid bounded source yields an obsolete literal in exported return evidence after implicit method invocation; production parsing/projection and a discriminating explicit-call control were observed, with no severe downstream incident demonstrated. - Workaround status: unverified - Workaround basis: Explicitly calling the conversion method changes the analyzed artifact and is only a control. No practical route preserving an unchanged original artifact was verified.
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#4048
No description provided.