[GH-ISSUE #6860] [Bug] Reference-source language detection mislabels capital .C and .M suffixes #4200

Closed
opened 2026-10-31 00:47:38 +00:00 by bsakaguchi · 2 comments
Owner

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

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

import-reference-source reports conventional C++ widget.C as language: "C" and Objective-C++ widget.M as language: "Objective-C". Both incorrect labels propagate into the graph's languages index and summary. Byte-identical .cpp and .mm controls receive the correct C++ and Objective-C++ labels. Full and summary source-CLI calls all exit 0.

Reproduction

From the source checkout below, with its locked dependencies already present, save this as /tmp/reference-capital-suffixes.mjs. The exact script body ran once with scratch paths; only those temporary paths are normalized in the command. It exercises the registered public source CLI in full and summary modes. It does not compile or execute any input source.

node --import ./node_modules/tsx/dist/loader.mjs \
  /tmp/reference-capital-suffixes.mjs "$PWD" /tmp/reference-capital-suffixes-fixtures
import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { pathToFileURL } from 'node:url';
const [repo, out] = process.argv.slice(2);
const { createCli, closeCliJavaScriptResources } = await import(pathToFileURL(join(repo, 'src/cli.ts')).href);
const cpp = 'template<class T> struct Box { T value; };\n';
const objcxx = cpp + '@interface Widget\n@end\n';
const cases = { capital_C: ['widget.C', cpp], cpp_control: ['widget.cpp', cpp], capital_M: ['widget.M', objcxx], mm_control: ['widget.mm', objcxx] };
try {
  for (const [name, [filename, source]] of Object.entries(cases)) {
    const root = join(out, name);
    await mkdir(root, { recursive: true });
    await writeFile(join(root, filename), source);
    const outputs = [];
    for (const args of [[], ['--detail', 'summary']]) {
      let stdout = '', exit = 0;
      await createCli({ REA_LOG_LEVEL: 'silent' }).serve(
        ['import-reference-source', root, ...args, '--json'],
        { env: {}, exit: code => { exit = code; }, stdout: text => { stdout += text; } },
      );
      const value = JSON.parse(stdout);
      await writeFile(join(out, `${name}-${args.length ? 'summary' : 'full'}.json`), stdout);
      outputs.push({ exit, value });
    }
    const full = outputs[0].value, summary = outputs[1].value;
    console.log(JSON.stringify({ case: name, exit: outputs.map(item => item.exit), path: full.entries[0].path, language: full.entries[0].language, languages: full.languages, summary_languages: summary.languages, sha256: full.entries[0].sha256 }));
  }
} finally { await closeCliJavaScriptResources(); }

Expected behavior

Preserve conventional case-sensitive suffix meanings: .C means C++, while .M means Objective-C++. Keep lowercase .c and .m as C and Objective-C. GCC's official filename-language documentation explicitly distinguishes these literal capital suffixes. The executed .cpp and .mm controls show that REA already supports the corresponding language labels. This expectation concerns ordinary suffix-based detection without an explicit compiler-language override.

Impact and scope

The demonstrated defect is descriptive language metadata in full graphs and summaries. Original paths, byte counts, hashes and source classifications remain available. A tree containing only widget.C is listed as containing C and no C++; the matching .M fixture similarly omits Objective-C++ from its language inventory. No downstream parser, analysis or execution consequence was demonstrated, so this report conservatively assesses the observed scope as P3. Real-project prevalence and other platforms were not measured.

REA version

Package metadata 6.7.0; immutable main source archive at 96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9. The parent investigation confirmed 6.7.0 as npm latest. These observations concern the stated source runtime, not an executed installed tarball.

Runtime and platform

Node.js v24.22.1 (repository-pinned runtime), existing locked tsx 4.23.15; Linux 7.2.8-9-omarchy x86_64. No native analysis provider was required.

Target and artifact context

Four self-authored inert directories, each containing one UTF-8 source file with no compiler configuration or explicit language override. The .C/.cpp pair is byte-identical, as is the .M/.mm pair. No compilation or target execution occurred.

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

Observed output from the exact script body (exit contains the full and summary statuses):

{"case":"capital_C","exit":[0,0],"path":"widget.C","language":"C","languages":["C"],"summary_languages":["C"],"sha256":"fd2b55b63deb722b6339f8daaf3d43b54983580fceca247a53a96ab39bd26ffb"}
{"case":"cpp_control","exit":[0,0],"path":"widget.cpp","language":"C++","languages":["C++"],"summary_languages":["C++"],"sha256":"fd2b55b63deb722b6339f8daaf3d43b54983580fceca247a53a96ab39bd26ffb"}
{"case":"capital_M","exit":[0,0],"path":"widget.M","language":"Objective-C","languages":["Objective-C"],"summary_languages":["Objective-C"],"sha256":"f82023ff4aa43f490e31ae557b5d9f91fe308107d33aabdbf54e56e15107571f"}
{"case":"mm_control","exit":[0,0],"path":"widget.mm","language":"Objective-C++","languages":["Objective-C++"],"summary_languages":["Objective-C++"],"sha256":"f82023ff4aa43f490e31ae557b5d9f91fe308107d33aabdbf54e56e15107571f"}
  • Expected source: GCC's suffix definitions and the two byte-identical controls.
  • Failure source: public source CLI with actual reader, importer, graph and summary projection; no handler or filesystem mocks.
  • Evidence provenance: observed.
  • Local verification: reproduced.
  • Reproduction completeness: complete for full and summary source-CLI output. Packaged executable/dispatcher replay and downstream consumers were not tested.

Public reachability is through CLI registration, the production importer and full/summary selection. The generic overall inventory limitation is unrelated to the retained language value; no complete-inventory claim is made.

Typed outcome or recovery expected

For these conventional fixtures, retain language: "C++" for widget.C and language: "Objective-C++" for widget.M, with the same language values in their graph and summary indexes. Preserve source bytes and paths. No repair was implemented.

Analysis or suspected cause

Source-derived: language detection lowercases the original extension before lookup, erasing the meaningful distinction between .C/.c and .M/.m. The import entry producer stores that result; graph language derivation collects it, and the summary copies that index. This explains the same mislabel at all three surfaces.

Additional context

The supplied open-title corpus was checked before probing. Saved GitHub connector searches covered open and closed issues for reference language/classification, uppercase/capital suffixes, detectReferenceSourceLanguage, and Objective-C++ reference imports. Exact reference/language and case/language title searches returned no matches in either state. No matching report surfaced. Related closed #2604 concerns a generated-directory classification; open #5619 concerns Git ignore-case selection. Neither addresses retained language labels.

AI-assisted research and drafting: Codex. No human-review attestation is made. No installation, source change, compiler run, build, broad test suite, commit, pipeline or filing occurred. NOT_ENOUGH_INFO: introducing revision, last known good release, packaged runtime behavior and downstream impact. The draft is frozen after writing; no post-draft bug rerun or second review was performed.

Triage assessment

  • Impact level: P3
  • Assessment status: supported
  • Impact basis: The observed difference is incorrect descriptive language metadata in otherwise retained source inventories and summaries; no consequential downstream behavior change was established.
  • Workaround status: available
  • Workaround basis: Both outputs preserve the original case-sensitive filenames. A consumer can interpret .C as C++ and .M as Objective-C++ using the documented mapping, without changing the selected source tree; the byte-identical controls demonstrate the correct labels.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6860 ## 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 `import-reference-source` reports conventional C++ `widget.C` as `language: "C"` and Objective-C++ `widget.M` as `language: "Objective-C"`. Both incorrect labels propagate into the graph's `languages` index and summary. Byte-identical `.cpp` and `.mm` controls receive the correct C++ and Objective-C++ labels. Full and summary source-CLI calls all exit 0. ## Reproduction From the source checkout below, with its locked dependencies already present, save this as `/tmp/reference-capital-suffixes.mjs`. The exact script body ran once with scratch paths; only those temporary paths are normalized in the command. It exercises the registered public source CLI in full and summary modes. It does not compile or execute any input source. ```sh node --import ./node_modules/tsx/dist/loader.mjs \ /tmp/reference-capital-suffixes.mjs "$PWD" /tmp/reference-capital-suffixes-fixtures ``` ```javascript import { mkdir, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { pathToFileURL } from 'node:url'; const [repo, out] = process.argv.slice(2); const { createCli, closeCliJavaScriptResources } = await import(pathToFileURL(join(repo, 'src/cli.ts')).href); const cpp = 'template<class T> struct Box { T value; };\n'; const objcxx = cpp + '@interface Widget\n@end\n'; const cases = { capital_C: ['widget.C', cpp], cpp_control: ['widget.cpp', cpp], capital_M: ['widget.M', objcxx], mm_control: ['widget.mm', objcxx] }; try { for (const [name, [filename, source]] of Object.entries(cases)) { const root = join(out, name); await mkdir(root, { recursive: true }); await writeFile(join(root, filename), source); const outputs = []; for (const args of [[], ['--detail', 'summary']]) { let stdout = '', exit = 0; await createCli({ REA_LOG_LEVEL: 'silent' }).serve( ['import-reference-source', root, ...args, '--json'], { env: {}, exit: code => { exit = code; }, stdout: text => { stdout += text; } }, ); const value = JSON.parse(stdout); await writeFile(join(out, `${name}-${args.length ? 'summary' : 'full'}.json`), stdout); outputs.push({ exit, value }); } const full = outputs[0].value, summary = outputs[1].value; console.log(JSON.stringify({ case: name, exit: outputs.map(item => item.exit), path: full.entries[0].path, language: full.entries[0].language, languages: full.languages, summary_languages: summary.languages, sha256: full.entries[0].sha256 })); } } finally { await closeCliJavaScriptResources(); } ``` ## Expected behavior Preserve conventional case-sensitive suffix meanings: `.C` means C++, while `.M` means Objective-C++. Keep lowercase `.c` and `.m` as C and Objective-C. GCC's [official filename-language documentation](https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html) explicitly distinguishes these literal capital suffixes. The executed `.cpp` and `.mm` controls show that REA already supports the corresponding language labels. This expectation concerns ordinary suffix-based detection without an explicit compiler-language override. ## Impact and scope The demonstrated defect is descriptive language metadata in full graphs and summaries. Original paths, byte counts, hashes and source classifications remain available. A tree containing only `widget.C` is listed as containing C and no C++; the matching `.M` fixture similarly omits Objective-C++ from its language inventory. No downstream parser, analysis or execution consequence was demonstrated, so this report conservatively assesses the observed scope as P3. Real-project prevalence and other platforms were not measured. ## REA version Package metadata `6.7.0`; immutable main source archive at `96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9`. The parent investigation confirmed 6.7.0 as npm latest. These observations concern the stated source runtime, not an executed installed tarball. ## Runtime and platform Node.js v24.22.1 (repository-pinned runtime), existing locked tsx 4.23.15; Linux 7.2.8-9-omarchy x86_64. No native analysis provider was required. ## Target and artifact context Four self-authored inert directories, each containing one UTF-8 source file with no compiler configuration or explicit language override. The `.C`/`.cpp` pair is byte-identical, as is the `.M`/`.mm` pair. No compilation or target execution occurred. ## Interface CLI ## Earliest failure stage Artifact or evidence registration ## Relevant output or evidence Observed output from the exact script body (`exit` contains the full and summary statuses): ```jsonl {"case":"capital_C","exit":[0,0],"path":"widget.C","language":"C","languages":["C"],"summary_languages":["C"],"sha256":"fd2b55b63deb722b6339f8daaf3d43b54983580fceca247a53a96ab39bd26ffb"} {"case":"cpp_control","exit":[0,0],"path":"widget.cpp","language":"C++","languages":["C++"],"summary_languages":["C++"],"sha256":"fd2b55b63deb722b6339f8daaf3d43b54983580fceca247a53a96ab39bd26ffb"} {"case":"capital_M","exit":[0,0],"path":"widget.M","language":"Objective-C","languages":["Objective-C"],"summary_languages":["Objective-C"],"sha256":"f82023ff4aa43f490e31ae557b5d9f91fe308107d33aabdbf54e56e15107571f"} {"case":"mm_control","exit":[0,0],"path":"widget.mm","language":"Objective-C++","languages":["Objective-C++"],"summary_languages":["Objective-C++"],"sha256":"f82023ff4aa43f490e31ae557b5d9f91fe308107d33aabdbf54e56e15107571f"} ``` - Expected source: GCC's suffix definitions and the two byte-identical controls. - Failure source: public source CLI with actual reader, importer, graph and summary projection; no handler or filesystem mocks. - Evidence provenance: observed. - Local verification: reproduced. - Reproduction completeness: complete for full and summary source-CLI output. Packaged executable/dispatcher replay and downstream consumers were not tested. Public reachability is through [CLI registration](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/cli/utilityCommands.ts#L279-L342), the [production importer](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/cli/utilityCommands.ts#L364-L373) and [full/summary selection](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/cli/utilityCommands.ts#L434-L436). The generic overall inventory limitation is unrelated to the retained language value; no complete-inventory claim is made. ## Typed outcome or recovery expected For these conventional fixtures, retain `language: "C++"` for `widget.C` and `language: "Objective-C++"` for `widget.M`, with the same language values in their graph and summary indexes. Preserve source bytes and paths. No repair was implemented. ## Analysis or suspected cause Source-derived: [language detection](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/domain/referenceSourceClassification.ts#L336-L349) lowercases the original extension before lookup, erasing the meaningful distinction between `.C`/`.c` and `.M`/`.m`. The [import entry producer](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/application/ReferenceSourceImportEntries.ts#L338-L351) stores that result; [graph language derivation](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/domain/referenceSourceGraph.ts#L299-L311) collects it, and the [summary](https://github.com/morluto/rea/blob/96ea32b7e4e28d3c9cd79a1de4b8e1ba3b4244e9/src/domain/referenceSourceSummary.ts#L69-L78) copies that index. This explains the same mislabel at all three surfaces. ## Additional context The supplied open-title corpus was checked before probing. Saved GitHub connector searches covered open and closed issues for reference language/classification, uppercase/capital suffixes, `detectReferenceSourceLanguage`, and Objective-C++ reference imports. Exact reference/language and case/language title searches returned no matches in either state. No matching report surfaced. Related closed [#2604](https://github.com/morluto/rea/issues/2604) concerns a generated-directory classification; open [#5619](https://github.com/morluto/rea/issues/5619) concerns Git ignore-case selection. Neither addresses retained language labels. AI-assisted research and drafting: Codex. No human-review attestation is made. No installation, source change, compiler run, build, broad test suite, commit, pipeline or filing occurred. NOT_ENOUGH_INFO: introducing revision, last known good release, packaged runtime behavior and downstream impact. The draft is frozen after writing; no post-draft bug rerun or second review was performed. ## Triage assessment - Impact level: P3 - Assessment status: supported - Impact basis: The observed difference is incorrect descriptive language metadata in otherwise retained source inventories and summaries; no consequential downstream behavior change was established. - Workaround status: available - Workaround basis: Both outputs preserve the original case-sensitive filenames. A consumer can interpret `.C` as C++ and `.M` as Objective-C++ using the documented mapping, without changing the selected source tree; the byte-identical controls demonstrate the correct labels.
Author
Owner

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

I plan to preserve the conventional case-sensitive .C / .M language identities at the existing shared classification owner, while retaining lowercase .c / .m and the current case-folded fallback for other extensions. I will check both the complete import graph and its committed CLI summary, including same-byte .cpp / .mm controls and preserved source hashes. No C/C++ execution or new provider is involved. If someone is already working on this scope, please let me know so we can coordinate; this is not a claim of assignment or maintainer approval.

<!-- gh-comment-id:6372820841 --> @gongfpp commented on GitHub (Oct 23, 2026): I plan to preserve the conventional case-sensitive .C / .M language identities at the existing shared classification owner, while retaining lowercase .c / .m and the current case-folded fallback for other extensions. I will check both the complete import graph and its committed CLI summary, including same-byte .cpp / .mm controls and preserved source hashes. No C/C++ execution or new provider is involved. If someone is already working on this scope, please let me know so we can coordinate; this is not a claim of assignment or maintainer approval.
Author
Owner

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

Resolved by github.com/morluto/rea@f2e5fd148a. Original .C/.M suffixes are handled before case folding; the public CLI fixture checks full graph and summary with lowercase and conventional suffix controls. Validation: tests/boundary/cli/referenceSourceModuleSemantics.test.ts passed in the recorded round2/3 execution; this review did not rerun tests. Coverage is limited to the cited control; no broader real-provider, Windows or performance claim.

<!-- gh-comment-id:6376104583 --> @morluto commented on GitHub (Oct 23, 2026): Resolved by https://github.com/morluto/rea/commit/f2e5fd148a85fa737302dd194a33172c4561093e. Original .C/.M suffixes are handled before case folding; the public CLI fixture checks full graph and summary with lowercase and conventional suffix controls. Validation: `tests/boundary/cli/referenceSourceModuleSemantics.test.ts` passed in the recorded round2/3 execution; this review did not rerun tests. Coverage is limited to the cited control; no broader real-provider, Windows or performance claim.
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#4200
No description provided.