Skip to content

[TIER 1] Class detection is 0% across apex/csharp/fortran/solidity despite near-perfect function detection #1264

Closed

Description

@squid-protocol

Summary

Four languages (apex, csharp, fortran, solidity) show 0% class detection (found_classes=0) in their respective language-crucible corpora, yet each has excellent function detection (89-100% recall). This pattern suggests a shared root cause rather than four independent bugs -- file as ONE issue to investigate the common cause first.

Related epic: #1261

Per-language measurements

Language Files Real Classes Found Classes Recall Real Functions Found Functions Recall
apex 4 4 0 0% 38 38 100%
csharp 6 19 0 0% 558 553 99%
fortran 6 11 0 0% 121 119 98%
solidity 7 7 0 0% 95 85 89%

Data from tests/tree_sitter_accuracy_baseline_<lang>.json files.

Why this pattern is suspicious

Action (investigate the common cause first)

  1. Before modifying any of the four class_start regexes independently, determine:

  2. If it's a process gap: Document what validation was/wasn't done, add it to the harden-language-extraction skill's checklist, and ensure all future language additions include class_start corpus validation.

  3. If the regexes are genuinely broken: Each language's class_start may need separate investigation, but file SEPARATE sub-issues rather than expanding this one. Do NOT treat this as four independent PRs -- keep them coordinated to avoid the same mistake repeating.

Notes

  • Function detection working proves the corpus and measurement tool are sound.
  • This pattern (100% function recall, 0% class recall on identical files) is rare enough to suggest something systematic about the class_start regexes specifically, not the measurement method or the languages.

Activity

  1. added
    bugUnintended behavior or logic failure in the engine
    testingUnit, integration, and E2E pipeline verification
    core-engineModifications to the central physics and parsing engine
    threat: false-negativeAccuracy tuning: Engine missed a bypass or vulnerability
    priority: highCore feature broken, but workarounds exist
    on Aug 11, 2026
  2. squid-protocol commented on Aug 12, 2026

    @squid-protocol
    OwnerAuthor

    Root cause found: it's not the four class_start regexes -- they're fine

    Verified each of the four languages' class_start regex in language_standards.py directly against sample text: all match correctly in isolation (tested apex/csharp/fortran/solidity patterns standalone with realistic input). So hypothesis #3 in the issue body ("regexes are genuinely broken") is ruled out, and hypothesis #1's specific guess (unvalidated class_start patterns at rollout) is also not quite it -- the patterns themselves are sound.

    The actual bug: detector.py's named-entity class extractor never uses class_start at all.

    function_data/class_data (the tables the tree-sitter accuracy harness diffs against) are populated from two structurally different code paths:

    • Functions: detector.py pulls matches from rules.get("func_start") -- the real per-language regex from language_standards.py -- see e.g. detector.py:1503-1571.

    • Classes: detector.py has a second, entirely separate "FAST CLASS EXTRACTOR" (detector.py:554-560) that never touches rules["class_start"]. It's one hardcoded, language-agnostic regex:

      class_pattern = re.compile(
          r"^\s*(?:export\s+|public\s+|abstract\s+)?(?:class|struct|interface|trait|enum)\s+([a-zA-Z0-9_]+)(?:\s*(?:\(|extends\s+|implements\s+|:\s*)([a-zA-Z0-9_]+))?",
          re.MULTILINE,
      )

      This is what actually builds the classes list that becomes class_data rows, class_count, and the method→class linkage. class_start's own matches only ever feed the numeric signal count in equations/counts (risk-scoring class_start frequency) -- they never reach the named-entity table the accuracy harness reads.

    So the harness's found_classes metric was never testing the four languages' hand-tuned class_start regexes to begin with -- it's been testing this one hardcoded fallback for every language, the whole time.

    Confirmed against the real corpus (not just synthetic samples)

    Ran class_pattern directly against language-crucible's actual apex/csharp/fortran/solidity files:

    Language Why it structurally can't match
    apex Real declarations use compound modifiers before class -- public with sharing class Foo, global class Foo. The pattern's modifier group is a single non-repeating optional slot ((?:export|public|abstract)?), and global/with sharing aren't in it at all. 0/0 matches on the corpus.
    csharp Same shape: real code is internal sealed class, internal sealed partial class, private sealed class -- internal/sealed/partial/private aren't in the 3-word alternation, and even legal combos like public abstract class fail because the slot only fires once. 0/0 matches.
    fortran Fortran's class-equivalents are MODULE/TYPE ::/SUBMODULE -- none of those keywords exist in the pattern's keyword set (class|struct|interface|trait|enum) at all. Structurally unreachable, not a modifier issue. 0/0 matches.
    solidity Real OOP unit is contract (and library) -- neither keyword is in the set either (only interface happens to overlap). The pattern did fire 10 times on the corpus, but only by accidentally matching nested struct definitions (ProposalCore, AddressSlot, etc.) -- zero overlap with the 7 real contract/interface/library names ground truth counts, so found_classes stayed 0 and those 10 became noise in extra_classes instead.

    This is bigger than 4 languages

    Surveyed all class_start regexes in language_standards.py against the universal pattern's (?:export|public|abstract)?(?:class|struct|interface|trait|enum) shape. Languages whose real class-equivalent keyword or modifier grammar falls outside that shape -- and would fail the same way if/when they get a tree-sitter baseline -- include at least: go (type X struct), rust (pub struct -- pub isn't in the modifier set), ruby (module), perl (package/role), cobol (PROGRAM-ID/CLASS-ID), haskell (data/newtype/type), zig (const X = struct), matlab (classdef), scala/kotlin/swift/dart/groovy (compound modifier stacks like C#/apex), abap, tcl, scheme, ada, livecode. These four just happen to be the ones currently measured (they have tree-sitter baselines); the same silent failure is very likely already present, unmeasured, everywhere else that isn't python/javascript-shaped.

    Recommendation

    Don't touch the four class_start regexes -- they're not the bug. The fix belongs in detector.py's class extractor: replace (or fall back from) the hardcoded universal class_pattern with the per-language rules.get("class_start"), mirroring exactly how func_start is already consulted at detector.py:1503. That's a single shared code path serving two different purposes today (numeric signal count vs. named-entity extraction) that need to be reconciled -- worth scoping as its own issue given the blast radius above, separate from any per-language follow-ups.

    Given the size of this (core extraction pipeline, ~20+ potentially-affected languages, both the numeric-signal and named-entity paths need reconciling), I'd suggest this becomes the primary tracked issue for epic #1261's class-detection thread rather than filing four separate per-language regex fixes as originally proposed in this issue's Action item #3.

  3. added this to the v2.4.8 milestone on Aug 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginecore-engineModifications to the central physics and parsing enginepriority: highCore feature broken, but workarounds existtestingUnit, integration, and E2E pipeline verificationthreat: false-negativeAccuracy tuning: Engine missed a bypass or vulnerability

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions