fix/audit-findings #5

Merged
trevon merged 14 commits from fix/audit-findings into main 2026-09-25 02:39:30 +00:00
2 changed files with 41 additions and 15 deletions
Showing only changes of commit 46698cd87d - Show all commits

docs: state resolution rules and limits as the code now implements them
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

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.
trvon 2026-09-24 20:21:29 -06:00
Signed by: trevon
GPG key ID: 38686EA797D7A8A7

View file

@ -6,8 +6,8 @@ elements, and dependency edges show calls, imports, and inheritance. The same
model is emitted as versioned JSON for other tools, including a future Fold
integration.
The default extractor uses pinned Tree-sitter grammars for Rust, Dart, C/C++,
JavaScript/JSX, and TypeScript/TSX. Python and Swift retain the lexical preview;
The default extractor uses pinned Tree-sitter grammars for Rust, Dart, C
(`.c`), C++ (including headers), JavaScript/JSX, and TypeScript/TSX. Python and Swift retain the lexical preview;
P4_16 retains its separate lexical and optional pilot paths. Declarations are
Syntactic evidence. Calls, imports, and inheritance retain Heuristic target
resolution with backend, confidence, and source location, independently of
@ -32,8 +32,16 @@ Layer Fold findings onto the building:
--json fold.brick.json \
--html fold.brick.html
A report must be a SARIF log or a Fold findings report; anything else is an
error. Findings keep Fold's symbolic lane only when the report names Fold as its
producer (`tool.name` / `tool.driver.name`); other producers' findings are
imported, never symbolic. Findings without a file location are diagnosed, and
SARIF `file://` URIs are decoded before matching.
Fold artifact paths are normalized lexically across `/`, `\\`, `.`, and `..`
components before exact repository-relative matching. Absolute paths are
components before exact repository-relative matching; a path with `..` that
exists in this checkout follows the filesystem instead, so `link/..` resolves
through the symlink. Absolute paths are
accepted only beneath the model's scan root (including existing filesystem
aliases whose canonical targets are beneath that root); leading traversal and unrelated
suffix paths remain diagnostics. Findings for excluded, generated, or genuinely
@ -152,26 +160,43 @@ Brick extracts syntax, without compiler type checking or build configuration.
Macro expansion, overload resolution, dynamic dispatch, generated code, and
full package/build-system resolution remain outside the default frontend.
Malformed syntax produces diagnostics; recoverable sibling facts remain visible.
A file with invalid UTF-8 is decoded lossily with a diagnostic; files with NUL
bytes are skipped as binary. `build` prints diagnostic counts, and a scan that
finds no supported source says so. `check` recomputes metrics from the graph
(stored metrics are never trusted) and fails a model with no scanned source.
Its score is not proof of correctness, maintainability,
or security. Use the component metrics and evidence records; do not rank teams
or repositories by the composite alone.
Resolution respects language, file, declaration ownership, and lexical namespace.
Relative JS/TS and Dart imports resolve against the importing directory; missing
paths never fall back to unrelated basenames. Explicit JS/TS named/default import
bindings, module-scoped Rust grouped/aliased imports, and module-qualified Rust
public calls can resolve across files.
Grammar-based resolution respects language, file, declaration ownership, and
lexical namespace. Relative JS/TS and Dart imports resolve against the importing
directory (Dart `package:<own package>/` against `lib/`); missing paths never
fall back to unrelated basenames. Explicit JS/TS named/default import bindings,
module-scoped Rust grouped/aliased imports, module-qualified Rust public calls,
and public top-level Dart names from imported libraries can resolve across files
(Dart `show`/`hide` combinators are not modelled). The lexical preview resolves
Python names in the calling file, then in files it imports; Swift names in the
calling file, then by a module-wide unique name (Swift files of one module see
each other without imports).
C++ calls resolve through the include closure: a header prototype pairs with
its definition in another translation unit, lookup walks class (including
in-repository bases) and namespace scopes outward, and `static`/anonymous
definitions stay file-local. C++ and Rust member calls resolve only through an
explicitly declared receiver type (parameter, local, field, `this`/`self`,
smart pointer, or `Self`-returning constructor) and carry
`source.resolution`. Calls inside Rust expression macros (`assert!`, `format!`,
definitions stay file-local. Declarations in `#elif`/`#else` branches stay in
the graph (`source.preprocessor-branch: alternative`) but are never call
targets, because Brick does not evaluate conditions; several `using`
directives that nominate different declarations make a call ambiguous. C++ and
Rust member calls resolve only through an explicitly declared receiver type
(parameter, local, field, `this`/`self`, smart pointer, or `Self`-returning
constructor) and carry `source.resolution`. Rust types are identified by their
declaring file, so same-named types in different modules resolve through the
caller's `use` binding or stay ambiguous. Calls inside Rust expression macros (`assert!`, `format!`,
`vec!`, ...) are recovered by re-parsing and carry `source.extraction`.
Every unresolved call edge records `source.unresolved-reason`, and
`metrics.resolution` reports per-language call-site coverage. Ambiguous
targets stay external. Bare package specifiers, tsconfig aliases, Rust
`metrics.resolution` reports per-language call-site coverage; read the graph
with that coverage in mind (on a large C++ repository only a minority of call
sites resolve). Ambiguous targets stay external. Virtual calls resolve to the
declared type's method only (overrides are not fanned out), and Catch2
`TEST_CASE` bodies are not yet recognized as functions. Bare package specifiers, tsconfig aliases, Rust
wildcard/block-local binding expansion, Cargo workspace module paths,
`compile_commands.json` include paths, and compiler-grade dispatch need further
adapters. File fan-out remains an observation rather

View file

@ -42,7 +42,8 @@ change cycle, isolation, and fan metrics; no health weights are changed.
| 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.23.4,
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++](https://docs.rs/tree-sitter-cpp/0.23.4/tree_sitter_cpp/),