brick/docs/research/language-correctness.md
trvon 46698cd87d
Some checks failed
build / build-linux (pull_request) Successful in 1m3s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
docs: state resolution rules and limits as the code now implements them
The audit found README claims the code did not back: resolution was said
to respect lexical namespace everywhere (Python/Swift matched a
repo-wide unique name, Rust types their leaf name), "ambiguous targets
stay external" (not for rival using-directives or #else stubs), Dart
imports were said to resolve (no Dart symbol ever did across files), and
"C/C++" hid that C went through the C++ grammar.

The README now describes the fixed behaviour and its remaining limits:
per-language visibility rules (Python imports, Swift module-wide names,
Dart imported libraries without show/hide), Rust type identity by
declaring file, preprocessor alternatives excluded from resolution,
using-directive ambiguity, the C grammar for .c, Fold report
validation and producer-gated symbolic lane, lossy UTF-8 decoding,
diagnostic counts and empty-scan reporting, check recomputing metrics,
low call-site coverage on large C++ code, no virtual-override fan-out,
and unrecognized Catch2 TEST_CASE bodies. The research note lists the
pinned C grammar.
2026-09-24 20:21:29 -06:00

6.3 KiB

Language correctness work

The attached September 4 review is the acceptance scope: source-relative imports, language/scoped resolution, comment and string exclusion, symlink containment, C++ inline functions/constructors, JS arrows/default exports/methods, TS interfaces and generics, Dart multiline methods, Rust const functions and impl ownership, and Fold absolute path aliases. Each item needs positive and clean-negative public-model tests and a passing quality gate under the default environment.

Experiment contract:

{
  "hypothesis": "Grammar-based source extraction and scoped resolution remove the reported false edges and recover missing declarations and owners",
  "owner": "source extractor and resolver; separate filesystem and Fold path fixes",
  "fixtures": ["tests/languages.rs", "tests/fixtures/languages"],
  "expected": {
    "increases": ["labeled declaration recall", "labeled dependency precision and recall"],
    "preserves": ["unrelated stable IDs", "schema 4 JSON contract", "heuristic resolution confidence", "P4 and imported evidence lanes"]
  },
  "decision": "promote the covered default syntax extractor; retain heuristic resolution and explicit limits"
}

Declaration ownership fixes intentionally change identities for previously misowned methods. Removal of false edges and recovery of real functions can change cycle, isolation, and fan metrics; no health weights are changed.

Acceptance evidence

tests/languages.rs exercises every attached concern through the public scanner:

Concern Regression evidence
Wrong relative imports Existing local JS/TS/Dart paths resolve despite duplicate basenames; C++ parent-relative includes resolve; missing paths stay external
Cross-language/scoped false edges Same-file language/owner lookup, namespace separation, explicit imported aliases, parameter shadowing, private/type-only negatives
Comments and strings Clean-negative C++ raw strings, JS templates, TS URL strings, Dart triple strings, Rust raw strings
Symlink escape Outside directory/file links, internal aliases, and cycles are skipped with relative diagnostics
C++ inline functions/constructors Exact constructor/method parents and three body calls; no declaration-name calls
JS and TS syntax Arrows, default exports, methods, interfaces, generics, and TSX expression bodies
Dart multiline method Method has class parent and owns its helper call
Rust const/impl Const function, distinct type-owned methods, stable IDs after unrelated insertions; unresolved impl cannot create cyclic ownership
Fold absolute alias src/fold.rs tests existing root aliases while rejecting outside and excluded files; original default-tempdir test passes

The grammar versions are pinned in Cargo.toml and Cargo.lock: C 0.24.2 (.c files), C++ 0.23.4, JavaScript 0.25.0, TypeScript/TSX 0.23.2, Dart 0.2.0, Rust 0.24.2, with the Tree-sitter Rust runtime at 0.26.13. Upstream API/grammar references: C++, TypeScript, Dart. Building these grammar crates requires a C compiler in addition to pinned Rust.

Repeated baseline/candidate experiment

tests/fixtures/languages/labels.json is authored independently of scanner output. It enumerates 33 symbols with ownership and 12 dependency relationships across 13 files, stratified as C++, JS, TS, TSX, Dart, and Rust. Every emitted declaration and dependency participates in exact comparison, including clean negatives.

The original HEAD was archived and built separately under build/language-baseline-src / build/language-baseline-target. Three baseline scans and three candidate scans use the same absolute corpus root:

Targeted corpus result Original extractor Candidate
Correct symbols 16 / 33 33 / 33
Missing symbols 17 0
Correct dependencies 1 / 12 12 / 12
Unexpected dependencies 29 0
Missing dependencies 11 0
Full JSON stable over three repeats yes yes

Raw baseline JSON/HTML, archived-source hash, executable hash, corpus provenance, resolved plan, and results live under build/benchmarks/source_languages/baseline. Candidate runs live in timestamped directories under build/benchmarks/source_languages; the quality gate writes a fresh three-repeat run with Git working-tree fingerprint, raw models, command logs, latency, and RSS. These are targeted regression results, not language-wide precision or performance claims. The retained lexical_smoke benchmark also passes after the changes.

The policy integration fixture now uses the explicit Rust path crate::storage::db::query() and a public target. Its former unqualified reference between unrelated files depended on the global-name bug. The gate still verifies one real forbidden dependency, and MCP/policy evidence tests expect the new grammar-plus-heuristic backend string without weakening lane/confidence checks.

Remaining scope boundaries

No compiler type checking, macro expansion, generated-source discovery, dynamic dispatch, overload resolution, or full build/package configuration is claimed. Member calls remain unresolved without receiver evidence. Package specifiers, tsconfig aliases, Rust grouped-use bindings, and C++ cross-translation-unit resolution still need adapters. Anonymous callbacks without a declaration name are attributed to the enclosing named function. These limits are documented rather than silently converting uncertain targets into known dependencies.

Schema 4 needs no new reader behavior: the same graph/evidence contract carries the new facts and optional attributes. Corrected owners and scoped unknowns have intentional identity changes; unrelated simple declarations retain their IDs. P4 stays on its existing independent frontend and evidence paths.

Validation commands: cargo fmt --check, cargo test, cargo clippy --all-targets -- -D warnings, ./scripts/quality-gate.sh, and python3 tests/benchmarks/runner.py self-test. The quality gate includes optional P4 tests/lint, Python harness tests, the three-repeat source plan, and existing diff/policy/MCP harness self-tests. Use the default environment; no TMPDIR workaround is required. The final log is build/language-quality-gate.log.