[GH-ISSUE #4210] [Bug] Mixed named and unknown reference targets report an unsupported change #1653

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

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

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

compare_functions reports references: changed when one recorded target has a procedure name and the other has unknown cross-artifact identity, even though no known reference kind or named target differs. The same false endpoint-change conclusion occurs for one artifact when both records identify the exact same target address and only one supplies a procedure record. The first result also becomes a definite fail in verify_reconstruction; the all-unnamed control remains unknown in both tools.

Reproduction

Use the source revision under REA version and the repository's pinned development toolchain. From the checkout root, install the locked dependencies if necessary and build the runtime:

npm ci
npm run build:cached

Run this complete fixture from the checkout root. It supplies complete inline analyze_function Evidence to the registered tool on a fresh session, with available reference facets and complete relationship coverage. The target names, addresses and artifact digests are inert recorded metadata; no corresponding binary file is needed. The fixture checks both reported cases and controls, prints the relevant statuses and closes its MCP connection.

node --input-type=module <<'JS'
import assert from 'node:assert/strict';
import { mkdtemp, mkdir, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { Client } from '@modelcontextprotocol/client';
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
import { createEvidence, parseEvidence } from './dist/domain/evidence.js';
import { functionDossierSchema } from './dist/domain/hopperValues.js';
import { FUNCTION_COMPARISON_EXAMPLE } from './dist/contracts/functionComparisonExample.js';
const kind = { available: true, provenance: 'ghidra-reference-manager', type: 'READ', flow: false, call: false, jump: false, data: true, read: true, write: false, indirect: false, computed: false, conditional: false, terminal: false, primary: true, operand_index: 0, external: false };
const procedure = (address, name) => ({ address, name, classification: null, body: { available: false, reason: 'Not recorded' } });
function observe(digit, target, name, edgeKind = kind, available = true) {
  const original = FUNCTION_COMPARISON_EXAMPLE.left;
  const result = structuredClone(original.normalized_result);
  result.outgoing_references = [{ source_address: '0x1000', target_address: target, source_procedure: procedure('0x1000', 'main'), target_procedure: name === null ? null : procedure(target, name), kind: edgeKind }];
  if (!available) result.facet_availability.references = { available: false, reason: 'References not observed' };
  return createEvidence({ path: 'sample.bin', sha256: digit.repeat(64), format: 'mach-o' }, original.provider, { operation: 'analyze_function', parameters: { procedure: 'main' }, result: functionDossierSchema.parse(result), confidence: 'derived', authority: 'shipped-artifact', relationshipCoverage: { status: 'complete' } });
}
const readWrite = { ...kind, type: 'WRITE', read: false, write: true };
const cases = [
  ['mixed-cross-artifact', observe('a', '0x2000', 'helper'), observe('b', '0x3000', null), 'changed'],
  ['mixed-cross-artifact-reversed', observe('b', '0x3000', null), observe('a', '0x2000', 'helper'), 'changed'],
  ['mixed-same-artifact-same-address', observe('a', '0x2000', 'helper'), observe('a', '0x2000', null), 'changed'],
  ['unnamed-cross-artifact', observe('a', '0x2000', null), observe('b', '0x3000', null), 'unknown'],
  ['unnamed-same-artifact-different-addresses', observe('a', '0x2000', null), observe('a', '0x3000', null), 'changed'],
  ['unnamed-same-artifact-same-address', observe('a', '0x2000', null), observe('a', '0x2000', null), 'unchanged'],
  ['named-different-names', observe('a', '0x2000', 'first'), observe('b', '0x3000', 'second'), 'changed'],
  ['named-same-name-relocated', observe('a', '0x2000', 'helper'), observe('b', '0x3000', 'helper'), 'unchanged'],
  ['unnamed-known-kind-change', observe('a', '0x2000', null), observe('b', '0x3000', null, readWrite), 'changed'],
  ['mixed-unavailable-facet', observe('a', '0x2000', 'helper'), observe('b', '0x3000', null, kind, false), 'unknown'],
];
const workspace = await mkdtemp(join(tmpdir(), 'reference-comparison-'));
for (const folder of ['home', 'config', 'cache', 'temp']) await mkdir(join(workspace, folder));
const client = new Client({ name: 'reference-comparison-check', version: '1' });
try {
  await client.connect(new StdioClientTransport({
    command: process.execPath, args: ['scripts/rea.mjs', 'mcp'], cwd: process.cwd(),
    env: { PATH: process.env.PATH, HOME: join(workspace, 'home'), XDG_CONFIG_HOME: join(workspace, 'config'), XDG_CACHE_HOME: join(workspace, 'cache'), TMPDIR: join(workspace, 'temp'), REA_LOG_LEVEL: 'silent' }
  }));
  for (const [label, left, right] of cases) {
    const reply = await client.callTool({ name: 'compare_functions', arguments: { left, right } });
    assert.notEqual(reply.isError, true, JSON.stringify(reply));
    const evidence = parseEvidence(reply.structuredContent);
    const result = evidence.normalized_result;
    const reference = result.dimensions.find(d => d.dimension === 'references');
    console.log(JSON.stringify({ label, status: result.status, references: { status: reference.status, conclusion_kind: reference.conclusion_kind, left_count: reference.left_count, right_count: reference.right_count, limitations: reference.limitations } }));
    if (label === 'mixed-cross-artifact' || label === 'unnamed-cross-artifact') {
      const reply = await client.callTool({ name: 'verify_reconstruction', arguments: { specification: { name: 'Reference agreement', claims: [{ kind: 'structural-function', claim_id: 'references', title: 'References agree', comparison_evidence_id: evidence.evidence_id, dimension: 'references' }] } } });
      assert.notEqual(reply.isError, true, JSON.stringify(reply));
      console.log(JSON.stringify({ label: `${label}-verification`, status: reply.structuredContent.normalized_result.status }));
    }
  }
  await client.ping();
} finally {
  await client.close();
  await rm(workspace, { recursive: true, force: true });
}
JS

Expected behavior

For mixed-cross-artifact, the unnamed right endpoint has no established identity across artifacts. A known left name alone cannot establish that the targets differ. With matching source identity and reference kind, the reference dimension should remain unknown with an unresolved-identity limitation, and the structural reference claim should remain unknown instead of failing. Reversing the inputs must preserve this uncertainty.

For mixed-same-artifact-same-address, both subjects have the same digest, both targets have address 0x2000, and the source and kind are identical. The absent procedure record must not establish a different endpoint. The dimension may retain uncertainty if the available identity facts do not prove equality, but it must not report an established endpoint change merely because name availability differs. Preserve independent known differences, including different named targets, different unnamed addresses within one artifact, and differing known kinds.

Impact and scope

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A bounded class of admitted recorded dossiers produces a false positive reference change, changes the overall comparison result and yields an observed structural verification failure. No severe harm, data loss or broad analysis outage was established; real-provider emission frequency is unmeasured.
  • Workaround status: unverified
  • Workaround basis: The retained dossiers expose the original names and addresses for inspection, but inspection does not establish cross-artifact correspondence or restore machine-readable comparison and verification statuses. No safe practical procedure preserving those results was demonstrated.

REA version

Source checkout at 62bf09809ef7bb224028916424f8f07652a20f4f, built with npm run build:cached. The source package reports 6.5.0; this is not a reproduction of the published rea-agents-6.5.0 package. Current main 08a897b2cd7b359fcb0674c82baec3f1a74af632 was inspected: the cited contract, comparator, and public adapter files are byte-identical to the tested source revision. The baseline reproduction was not rerun on that newer main revision, and packaged-release applicability was not established.

Runtime and platform

macOS arm64; pinned Node.js v24.18.0 and npm 11.16.0; repository locked dependencies. MCP client 2.3.1 and Vitest 5.0.3. No external analysis engine ran. The reference-kind provenance in the fixture does not claim an executed Ghidra session. NOT_ENOUGH_INFO: the OS release was not recorded for the reproduction.

Target and artifact context

Synthetic artifact-bound analyze_function Evidence constructed from the shipped example and validated by functionDossierSchema. Inert Mach-O metadata identifies sample.bin, distinct repeated-digit artifact digests, source main at 0x1000, and outgoing reference targets at 0x2000 or 0x3000. Both facets are available except the explicit unavailable-facet control. No binary file, disassembler, active analysis provider, or target execution is needed.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The executed public MCP calls accepted every fixture. Both mixed cases and the cross-artifact reversal returned overall changed; their reference dimension reported changed, one edge on each side, conclusion_kind: "derived_relationship", and the limitation "Reference endpoints differ independently of provider reference-kind metadata.". The mixed cross-artifact structural verification returned fail. The all-unnamed cross-artifact pair returned unknown, conclusion_kind: "unresolved_branch", and its verification returned unknown.

The controls returned the existing discriminating results: two unnamed different addresses in one artifact were changed; identical unnamed addresses in one artifact were unchanged; different known names were changed; the same known name after relocation was unchanged; a known kind change between unnamed cross-artifact endpoints was changed; and an explicitly unavailable reference facet was unknown with null counts. The reproduction completed with exit status 0. The unchanged existing function-comparison test file passed all 55 tests.

Evidence provenance: observed. Local verification: reproduced. Reproduction completeness: complete. The exact inline reproduction was independently rerun after a fresh source build. All ten public compare_functions calls, both public verify_reconstruction calls, and the final ping completed. The unchanged existing function-comparison suite passed all 55 tests.

Typed outcome or recovery expected

Repeat the same public calls. The mixed cross-artifact pair and its reversal must preserve unknown endpoint identity; its reference reconstruction claim must be unknown. The mixed same-artifact/same-address case must not establish an endpoint change from the missing name alone. Keep the known-name, known-kind, same-artifact-address, relocation and unavailable-facet controls at their documented discriminating outcomes. Keep the original reference records and comparison Evidence links available. Treating every reference comparison as unknown would suppress established changes and would not restore the contract.

Analysis or suspected cause

Source-derived expected contract: the repository identity and uncertainty rule keeps unresolved identity unknown. Endpoint normalization explicitly represents unnamed cross-artifact identity as unknown and retains same-artifact addresses. A known left name does not resolve an unknown right endpoint; identical same-artifact coordinates do not become different because one procedure record is missing.

Source-derived failure explanation: reference comparison returns changed for unequal endpoint projections before the unnamed cross-artifact identity guard. A named string versus null, or versus the same address represented as an object, reaches that earlier branch. This explains the executed results; it does not prescribe a particular implementation.

Public reachability: the MCP contract accepts complete analyze_function Evidence directly. The registered handler authenticates the envelope and operation, records both sources and derived comparison Evidence, and delivers the result. Dossier parsing validates artifact-bound inputs, and session admission allows this composed operation without invoking an analysis executor.

Additional context

Closed #3388 addressed false equality between two unnamed targets at different addresses within one artifact. Its merged fix preserves those addresses and introduces cross-artifact uncertainty, but the mixed cases above still return an unsupported change. The prior all-unnamed regression tests alone do not specify mixed behavior; the expected result here follows from the owning identity-preservation rule and the recorded coordinates.

Open #1947 concerns additive address-normalized provider-text dimensions, while #3506 explores explicit cross-build callee matches for normalized views. Neither closure signal restores the reference dimension's uncertainty for these existing admitted inputs. No claim is made about the frequency of this fixture shape in real engine output or about behavior on other host platforms.

NOT_ENOUGH_INFO: frequency in real provider output, behavior on other platforms, and a practical result-preserving workaround were not established. Published-package behavior was not tested.

Originally created by @coygeek on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4210 ### 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 `compare_functions` reports `references: changed` when one recorded target has a procedure name and the other has unknown cross-artifact identity, even though no known reference kind or named target differs. The same false endpoint-change conclusion occurs for one artifact when both records identify the exact same target address and only one supplies a procedure record. The first result also becomes a definite `fail` in `verify_reconstruction`; the all-unnamed control remains `unknown` in both tools. ### Reproduction Use the source revision under REA version and the repository's pinned development toolchain. From the checkout root, install the locked dependencies if necessary and build the runtime: ```sh npm ci npm run build:cached ``` Run this complete fixture from the checkout root. It supplies complete inline `analyze_function` Evidence to the registered tool on a fresh session, with available reference facets and complete relationship coverage. The target names, addresses and artifact digests are inert recorded metadata; no corresponding binary file is needed. The fixture checks both reported cases and controls, prints the relevant statuses and closes its MCP connection. ```sh node --input-type=module <<'JS' import assert from 'node:assert/strict'; import { mkdtemp, mkdir, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { Client } from '@modelcontextprotocol/client'; import { StdioClientTransport } from '@modelcontextprotocol/client/stdio'; import { createEvidence, parseEvidence } from './dist/domain/evidence.js'; import { functionDossierSchema } from './dist/domain/hopperValues.js'; import { FUNCTION_COMPARISON_EXAMPLE } from './dist/contracts/functionComparisonExample.js'; const kind = { available: true, provenance: 'ghidra-reference-manager', type: 'READ', flow: false, call: false, jump: false, data: true, read: true, write: false, indirect: false, computed: false, conditional: false, terminal: false, primary: true, operand_index: 0, external: false }; const procedure = (address, name) => ({ address, name, classification: null, body: { available: false, reason: 'Not recorded' } }); function observe(digit, target, name, edgeKind = kind, available = true) { const original = FUNCTION_COMPARISON_EXAMPLE.left; const result = structuredClone(original.normalized_result); result.outgoing_references = [{ source_address: '0x1000', target_address: target, source_procedure: procedure('0x1000', 'main'), target_procedure: name === null ? null : procedure(target, name), kind: edgeKind }]; if (!available) result.facet_availability.references = { available: false, reason: 'References not observed' }; return createEvidence({ path: 'sample.bin', sha256: digit.repeat(64), format: 'mach-o' }, original.provider, { operation: 'analyze_function', parameters: { procedure: 'main' }, result: functionDossierSchema.parse(result), confidence: 'derived', authority: 'shipped-artifact', relationshipCoverage: { status: 'complete' } }); } const readWrite = { ...kind, type: 'WRITE', read: false, write: true }; const cases = [ ['mixed-cross-artifact', observe('a', '0x2000', 'helper'), observe('b', '0x3000', null), 'changed'], ['mixed-cross-artifact-reversed', observe('b', '0x3000', null), observe('a', '0x2000', 'helper'), 'changed'], ['mixed-same-artifact-same-address', observe('a', '0x2000', 'helper'), observe('a', '0x2000', null), 'changed'], ['unnamed-cross-artifact', observe('a', '0x2000', null), observe('b', '0x3000', null), 'unknown'], ['unnamed-same-artifact-different-addresses', observe('a', '0x2000', null), observe('a', '0x3000', null), 'changed'], ['unnamed-same-artifact-same-address', observe('a', '0x2000', null), observe('a', '0x2000', null), 'unchanged'], ['named-different-names', observe('a', '0x2000', 'first'), observe('b', '0x3000', 'second'), 'changed'], ['named-same-name-relocated', observe('a', '0x2000', 'helper'), observe('b', '0x3000', 'helper'), 'unchanged'], ['unnamed-known-kind-change', observe('a', '0x2000', null), observe('b', '0x3000', null, readWrite), 'changed'], ['mixed-unavailable-facet', observe('a', '0x2000', 'helper'), observe('b', '0x3000', null, kind, false), 'unknown'], ]; const workspace = await mkdtemp(join(tmpdir(), 'reference-comparison-')); for (const folder of ['home', 'config', 'cache', 'temp']) await mkdir(join(workspace, folder)); const client = new Client({ name: 'reference-comparison-check', version: '1' }); try { await client.connect(new StdioClientTransport({ command: process.execPath, args: ['scripts/rea.mjs', 'mcp'], cwd: process.cwd(), env: { PATH: process.env.PATH, HOME: join(workspace, 'home'), XDG_CONFIG_HOME: join(workspace, 'config'), XDG_CACHE_HOME: join(workspace, 'cache'), TMPDIR: join(workspace, 'temp'), REA_LOG_LEVEL: 'silent' } })); for (const [label, left, right] of cases) { const reply = await client.callTool({ name: 'compare_functions', arguments: { left, right } }); assert.notEqual(reply.isError, true, JSON.stringify(reply)); const evidence = parseEvidence(reply.structuredContent); const result = evidence.normalized_result; const reference = result.dimensions.find(d => d.dimension === 'references'); console.log(JSON.stringify({ label, status: result.status, references: { status: reference.status, conclusion_kind: reference.conclusion_kind, left_count: reference.left_count, right_count: reference.right_count, limitations: reference.limitations } })); if (label === 'mixed-cross-artifact' || label === 'unnamed-cross-artifact') { const reply = await client.callTool({ name: 'verify_reconstruction', arguments: { specification: { name: 'Reference agreement', claims: [{ kind: 'structural-function', claim_id: 'references', title: 'References agree', comparison_evidence_id: evidence.evidence_id, dimension: 'references' }] } } }); assert.notEqual(reply.isError, true, JSON.stringify(reply)); console.log(JSON.stringify({ label: `${label}-verification`, status: reply.structuredContent.normalized_result.status })); } } await client.ping(); } finally { await client.close(); await rm(workspace, { recursive: true, force: true }); } JS ``` ### Expected behavior For `mixed-cross-artifact`, the unnamed right endpoint has no established identity across artifacts. A known left name alone cannot establish that the targets differ. With matching source identity and reference kind, the reference dimension should remain `unknown` with an unresolved-identity limitation, and the structural reference claim should remain `unknown` instead of failing. Reversing the inputs must preserve this uncertainty. For `mixed-same-artifact-same-address`, both subjects have the same digest, both targets have address `0x2000`, and the source and kind are identical. The absent procedure record must not establish a different endpoint. The dimension may retain uncertainty if the available identity facts do not prove equality, but it must not report an established endpoint change merely because name availability differs. Preserve independent known differences, including different named targets, different unnamed addresses within one artifact, and differing known kinds. ### Impact and scope - Impact level: P2 - Assessment status: supported - Impact basis: A bounded class of admitted recorded dossiers produces a false positive reference change, changes the overall comparison result and yields an observed structural verification failure. No severe harm, data loss or broad analysis outage was established; real-provider emission frequency is unmeasured. - Workaround status: unverified - Workaround basis: The retained dossiers expose the original names and addresses for inspection, but inspection does not establish cross-artifact correspondence or restore machine-readable comparison and verification statuses. No safe practical procedure preserving those results was demonstrated. ### REA version Source checkout at [62bf09809ef7bb224028916424f8f07652a20f4f](https://github.com/morluto/rea/commit/62bf09809ef7bb224028916424f8f07652a20f4f), built with `npm run build:cached`. The source package reports 6.5.0; this is not a reproduction of the published `rea-agents-6.5.0` package. Current main `08a897b2cd7b359fcb0674c82baec3f1a74af632` was inspected: the cited contract, comparator, and public adapter files are byte-identical to the tested source revision. The baseline reproduction was not rerun on that newer main revision, and packaged-release applicability was not established. ### Runtime and platform macOS arm64; pinned Node.js v24.18.0 and npm 11.16.0; repository locked dependencies. MCP client 2.3.1 and Vitest 5.0.3. No external analysis engine ran. The reference-kind provenance in the fixture does not claim an executed Ghidra session. NOT_ENOUGH_INFO: the OS release was not recorded for the reproduction. ### Target and artifact context Synthetic artifact-bound `analyze_function` Evidence constructed from the shipped example and validated by `functionDossierSchema`. Inert Mach-O metadata identifies `sample.bin`, distinct repeated-digit artifact digests, source `main` at `0x1000`, and outgoing reference targets at `0x2000` or `0x3000`. Both facets are available except the explicit unavailable-facet control. No binary file, disassembler, active analysis provider, or target execution is needed. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The executed public MCP calls accepted every fixture. Both mixed cases and the cross-artifact reversal returned overall `changed`; their reference dimension reported `changed`, one edge on each side, `conclusion_kind: "derived_relationship"`, and the limitation `"Reference endpoints differ independently of provider reference-kind metadata."`. The mixed cross-artifact structural verification returned `fail`. The all-unnamed cross-artifact pair returned `unknown`, `conclusion_kind: "unresolved_branch"`, and its verification returned `unknown`. The controls returned the existing discriminating results: two unnamed different addresses in one artifact were `changed`; identical unnamed addresses in one artifact were `unchanged`; different known names were `changed`; the same known name after relocation was `unchanged`; a known kind change between unnamed cross-artifact endpoints was `changed`; and an explicitly unavailable reference facet was `unknown` with null counts. The reproduction completed with exit status 0. The unchanged existing function-comparison test file passed all 55 tests. Evidence provenance: observed. Local verification: reproduced. Reproduction completeness: complete. The exact inline reproduction was independently rerun after a fresh source build. All ten public `compare_functions` calls, both public `verify_reconstruction` calls, and the final ping completed. The unchanged existing function-comparison suite passed all 55 tests. ### Typed outcome or recovery expected Repeat the same public calls. The mixed cross-artifact pair and its reversal must preserve unknown endpoint identity; its reference reconstruction claim must be `unknown`. The mixed same-artifact/same-address case must not establish an endpoint change from the missing name alone. Keep the known-name, known-kind, same-artifact-address, relocation and unavailable-facet controls at their documented discriminating outcomes. Keep the original reference records and comparison Evidence links available. Treating every reference comparison as unknown would suppress established changes and would not restore the contract. ### Analysis or suspected cause Source-derived expected contract: [the repository identity and uncertainty rule](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/AGENTS.md#L19-L29) keeps unresolved identity unknown. [Endpoint normalization](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/src/domain/functionComparisonNormalization.ts#L77-L115) explicitly represents unnamed cross-artifact identity as unknown and retains same-artifact addresses. A known left name does not resolve an unknown right endpoint; identical same-artifact coordinates do not become different because one procedure record is missing. Source-derived failure explanation: [reference comparison](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/src/domain/functionComparisonDimensions.ts#L264-L329) returns changed for unequal endpoint projections before the unnamed cross-artifact identity guard. A named string versus null, or versus the same address represented as an object, reaches that earlier branch. This explains the executed results; it does not prescribe a particular implementation. Public reachability: [the MCP contract](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/docs/mcp-contracts.md#L18-L22) accepts complete `analyze_function` Evidence directly. [The registered handler](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/src/server/registerFunctionComparisonTool.ts#L31-L120) authenticates the envelope and operation, records both sources and derived comparison Evidence, and delivers the result. [Dossier parsing](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/src/domain/functionDossierEvidence.ts#L16-L39) validates artifact-bound inputs, and [session admission](https://github.com/morluto/rea/blob/62bf09809ef7bb224028916424f8f07652a20f4f/src/application/binary/BinarySession.ts#L673-L698) allows this composed operation without invoking an analysis executor. ### Additional context Closed [#3388](https://github.com/morluto/rea/issues/3388) addressed false equality between two unnamed targets at different addresses within one artifact. Its merged fix preserves those addresses and introduces cross-artifact uncertainty, but the mixed cases above still return an unsupported change. The prior all-unnamed regression tests alone do not specify mixed behavior; the expected result here follows from the owning identity-preservation rule and the recorded coordinates. Open [#1947](https://github.com/morluto/rea/issues/1947) concerns additive address-normalized provider-text dimensions, while [#3506](https://github.com/morluto/rea/issues/3506) explores explicit cross-build callee matches for normalized views. Neither closure signal restores the reference dimension's uncertainty for these existing admitted inputs. No claim is made about the frequency of this fixture shape in real engine output or about behavior on other host platforms. NOT_ENOUGH_INFO: frequency in real provider output, behavior on other platforms, and a practical result-preserving workaround were not established. Published-package behavior was not tested.
Author
Owner

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

Fixed on main in 92dadf933.

The old projections discarded endpoint uncertainty before comparing rows and erased all reference-kind facts if any row lacked a kind. They also substituted containing procedures for raw same-artifact sites and treated generated/nonunique names as sufficient cross-artifact identity.

A shared reference-fact owner now preserves direction, per-edge kind knowledge, exact same-artifact coordinates and cross-artifact identity uncertainty. Exact compatible pairing retains duplicates and alternatives; a known contradiction proves change only when every pairing contradicts it. The matcher uses a sparse grouped flow graph and iterative walks, replacing quadratic adjacency storage and recursive matching proposed in the existing PR. Native coordinate parsing is shared with call paths; superseded projections were removed. The matching insight from PR #4365 is credited to Henglie in the commit; neither PR #4365 nor #4337 was merged.

Validation executed: 199 focused tests across 11 files, including public MCP comparison/reconstruction, call-path consumers and 15 advertised-schema checks; final expanded public regressions 5/5; independent tiny permutation oracles and 10,000-row dense controls; full static/architecture checks, docs checks (5 conformance tests), discovery and pre-push checks. A clean baseline at 559af3d3f reproduced the public regressions before the fix. Tests use authenticated controlled Evidence; no native engine or binary executed.

Twelve compiled public SDK measurements included discovery and request/reply serialization estimates. Four-row equivalent control repeated-process medians: elapsed 2.154→2.155 s, CPU 2.846→2.867 s, sampled process-family RSS 741→744 MB; request tokens 2,104 unchanged, SDK reply estimate 811,565→811,577 cl100k tokens including the full 207-tool catalog. Catalog hash unchanged. The 1,000-row partial-identity case now correctly returns unknown instead of changed, so its before/after costs are not an equivalent-result speed comparison. No speedup, actual model-context, true cold-cache, adversarial worst-case runtime or real-provider qualification is claimed. Graph storage is linear in distinct row groups; general worst-case flow time remains cubic, applying the general max-flow bound to this linear graph.

The adjacent public consumer scan also reproduced existing #3333 for distinct unresolved reconstruction verifications in one session; that separate registry-identity defect is fixed in 95c8f57aa. Whole-facet unavailable declarations intentionally remain unknown; this change concerns available facets with partial per-row knowledge.

<!-- gh-comment-id:6256664190 --> @morluto commented on GitHub (Oct 18, 2026): Fixed on main in [92dadf933](https://github.com/morluto/rea/commit/92dadf933). The old projections discarded endpoint uncertainty before comparing rows and erased all reference-kind facts if any row lacked a kind. They also substituted containing procedures for raw same-artifact sites and treated generated/nonunique names as sufficient cross-artifact identity. A shared reference-fact owner now preserves direction, per-edge kind knowledge, exact same-artifact coordinates and cross-artifact identity uncertainty. Exact compatible pairing retains duplicates and alternatives; a known contradiction proves change only when every pairing contradicts it. The matcher uses a sparse grouped flow graph and iterative walks, replacing quadratic adjacency storage and recursive matching proposed in the existing PR. Native coordinate parsing is shared with call paths; superseded projections were removed. The matching insight from PR #4365 is credited to Henglie in the commit; neither PR #4365 nor #4337 was merged. Validation executed: 199 focused tests across 11 files, including public MCP comparison/reconstruction, call-path consumers and 15 advertised-schema checks; final expanded public regressions 5/5; independent tiny permutation oracles and 10,000-row dense controls; full static/architecture checks, docs checks (5 conformance tests), discovery and pre-push checks. A clean baseline at 559af3d3f reproduced the public regressions before the fix. Tests use authenticated controlled Evidence; no native engine or binary executed. Twelve compiled public SDK measurements included discovery and request/reply serialization estimates. Four-row equivalent control repeated-process medians: elapsed 2.154→2.155 s, CPU 2.846→2.867 s, sampled process-family RSS 741→744 MB; request tokens 2,104 unchanged, SDK reply estimate 811,565→811,577 cl100k tokens including the full 207-tool catalog. Catalog hash unchanged. The 1,000-row partial-identity case now correctly returns unknown instead of changed, so its before/after costs are not an equivalent-result speed comparison. No speedup, actual model-context, true cold-cache, adversarial worst-case runtime or real-provider qualification is claimed. Graph storage is linear in distinct row groups; general worst-case flow time remains cubic, applying the [general max-flow bound](https://atcoder.github.io/ac-library/production/document_en/maxflow.html) to this linear graph. The adjacent public consumer scan also reproduced existing #3333 for distinct unresolved reconstruction verifications in one session; that separate registry-identity defect is fixed in [95c8f57aa](https://github.com/morluto/rea/commit/95c8f57aa). Whole-facet unavailable declarations intentionally remain unknown; this change concerns available facets with partial per-row knowledge.
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#1653
No description provided.