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.
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.