[GH-ISSUE #3195] [Bug] Function comparison and reconstruction verification drop complete call-coverage diagnostics #1132

Closed
opened 2026-10-15 18:31:22 +00:00 by bsakaguchi · 1 comment
Owner

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

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

Valid inline analyze_function Evidence with complete relationship coverage and a provider diagnostic loses that diagnostic when passed to compare_functions. A subsequent verify_reconstruction claim selecting the calls dimension also omits it. In the reproduced synthetic-input case, the comparison reports calls.status: unchanged with zero left and right counts and empty dimension limitations. Its normalized-result limitations are empty, and the full MCP response contains no supplied diagnostic. Verification returns pass with observed_status: unchanged, also without the diagnostic.

These statuses can remain correct for the complete provider-observed set. The defect is the omitted caveat about the scope of that set. The canonical comparison Evidence and verification claim retain the unrelated artifact-identity notice, so their limitation arrays are not entirely empty.

The controls show that partial coverage retains the diagnostic and read-limit reason and produces unknown in both tools. Complete coverage without a diagnostic produces unchanged and pass. A separate dossier caveat survives comparison and verification while the complete-coverage diagnostic still disappears. get_evidence_bundle retains the original source diagnostic on the same MCP connection.

Reproduction

  1. Start from a clean checkout at 58300885207133422af235e0f2b10658cf958b03. Install the locked dependencies and build the runtime. The verifier used an already prepared baseline and did not rerun these preparation commands. Use an isolated home for the reproduction.
npm ci
npm run build:cached
mkdir -p repro-home/config repro-home/cache repro-home/data
  1. Run the following inline program from the checkout root. It creates all Evidence inputs inline, starts the production MCP server, calls compare_functions and then verify_reconstruction on the same connection, and closes the connection. Artifact paths and digests are synthetic Evidence metadata; no artifact file is opened. Each dossier explicitly declares its empty caller and callee sets available. The controls vary coverage and add a separate dossier caveat.
env HOME="$PWD/repro-home" XDG_CONFIG_HOME="$PWD/repro-home/config" XDG_CACHE_HOME="$PWD/repro-home/cache" XDG_DATA_HOME="$PWD/repro-home/data" node --input-type=module <<'EOF'
import assert from 'node:assert/strict';
import { resolve } from 'node:path';
import { Client } from '@modelcontextprotocol/client';
import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
import { createEvidence, parseEvidence } from './dist/domain/evidence.js';
import { jsonValueSchema } from './dist/domain/jsonValue.js';

const diagnostic = 'Only resolved Ghidra call references are returned; unresolved computed or indirect calls remain unknown, while function classifications distinguish thunks and externals.';
const dossier = jsonValueSchema.parse({
  procedure: { address: '0x1000', name: 'main', classification: null,
    body: { available: false, reason: 'Synthetic observation omits body extent.' },
    signature: 'int main(void)', locals: [] },
  pseudocode: 'return 0;', assembly: ['ret'], comments: [], callers: [], callees: [],
  incoming_references: [], outgoing_references: [], referenced_strings: [], referenced_names: [],
  basic_blocks: [{ start: '0x1000', end: '0x1001', successors: [] }],
  native_api: null, native_value_flow: null,
  facet_availability: Object.fromEntries(['pseudocode', 'assembly', 'comments', 'callers', 'callees', 'references', 'strings_names', 'cfg'].map(key => [key, { available: true }])),
  limitations: [],
});
const observe = (digit, relationshipCoverage, limitations = []) => createEvidence(
  { path: resolve(`artifact-${digit}`), sha256: digit.repeat(64), format: 'mach-o' },
  { id: 'synthetic-provider', name: 'Synthetic provider', version: '1' },
  { operation: 'analyze_function', parameters: { procedure: 'main' }, result: jsonValueSchema.parse({ ...dossier, limitations }),
    confidence: 'derived', authority: 'shipped-artifact', relationshipCoverage }
);
const env = Object.fromEntries(['PATH', 'HOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME'].map(key => [key, process.env[key]]));
const transport = new StdioClientTransport({ command: process.execPath,
  args: [resolve('scripts/rea.mjs'), 'mcp'],
  env: { ...env, REA_LOG_LEVEL: 'silent', HOPPER_LAUNCHER_PATH: resolve('unconfigured-hopper') }, stderr: 'pipe' });
let stderr = '';
transport.stderr?.on('data', value => { stderr += value.toString(); });
const client = new Client({ name: 'coverage-reproduction', version: '1' });
try {
  await client.connect(transport);
  for (const [label, coverage, limitations] of [
    ['complete-diagnostic', { status: 'complete', diagnostics: [diagnostic] }],
    ['partial-diagnostic', { status: 'partial', limitations: ['A read limit was reached.'], diagnostics: [diagnostic] }],
    ['complete-no-diagnostic', { status: 'complete' }],
    ['complete-with-dossier-caveat', { status: 'complete', diagnostics: [diagnostic] }, ['Unresolved computed or indirect flows without target addresses are not represented as reference edges.']],
  ]) {
    const response = await client.callTool({ name: 'compare_functions', arguments: { left: observe('a', coverage, limitations), right: observe('b', coverage, limitations) } });
    assert.notEqual(response.isError, true, JSON.stringify(response));
    const evidence = parseEvidence(response.structuredContent);
    const calls = evidence.normalized_result.dimensions.find(d => d.dimension === 'calls');
    const verification = await client.callTool({ name: 'verify_reconstruction', arguments: {
      specification: { name: 'Resolved call comparison', claims: [{ kind: 'structural-function', claim_id: 'calls', title: 'Resolved calls agree', comparison_evidence_id: evidence.evidence_id, dimension: 'calls' }] }
    } });
    assert.notEqual(verification.isError, true, JSON.stringify(verification));
    const verificationEvidence = parseEvidence(verification.structuredContent);
    const claim = verificationEvidence.normalized_result.claims.items[0];
    console.log(JSON.stringify({ label, callsStatus: calls.status, callsLimitations: calls.limitations,
      comparisonLimitations: evidence.normalized_result.limitations, claimStatus: claim.status,
      claimLimitations: claim.limitations, diagnosticPresentInComparison: JSON.stringify(response).includes(diagnostic),
      diagnosticPresentInVerification: JSON.stringify(verification).includes(diagnostic) }));
    if (label === 'partial-diagnostic') {
      assert.equal(calls.status, 'unknown');
      assert.equal(JSON.stringify(response).includes(diagnostic), true);
      assert.equal(JSON.stringify(verification).includes(diagnostic), true);
    } else {
      assert.equal(calls.status, 'unchanged');
      assert.deepEqual(calls.limitations, []);
      assert.equal(claim.status, 'pass');
      assert.equal(claim.limitations.some(item => item.includes(diagnostic)), false);
      assert.equal(JSON.stringify(response).includes(diagnostic), false);
      assert.equal(JSON.stringify(verification).includes(diagnostic), false);
    }
  }
  const retained = await client.callTool({ name: 'get_evidence_bundle', arguments: {} });
  assert.notEqual(retained.isError, true, JSON.stringify(retained));
  assert.equal(JSON.stringify(retained).includes(diagnostic), true);
  console.log(JSON.stringify({ retainedSourceDiagnosticPresent: true }));
} finally {
  await client.close();
  await transport.close();
  if (stderr) console.error(stderr);
}
EOF
  1. Inspect the complete-diagnostic output. The calls limitations are empty and both diagnostic-presence fields are false. The partial-diagnostic control retains the diagnostic in both responses and reports unknown. The complete-no-diagnostic control reports unchanged and pass without adding a coverage diagnostic. The complete-with-dossier-caveat control retains the separate dossier caveat while still losing the coverage diagnostic. The final output confirms that get_evidence_bundle still contains the source diagnostic.

Expected behavior

docs/tool-design.md:60-64 defines complete relationship coverage as the provider-observed direct relationship set returned without a known read limit. It requires provider and execution caveats to stay in limitations without implying incomplete relationship coverage. docs/mcp-contracts.md:19-21 supports inline analyze_function Evidence as comparison input, and docs/mcp-contracts.md:56-65 defines comparison coverage semantics. src/domain/relationshipCoverage.ts:3-7 permits diagnostics on complete coverage.

The calls comparison and downstream calls claim should retain the supplied diagnostic while preserving the complete observed-set conclusion. A diagnostic alone should not make otherwise equal complete call sets unknown.

Impact and scope

The supported inline-Evidence workflow loses a provider caveat in two derived results. This affects interpretation of the observed call-set scope. The independent verifier rated it P2 because the loss is consequential but bounded, with a demonstrated workaround. Inspect the retained source Evidence's relationship_coverage.diagnostics, available through get_evidence_bundle, when interpreting the derived result.

No source-data loss, crash, or security boundary crossing was observed. Ghidra engine execution was not performed. Static source inspection establishes provider applicability, but real Ghidra dossiers also carry separate unresolved-flow and classification caveats. This report does not establish that real Ghidra comparisons lose every warning about indirect calls. The dossier-caveat control demonstrates that independent caveats survive.

REA version

6.4.0 (main at 5830088520)

Runtime and platform

Node 26.10.0; macOS 27.0 arm64

Target and artifact context

Synthetic canonical analyze_function Evidence, with synthetic Mach-O artifact paths and digests and an explicitly synthetic provider identity. All input records are created inline. Each dossier declares its empty caller and callee sets available. No executable artifact is opened, no target is executed, and no Ghidra installation is required.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

{"label":"complete-diagnostic","callsStatus":"unchanged","callsLimitations":[],"comparisonLimitations":[],"claimStatus":"pass","claimLimitations":["Artifact identity is unavailable for this observation."],"diagnosticPresentInComparison":false,"diagnosticPresentInVerification":false}
{"retainedSourceDiagnosticPresent":true}

The first line is the complete-diagnostic case. The supplied diagnostic is Only resolved Ghidra call references are returned; unresolved computed or indirect calls remain unknown, while function classifications distinguish thunks and externals. The last line confirms source retention after the comparison and verification controls.

Typed outcome or recovery expected

The comparison's calls limitations and the downstream calls claim must carry the supplied diagnostic. Equal complete observed call sets should remain unchanged, and verification should retain its complete-set conclusion with that caveat. Partial coverage must remain unknown with its read-limit reasons and diagnostics. Complete coverage without diagnostics must not gain a fabricated caveat. The dossier-caveat control must retain both the independent caveat and the coverage diagnostic. Original source Evidence must remain accessible.

Analysis or suspected cause

Source-derived at the reported baseline: src/server/registerFunctionComparisonTool.ts:38-75 validates inline Evidence and reaches comparison. src/domain/functionDossierEvidence.ts:25-28 computes call limitations through src/domain/functionCallCoverage.ts:82-92. The conditional at line 88 excludes diagnostics whenever coverage is complete. src/domain/functionComparisonDimensions.ts:328-365 consumes that result when comparing calls. src/domain/reconstructionVerification.ts:219-222 independently rereads retained source coverage through the same helper, so source retention does not restore the diagnostic in verification.

Source-derived repair constraint: src/domain/functionComparisonDimensions.ts:335-346 treats every call-coverage limitation as an equality blocker. Simply removing the helper's conditional would therefore turn a complete observed-set comparison into unknown, contrary to the documented distinction between caveats and incomplete coverage. Diagnostic preservation must respect that distinction.

Source-derived Ghidra applicability, without engine execution: bridge/ghidra/ReaGhidraBridge.java:1539-1654 emits dossier call coverage, and bridge/ghidra/ReaGhidraBridge.java:3373-3416 supplies the diagnostic on complete coverage. src/ghidra/GhidraFunctionValues.ts:445-486 preserves the declared field, and src/ghidra/GhidraProviderClient.ts:853-861 and src/ghidra/GhidraProviderClient.ts:952-959 carry it into provider execution. Separate dossier caveats are supplied at bridge/ghidra/ReaGhidraBridge.java:1610-1622.

Additional context

Related reports #2222, #2951, #2980, #2326, and #1964 address incomplete-coverage verdicts, missing producer declarations, primitive warning generation, or graph/path caveat classification; this report requires retaining an already supplied complete-coverage diagnostic in comparison and verification while preserving valid observed-set equality.

Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3195 ### 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 Valid inline `analyze_function` Evidence with complete relationship coverage and a provider diagnostic loses that diagnostic when passed to `compare_functions`. A subsequent `verify_reconstruction` claim selecting the `calls` dimension also omits it. In the reproduced synthetic-input case, the comparison reports `calls.status: unchanged` with zero left and right counts and empty dimension limitations. Its normalized-result limitations are empty, and the full MCP response contains no supplied diagnostic. Verification returns `pass` with `observed_status: unchanged`, also without the diagnostic. These statuses can remain correct for the complete provider-observed set. The defect is the omitted caveat about the scope of that set. The canonical comparison Evidence and verification claim retain the unrelated artifact-identity notice, so their limitation arrays are not entirely empty. The controls show that partial coverage retains the diagnostic and read-limit reason and produces `unknown` in both tools. Complete coverage without a diagnostic produces `unchanged` and `pass`. A separate dossier caveat survives comparison and verification while the complete-coverage diagnostic still disappears. `get_evidence_bundle` retains the original source diagnostic on the same MCP connection. ### Reproduction 1. Start from a clean checkout at `58300885207133422af235e0f2b10658cf958b03`. Install the locked dependencies and build the runtime. The verifier used an already prepared baseline and did not rerun these preparation commands. Use an isolated home for the reproduction. ```sh npm ci npm run build:cached mkdir -p repro-home/config repro-home/cache repro-home/data ``` 2. Run the following inline program from the checkout root. It creates all Evidence inputs inline, starts the production MCP server, calls compare_functions and then verify_reconstruction on the same connection, and closes the connection. Artifact paths and digests are synthetic Evidence metadata; no artifact file is opened. Each dossier explicitly declares its empty caller and callee sets available. The controls vary coverage and add a separate dossier caveat. ```sh env HOME="$PWD/repro-home" XDG_CONFIG_HOME="$PWD/repro-home/config" XDG_CACHE_HOME="$PWD/repro-home/cache" XDG_DATA_HOME="$PWD/repro-home/data" node --input-type=module <<'EOF' import assert from 'node:assert/strict'; import { resolve } from 'node:path'; import { Client } from '@modelcontextprotocol/client'; import { StdioClientTransport } from '@modelcontextprotocol/client/stdio'; import { createEvidence, parseEvidence } from './dist/domain/evidence.js'; import { jsonValueSchema } from './dist/domain/jsonValue.js'; const diagnostic = 'Only resolved Ghidra call references are returned; unresolved computed or indirect calls remain unknown, while function classifications distinguish thunks and externals.'; const dossier = jsonValueSchema.parse({ procedure: { address: '0x1000', name: 'main', classification: null, body: { available: false, reason: 'Synthetic observation omits body extent.' }, signature: 'int main(void)', locals: [] }, pseudocode: 'return 0;', assembly: ['ret'], comments: [], callers: [], callees: [], incoming_references: [], outgoing_references: [], referenced_strings: [], referenced_names: [], basic_blocks: [{ start: '0x1000', end: '0x1001', successors: [] }], native_api: null, native_value_flow: null, facet_availability: Object.fromEntries(['pseudocode', 'assembly', 'comments', 'callers', 'callees', 'references', 'strings_names', 'cfg'].map(key => [key, { available: true }])), limitations: [], }); const observe = (digit, relationshipCoverage, limitations = []) => createEvidence( { path: resolve(`artifact-${digit}`), sha256: digit.repeat(64), format: 'mach-o' }, { id: 'synthetic-provider', name: 'Synthetic provider', version: '1' }, { operation: 'analyze_function', parameters: { procedure: 'main' }, result: jsonValueSchema.parse({ ...dossier, limitations }), confidence: 'derived', authority: 'shipped-artifact', relationshipCoverage } ); const env = Object.fromEntries(['PATH', 'HOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME'].map(key => [key, process.env[key]])); const transport = new StdioClientTransport({ command: process.execPath, args: [resolve('scripts/rea.mjs'), 'mcp'], env: { ...env, REA_LOG_LEVEL: 'silent', HOPPER_LAUNCHER_PATH: resolve('unconfigured-hopper') }, stderr: 'pipe' }); let stderr = ''; transport.stderr?.on('data', value => { stderr += value.toString(); }); const client = new Client({ name: 'coverage-reproduction', version: '1' }); try { await client.connect(transport); for (const [label, coverage, limitations] of [ ['complete-diagnostic', { status: 'complete', diagnostics: [diagnostic] }], ['partial-diagnostic', { status: 'partial', limitations: ['A read limit was reached.'], diagnostics: [diagnostic] }], ['complete-no-diagnostic', { status: 'complete' }], ['complete-with-dossier-caveat', { status: 'complete', diagnostics: [diagnostic] }, ['Unresolved computed or indirect flows without target addresses are not represented as reference edges.']], ]) { const response = await client.callTool({ name: 'compare_functions', arguments: { left: observe('a', coverage, limitations), right: observe('b', coverage, limitations) } }); assert.notEqual(response.isError, true, JSON.stringify(response)); const evidence = parseEvidence(response.structuredContent); const calls = evidence.normalized_result.dimensions.find(d => d.dimension === 'calls'); const verification = await client.callTool({ name: 'verify_reconstruction', arguments: { specification: { name: 'Resolved call comparison', claims: [{ kind: 'structural-function', claim_id: 'calls', title: 'Resolved calls agree', comparison_evidence_id: evidence.evidence_id, dimension: 'calls' }] } } }); assert.notEqual(verification.isError, true, JSON.stringify(verification)); const verificationEvidence = parseEvidence(verification.structuredContent); const claim = verificationEvidence.normalized_result.claims.items[0]; console.log(JSON.stringify({ label, callsStatus: calls.status, callsLimitations: calls.limitations, comparisonLimitations: evidence.normalized_result.limitations, claimStatus: claim.status, claimLimitations: claim.limitations, diagnosticPresentInComparison: JSON.stringify(response).includes(diagnostic), diagnosticPresentInVerification: JSON.stringify(verification).includes(diagnostic) })); if (label === 'partial-diagnostic') { assert.equal(calls.status, 'unknown'); assert.equal(JSON.stringify(response).includes(diagnostic), true); assert.equal(JSON.stringify(verification).includes(diagnostic), true); } else { assert.equal(calls.status, 'unchanged'); assert.deepEqual(calls.limitations, []); assert.equal(claim.status, 'pass'); assert.equal(claim.limitations.some(item => item.includes(diagnostic)), false); assert.equal(JSON.stringify(response).includes(diagnostic), false); assert.equal(JSON.stringify(verification).includes(diagnostic), false); } } const retained = await client.callTool({ name: 'get_evidence_bundle', arguments: {} }); assert.notEqual(retained.isError, true, JSON.stringify(retained)); assert.equal(JSON.stringify(retained).includes(diagnostic), true); console.log(JSON.stringify({ retainedSourceDiagnosticPresent: true })); } finally { await client.close(); await transport.close(); if (stderr) console.error(stderr); } EOF ``` 3. Inspect the complete-diagnostic output. The calls limitations are empty and both diagnostic-presence fields are false. The partial-diagnostic control retains the diagnostic in both responses and reports unknown. The complete-no-diagnostic control reports unchanged and pass without adding a coverage diagnostic. The complete-with-dossier-caveat control retains the separate dossier caveat while still losing the coverage diagnostic. The final output confirms that get_evidence_bundle still contains the source diagnostic. ### Expected behavior `docs/tool-design.md:60-64` defines complete relationship coverage as the provider-observed direct relationship set returned without a known read limit. It requires provider and execution caveats to stay in limitations without implying incomplete relationship coverage. `docs/mcp-contracts.md:19-21` supports inline `analyze_function` Evidence as comparison input, and `docs/mcp-contracts.md:56-65` defines comparison coverage semantics. `src/domain/relationshipCoverage.ts:3-7` permits diagnostics on complete coverage. The calls comparison and downstream calls claim should retain the supplied diagnostic while preserving the complete observed-set conclusion. A diagnostic alone should not make otherwise equal complete call sets `unknown`. ### Impact and scope The supported inline-Evidence workflow loses a provider caveat in two derived results. This affects interpretation of the observed call-set scope. The independent verifier rated it P2 because the loss is consequential but bounded, with a demonstrated workaround. Inspect the retained source Evidence's `relationship_coverage.diagnostics`, available through `get_evidence_bundle`, when interpreting the derived result. No source-data loss, crash, or security boundary crossing was observed. Ghidra engine execution was not performed. Static source inspection establishes provider applicability, but real Ghidra dossiers also carry separate unresolved-flow and classification caveats. This report does not establish that real Ghidra comparisons lose every warning about indirect calls. The dossier-caveat control demonstrates that independent caveats survive. ### REA version 6.4.0 (main at 58300885207133422af235e0f2b10658cf958b03) ### Runtime and platform Node 26.10.0; macOS 27.0 arm64 ### Target and artifact context Synthetic canonical `analyze_function` Evidence, with synthetic Mach-O artifact paths and digests and an explicitly synthetic provider identity. All input records are created inline. Each dossier declares its empty caller and callee sets available. No executable artifact is opened, no target is executed, and no Ghidra installation is required. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence ```text {"label":"complete-diagnostic","callsStatus":"unchanged","callsLimitations":[],"comparisonLimitations":[],"claimStatus":"pass","claimLimitations":["Artifact identity is unavailable for this observation."],"diagnosticPresentInComparison":false,"diagnosticPresentInVerification":false} {"retainedSourceDiagnosticPresent":true} ``` The first line is the complete-diagnostic case. The supplied diagnostic is `Only resolved Ghidra call references are returned; unresolved computed or indirect calls remain unknown, while function classifications distinguish thunks and externals.` The last line confirms source retention after the comparison and verification controls. ### Typed outcome or recovery expected The comparison's calls limitations and the downstream calls claim must carry the supplied diagnostic. Equal complete observed call sets should remain `unchanged`, and verification should retain its complete-set conclusion with that caveat. Partial coverage must remain `unknown` with its read-limit reasons and diagnostics. Complete coverage without diagnostics must not gain a fabricated caveat. The dossier-caveat control must retain both the independent caveat and the coverage diagnostic. Original source Evidence must remain accessible. ### Analysis or suspected cause Source-derived at the reported baseline: `src/server/registerFunctionComparisonTool.ts:38-75` validates inline Evidence and reaches comparison. `src/domain/functionDossierEvidence.ts:25-28` computes call limitations through `src/domain/functionCallCoverage.ts:82-92`. The conditional at line 88 excludes diagnostics whenever coverage is complete. `src/domain/functionComparisonDimensions.ts:328-365` consumes that result when comparing calls. `src/domain/reconstructionVerification.ts:219-222` independently rereads retained source coverage through the same helper, so source retention does not restore the diagnostic in verification. Source-derived repair constraint: `src/domain/functionComparisonDimensions.ts:335-346` treats every call-coverage limitation as an equality blocker. Simply removing the helper's conditional would therefore turn a complete observed-set comparison into `unknown`, contrary to the documented distinction between caveats and incomplete coverage. Diagnostic preservation must respect that distinction. Source-derived Ghidra applicability, without engine execution: `bridge/ghidra/ReaGhidraBridge.java:1539-1654` emits dossier call coverage, and `bridge/ghidra/ReaGhidraBridge.java:3373-3416` supplies the diagnostic on complete coverage. `src/ghidra/GhidraFunctionValues.ts:445-486` preserves the declared field, and `src/ghidra/GhidraProviderClient.ts:853-861` and `src/ghidra/GhidraProviderClient.ts:952-959` carry it into provider execution. Separate dossier caveats are supplied at `bridge/ghidra/ReaGhidraBridge.java:1610-1622`. ### Additional context Related reports [#2222](https://github.com/morluto/rea/issues/2222), [#2951](https://github.com/morluto/rea/issues/2951), [#2980](https://github.com/morluto/rea/issues/2980), [#2326](https://github.com/morluto/rea/issues/2326), and [#1964](https://github.com/morluto/rea/issues/1964) address incomplete-coverage verdicts, missing producer declarations, primitive warning generation, or graph/path caveat classification; this report requires retaining an already supplied complete-coverage diagnostic in comparison and verification while preserving valid observed-set equality.
bsakaguchi 2026-10-15 18:31:22 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

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

Delivered on main in fffb07419.

One limitation list mixed descriptive diagnostics with equality blockers and dropped complete-coverage diagnostics. Their owner now separates those facts; comparisons block only on actual uncertainty while Evidence retains diagnostics on every result path.

Validation: Function comparison and reconstruction regressions, including complete equality with diagnostics and unresolved function paths. Real Ghidra execution was not performed. Full exact-revision qualification passed.

<!-- gh-comment-id:6177639114 --> @morluto commented on GitHub (Oct 14, 2026): Delivered on main in [fffb07419](https://github.com/morluto/rea/commit/fffb0741936067530d1ce9777461cd53e87398c2). One limitation list mixed descriptive diagnostics with equality blockers and dropped complete-coverage diagnostics. Their owner now separates those facts; comparisons block only on actual uncertainty while Evidence retains diagnostics on every result path. Validation: Function comparison and reconstruction regressions, including complete equality with diagnostics and unresolved function paths. Real Ghidra execution was not performed. Full exact-revision [qualification](https://github.com/morluto/rea/actions/runs/38629313022) passed.
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#1132
No description provided.