Commit graph

57 commits

Author SHA1 Message Date
trvon
40bea78f9a
fix(cpp): recover receivers from local initialization
Some checks failed
build / build-linux (push) Has been cancelled
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Recover parenthesized object declarations only when their apparent parameters resolve to earlier visible value bindings. Respect recovered scope, alias hiding and prototype shadowing instead of manufacturing receiver types.

Preserve heuristic confidence and source provenance. Add positive and negative regressions plus a three-repeat labeled initialization fixture to the quality gate.

Validation: cargo fmt --check and ./scripts/quality-gate.sh passed.
2026-10-11 18:19:08 -06:00
27d53a1b03 Merge pull request 'fix: review follow-ups for #5 and the Swift lexical preview' (#8) from fix/review-followups into main
Some checks failed
build / build-linux (push) Successful in 1m6s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Reviewed-on: #8
2026-09-25 13:33:40 +00:00
trvon
67d1980001
Merge main into fix/review-followups: move the Dart import note into docs/resolution.md
Some checks failed
build / build-linux (pull_request) Successful in 1m8s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
2026-09-24 21:14:26 -06:00
trvon
324900287b
fix(dart): honour import prefixes, show/hide and one level of export
Some checks failed
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
build / build-linux (pull_request) Has been cancelled
Problem: a bare call in a Dart file resolved against every imported
library. An `import 'a.dart' as p;` still bound `foo()` to a.dart's foo,
`hide` and `show` combinators were ignored, and a name re-exported through
a barrel library (`export 'impl.dart';`) never resolved.

Fix: record each Dart import/export directive with its `as` prefix and
show/hide lists. A bare name resolves only in libraries imported without a
prefix whose combinators let it through, plus that library's own exports
that also let it through (one level).

Test: tests/dart_imports.rs covers a prefixed, a hiding, a showing and a
barrelled import; it failed on the prefixed case before this change.
2026-09-24 21:11:48 -06:00
trvon
04653788fa
fix(rust): keep impls written on a qualified path when leaf names collide
When several files declare the same type leaf name, rust_method keeps
only the impls of the type a call site means, asking each impl's file
which `Foo` it means. An impl in a third file written as
`impl crate:🅰️:Foo` resolved nothing (that file has no `Foo`
declaration or `use` binding), so its methods were dropped and
`x.run()` on an `a::Foo` read "member-not-found". It resolved before #5.

The extractor now records the impl's type path when it is written as
one (`impl_type_path`, generic arguments removed), the method index
keeps it, and the impl filter resolves that path to its declaring file
before falling back to the file's own view of the leaf name. Glob
imports (`use super::*`) are still not expanded; such an impl stays
unresolved rather than guessed.

Test: with `Foo` declared in a.rs and c.rs and `impl crate:🅰️:Foo` in
ext.rs, `x.run()` on `crate:🅰️:Foo` resolves to ext.rs's `run`; it
failed before this change.
2026-09-24 21:07:34 -06:00
trvon
3fbb9275a5
perf(scan): index import edges once instead of scanning per file
imported_paths found the file node with a linear scan of all nodes and
then filtered all edges, for every Python/Dart file it built a set for:
O(files x (nodes + edges)) during resolution, about 10^10 comparisons
for 10k files and a million edges.

Imports edges are now indexed by source file on first use and the file
node is looked up by its stable id, as resolve_import already does. The
index is complete when first built: resolve_relationships resolves
every import before any call. Output is unchanged (all 124 tests pass).
2026-09-24 21:05:11 -06:00
trvon
67334bec59
fix(python): resolve relative, package and dotted imports to the right file
Since #5 Python calls resolve only through import edges, but the
lexical importer could not produce those edges for the common forms:

- `from .util import helper` never matched (the regex needed a leading
  letter), so the call went unresolved;
- `from pkg import f` looked up the stem "pkg" instead of
  pkg/__init__.py;
- `from x.common import f` failed when y/common.py also existed, and
  `from other.common import f` (a module the repository does not have)
  resolved to y/common.py by basename.

Imports now resolve Python-specifically: leading dots are relative to
the importing package, and a dotted name maps to `a/b.py` or
`a/b/__init__.py` from the repository root or `src/`. Only a
single-component name (`import foo`) may still fall back to a unique
module basename; a dotted name never does. `from . import x` stays
unresolved (the module is in the import list, not the name).

Tests (both failed before): relative, package and duplicate-stem imports
resolve their calls to pkg/util.py, pkg/__init__.py and x/common.py;
an unknown dotted module does not bind to y/common.py.
2026-09-24 21:03:08 -06:00
trvon
c3c7c6c3f4
fix(swift): give the lexical preview Swift's forms and mask block comments
Swift ran through the C-style lexical patterns, which never recognize
`func`. On a small file (`func realTarget()`, `func ghost()`, a class
method `caller` that calls `realTarget()` below a `/* ghost() */`
comment) the preview reported:

  a.swift -> ghost       (a.swift:2 declaration, a.swift:5 in a comment)
  a.swift -> caller      (its declaration line)
  a.swift -> realTarget  (its declaration line)

and missed the real call. Now:

  caller -> realTarget   (a.swift:7)

- Swift gets its own patterns: `func` declarations (with attributes and
  modifiers), class/struct/enum/protocol/actor/extension declarations
  (`class func` / `class var` are members, not classes), and imports.
- Block comments are masked across lines, nested as Swift allows, and a
  `/*` inside a string literal does not open one. The masker is salvaged
  from the unmerged language-parity branch (543bafc).
- Calls are attributed to their enclosing function through the existing
  brace-scoped scopes, now that functions are recognized.

Test: tests/swift_preview.rs (functions and a class recognized, the call
attributed to `caller`, nothing from comments, nothing from the file
node); it failed before this change.
2026-09-24 21:00:59 -06:00
trvon
d0d52edfd1
fix(check): warn, don't fail, when stored metrics differ from recomputed
`check` treated any difference between stored and recomputed metrics as
a gate failure, so a model written by an older brick (without the
`metrics.resolution` field, or with an older formula) always failed,
even with every threshold met. CI checking an archived or cached model
broke on upgrade.

The gate already uses recomputed metrics, so a mismatch is now a
stderr warning. Only fields present in both copies are compared, so a
missing newer field does not count as a mismatch. Tampered metrics
still cannot pass: the existing test's recomputed cycle count fails the
gate, and it still reports "stored metrics".

Test: a freshly built model with `metrics.resolution` removed passes
`check --min-score 0`; it failed before this change.
2026-09-24 20:57:08 -06:00
trvon
5a6f8b143a
refactor: one definition of "the model scanned a source file"
The empty-model condition was written three times: a scan.rs
diagnostic, a helper in main.rs for `build`'s warning, and the same
helper for `check`'s failure. They could drift. model.rs now owns
`has_source_files` (and `Building::has_source_files`), used by all
three. No behaviour change; the empty-scan CLI test still passes.
2026-09-24 20:57:07 -06:00
trvon
3a0f2adf59
fix(fold): decode SARIF escapes safely, lane per run, follow absolute symlinked paths
Three import fixes from review of #5:

- sarif_uri_path sliced `&rest[i + 1..i + 3]` by byte index, so a `%`
  followed by a multibyte character (`file:///src/%aé.c`) panicked the
  whole build, and from_str_radix accepted `%+1` as byte 0x01. Escapes
  are now decoded on bytes and only from two hex digits.
- Whether findings keep Fold's Symbolic lane was decided for the whole
  report with all(): a merged SARIF log with one Fold run and one CodeQL
  run demoted every Fold finding to Imported. The lane is now decided
  per SARIF run (per report for native findings), and the diagnostic
  names only the non-Fold producers.
- The rule that `..` after a symlinked directory follows the filesystem
  applied only to relative paths; `/root/linkout/../src/main.rs` and its
  file:// form still normalized lexically onto an in-repository file.
  Absolute paths that exist now resolve through the filesystem too.

Tests (each failed before this change): percent-escape decoding without
panics, per-run lanes in a merged SARIF, and absolute/file:// paths
through a symlinked directory.
2026-09-24 20:54:36 -06:00
8b1e52042e Merge pull request 'docs: trim the README and split usage, resolution and development out' (#6) from docs/readme-split into main
Some checks failed
build / build-linux (push) Successful in 1m5s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Reviewed-on: #6
2026-09-25 02:54:20 +00:00
trvon
4de9884a54
Merge main into docs/readme-split: carry #7's caller-status docs into the split
Some checks failed
build / build-linux (pull_request) Successful in 1m4s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
2026-09-24 20:53:21 -06:00
b160fea314 Merge pull request 'feat: add brick_callers and brick_uncalled caller-status queries' (#7) from feat/caller-status into main
Some checks failed
build / build-linux (push) Successful in 1m4s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Reviewed-on: #7
2026-09-25 02:51:17 +00:00
d7be35d7ef Merge branch 'main' into feat/caller-status
Some checks failed
build / build-linux (pull_request) Successful in 1m4s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
2026-09-25 02:51:04 +00:00
trvon
d88238c986
docs: trim the README and split usage, resolution and development out
Some checks failed
build / build-linux (pull_request) Successful in 1m4s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
The README had grown to 254 lines covering an overview, every command,
the Fold/SARIF and p4c import contracts, the P4 pilot, per-language
resolution rules, limits, schema history, development and the agent
skill. It is now a 70-line overview (what Brick is, evidence lanes,
languages, quick start, commands, limits, links), and the rest lives in:

- docs/usage.md: every command (build, render, check with diff and
  policy gates, mcp, setup), Fold/SARIF and p4c layering, the P4 pilot,
  and what the model contains.
- docs/resolution.md: per-language name resolution as the code now
  implements it, what is not handled, P4 limits, the regression corpus
  and schema version 4.
- docs/development.md: build and test commands, the quality gate, the
  toolchain pin, and the brick-sast skill.

Architecture docs are linked, not repeated. "What v0.1 provides" and
the milestone note are folded into usage.md and the roadmap pointer.
Every relative link and anchor resolves.
2026-09-24 20:42:00 -06:00
2a9716dac0 Merge pull request 'fix/audit-findings' (#5) from fix/audit-findings into main
Some checks failed
build / build-linux (push) Successful in 1m3s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Reviewed-on: #5
2026-09-25 02:39:30 +00:00
trvon
46698cd87d
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.
2026-09-24 20:21:29 -06:00
trvon
f9804976bc
perf(source): record parents during traversal instead of re-walking from the root
tree-sitter's `Node::parent` re-descends from the root, so each call is
O(depth), and `enclosing_function`, `lexical_scope` and
`parameter_shadows` walked ancestors through it for every call site and
declaration: extraction time grew quadratically with nesting depth
(sample profile: >90% of time in ts_node_parent under those three).

The main traversal now records each node's parent, and the three
ancestor walks look it up (falling back to `Node::parent` for nodes the
traversal skips, so results are unchanged).

Measured on one C++ file with a call nested N blocks deep (release,
macOS arm64): N=2.5k/5k/10k/20k took 0.26/1.05/4.24/16.8 s before;
after, 20k takes 0.02 s with the same nodes and call edge. The full
suite (111 tests) passes unchanged.
2026-09-24 20:19:35 -06:00
trvon
e03fa40ccc
fix(c): parse .c files with the C grammar
`.c` files were parsed with tree-sitter-cpp, so valid C that uses C++
keywords as identifiers (`int delete = 0; int new = 1;`, a parameter
named `class`) produced grammar-error diagnostics and lost symbols.

`.c` files now parse with tree-sitter-c (pinned =0.24.2, backend
`c:0.24.2`) while staying on the shared C/C++ extraction path, so C
sources and the headers they include still share one include/declaration
index. Headers (`.h`) keep the C++ grammar, which parses the C subset.

Test: cpp_xtu::c_sources_parse_with_the_c_grammar fails before this
change (grammar errors in util.c).
2026-09-24 20:14:21 -06:00
trvon
9f9fc560b7
fix(scan): decode non-UTF-8 source lossily instead of dropping the file
A single invalid byte, such as a Latin-1 `é` in a comment, made
`read_to_string` fail and the whole file and its symbols were skipped.

Files are now read as bytes: a NUL byte still marks a binary file,
which is skipped with a diagnostic; otherwise invalid UTF-8 is decoded
lossily (U+FFFD) and a warning diagnostic records it, so the file keeps
its symbols and calls.

Test: languages::a_non_utf8_byte_does_not_drop_the_whole_file fails
before this change (latin1.rs has no symbols).
2026-09-24 20:13:01 -06:00
trvon
4b2c873445
fix(fold): follow the filesystem for .. after a symlinked directory
Fold report paths were normalized lexically, so `linkout/../src/main.rs`
with `linkout` pointing outside the root attached to the repository's
`src/main.rs` although the OS path names a different file.

A relative path containing `..` that exists in this checkout is now
canonicalized (and must stay under the canonical root); paths absent
from the checkout, such as reports from another machine, keep the
documented lexical matching.

Test: fold::tests::parent_steps_after_a_symlinked_directory_follow_the_filesystem
fails before this change (the finding attaches to src/main.rs).
2026-09-24 20:12:13 -06:00
trvon
088ba3fb15
fix(fold): validate the report envelope and gate the Symbolic lane on Fold
The Fold report importer was schema-less and trusted self-description:
- `{"hello":1}` imported 0 findings with no diagnostic, like a clean run;
- findings without a file location were dropped silently;
- any JSON declaring backend "source" and confidence "proved"/"latent"
  got the Symbolic lane, whoever produced it;
- SARIF `file://` URIs (and %-escapes) never matched a scanned file.

Now a report must be a SARIF log (`runs`) or a Fold findings report
(`findings`), otherwise the import fails with "not a Fold report". The
Symbolic lane requires the producer to be Fold (`tool.name`, or every
SARIF run's `tool.driver.name`, equal to "fold", which is what Fold
writes); other producers' findings are imported in the Imported lane
with a diagnostic. An unsupported `output_version` and findings dropped
for lack of a location are diagnosed. `file://[localhost]` URIs lose
their scheme and are percent-decoded before path matching. Existing
tests that model Fold reports now carry Fold's real envelope.

Tests (fold::tests) failing before this change:
rejects_a_file_that_is_not_a_fold_report,
symbolic_lane_requires_a_fold_producer_not_a_self_declared_label,
sarif_file_uris_match_and_unlocated_findings_are_diagnosed.
2026-09-24 20:11:14 -06:00
trvon
a03c36969e
feat(dart): resolve calls through imported libraries and own package: URIs
A Dart import exposes a library's public top-level names without a
per-name binding, so the binding-based lookup never matched and no
cross-file Dart call resolved, even when the import itself did (pipe's
VerifyCommand::run lost loadProject, analyzeProject, verifyAnalysis and
decodeBaselineEntries).

After the lexical-owner walk and binding lookup fail, a Dart call now
resolves to the one public (not `_`-prefixed) top-level declaration of
that name in the libraries the file imports; several such declarations
make it `ambiguous`, none leaves it external. `package:<name>/x.dart`
imports resolve to `lib/x.dart` when `<name>` is the root pubspec's
package; other packages stay external. `show`/`hide` combinators are not
modelled (noted as a follow-up).

Test: languages::dart_calls_resolve_through_imported_libraries fails
before this change (helper stays not-visible); an unimported file and a
library-private name stay unresolved.
2026-09-24 20:09:01 -06:00
trvon
4bdae55923
fix(python,swift): keep calls in their function and resolve only visible names
Three lexical-preview bugs, reproduced on one probe:

- A blank or comment-only line in a Python function fell through to the
  brace-depth scope rule, which popped every open scope, so every call
  after the first blank line in a body was attributed to the file.
  Blank/comment lines now leave Python scopes unchanged.
- `class Child(Base):` matched the call pattern and produced a call edge
  from the file to Child. The declared class name is no longer a call
  on its own header line.
- Calls resolved to the only function with that name anywhere in the
  repository, imported or not (a NameError at runtime became an edge).
  Resolution now prefers the caller's file; Python then considers only
  files the caller imports (resolved import edges, cached per file);
  otherwise the call stays external. Swift keeps the module-wide unique
  name after the same-file check, because files of one Swift module see
  each other without imports. Imported bases resolve the same way, so
  `from pkg.b import Base` disambiguates `class Child(Base)`.

Test: languages::python_calls_keep_their_function_and_resolve_only_what_is_visible
fails before this change (go() had no call edges at all).
2026-09-24 20:07:34 -06:00
trvon
3cf4d7660a
fix(build,check): report empty scans instead of scoring them 100
A directory with no supported source (Go/Java only) built
"1 nodes / 0 edges; score 100.0" with no diagnostic, and
`check --min-score 90 --max-cycles 0` passed it. The one-line summary
also hid diagnostics entirely: the yams run's 7,428 warnings (505 files
with grammar errors) never appeared.

- scan records a warning diagnostic when no source file was scanned;
- `build` prints the diagnostic and warning counts in its summary and
  warns on stderr when the model is empty;
- `check` fails a model that contains no scanned source files.

Test: diff_cli::a_scan_with_no_supported_source_is_reported_and_fails_check
fails before this change (no diagnostic; check passes).
2026-09-24 20:04:00 -06:00
trvon
4c630ffeb1
fix(check): gate on recomputed metrics, not the stored copy
`brick check` read `metrics` from the model JSON and gated on them, so
setting `cycle_count` to 0 and `score` to 100 in the file turned a
failing `--max-cycles 0` gate into "passed" without changing the graph.

check now recomputes the metrics from the loaded nodes and edges and
gates on those; if the stored copy differs, that is itself a failure
("stored metrics do not match the graph"). Honest models recompute to
identical values, so existing gates are unchanged.

Test: diff_cli::check_recomputes_metrics_instead_of_trusting_the_file
fails before this change (the tampered model passes).
2026-09-24 20:02:04 -06:00
trvon
46bd3f50f1
fix(dart,cpp): generic type arguments are not base classes
The base walker descended into type-argument lists, so
`class MyBloc extends Bloc<Ev, St>` emitted inherits edges to Bloc, Ev
and St; on pipe, 39 of 145 Dart inherits edges (27%) pointed at type
arguments (e.g. `Command<int>` -> `int`). C++ `: public Base<Arg>`
shared the walker through `template_argument_list`.

The walker stops at `type_arguments` / `template_argument_list` /
`type_parameters`, and handles tree-sitter-dart's shape, where the
arguments are sibling `type` fields of `superclass` (only the first
names the base) and nested `type` children of a `type`.

Test: languages::generic_type_arguments_are_not_base_classes fails
before this change (["Bloc", "Ev", "St"]).
2026-09-24 20:00:46 -06:00
trvon
2b19142557
fix(cpp): never resolve calls into #elif/#else branches
Every preprocessor branch was indexed as live. In yams,
InternalEventBus.h guards spdlog with
`#if __has_include(<spdlog/spdlog.h>) ... #else namespace spdlog { stubs }`,
so 1,243 spdlog::warn/info/error call sites resolved to the fallback
stubs, which became the 4th and 5th highest fan-in nodes.

Brick does not evaluate conditions, so only the first branch is treated
as live: declarations and prototypes inside `#elif`/`#else` stay in the
graph (marked `source.preprocessor-branch: alternative`) but are not
definitions, declarations or classes for call resolution. Branches are
tracked textually from the directive lines, because conditions like
`__has_include(<x>)` leave tree-sitter-cpp with an error-recovered tree
that has no `preproc_else` node to find. Include-guard (`#ifndef`) code
is a first branch and still resolves.

Test: cpp_xtu::preprocessor_alternative_branches_are_not_call_targets
fails before this change (spdlog::info resolves into the #elif stub).
2026-09-24 19:58:55 -06:00
trvon
195d118702
fix(cpp): treat rival using-directives as ambiguous, not first-come
With `using namespace a; using namespace b;` and both `a::run` and
`b::run` declared, a call to `run` resolved to whichever directive came
first in file order and was labelled `using-directive`. In C++ that
call is ambiguous (or an overload choice Brick does not model).

Directives are now grouped: each `using N::x;` and `using namespace N;`
nominates at most one declaration (its innermost resolving scope), and
the call resolves only when exactly one distinct declaration is
nominated; otherwise it stays external as `ambiguous`.

Test: cpp_xtu::two_using_directives_naming_the_same_function_are_ambiguous
fails before this change; its single-directive case still resolves.
2026-09-24 19:53:10 -06:00
trvon
b281a52255
fix(rust): resolve methods on the type the caller means, not its leaf name
The Rust impl index keyed types by leaf name, so `a::Config` and
`b::Config` shared one `(Config, load)` entry and the inherent method
won: `use crate:🅱️:Config; c.load()` produced a `declared-receiver-type`
edge to `a::Config::load`.

The index now records which files declare each type name and the file
of every impl. When several files declare a name, a call resolves only
among impls of the type the calling file means (its own declaration,
then a `use` binding, then the only declaration); with no such binding
the call is left external as `ambiguous` instead of guessed. Unique
names behave as before.

Test: rust_methods::same_named_types_in_different_modules_resolve_through_use_bindings
fails before this change (edge to src/a.rs).
2026-09-24 19:51:11 -06:00
fb0dcdc19d Merge pull request 'feat: resolve C/C++ and Rust calls across files and typed receivers' (#3) from feat/cpp-rust-resolution into main
Some checks failed
build / build-linux (push) Successful in 1m4s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Reviewed-on: #3
2026-09-22 21:14:53 +00:00
trvon
6d4335d3ae
docs: record C/C++ and Rust resolution research and validation
Some checks failed
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
build / build-linux (pull_request) Has been cancelled
Adds the audit, literature rationale, experiment contract, labeled-corpus
results, Fold/Paperbridge/Brick/YAMS coverage and dead-code spot checks,
model changes, identity changes, and remaining limits.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 15:12:13 -06:00
trvon
d292b9f3f2
feat: add brick_callers and brick_uncalled caller-status queries
Agents asking "is this function used?" get resolved, unknown, or
unreferenced per function instead of a bare zero in-degree. Unknown lists
why callers may exist: same-name unresolved call sites (excluding foreign
receivers and macros), name references (callbacks, address-taken, macro
bodies), virtual/trait-impl/external-base/outside-class members, framework
attributes, implicit protocol invocations, entry points, test code,
incomplete parses, and, unless assume_closed_world is set, exported or
external-linkage functions. Unreferenced is a review candidate with an
explicit heuristic/compiler evidence basis, never a dead-code proof.

The queries are read-only over validated schema-4 models and return
complete canonical nodes and edges plus metrics.resolution coverage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 15:12:13 -06:00
trvon
7c664cb5a0
docs: describe C/C++ and Rust resolution limits and next stages
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
README limits now describe include-closure C++ lookup, declared-receiver
member resolution, Rust macro re-parsing, unresolved reasons, and
metrics.resolution, plus the remaining adapter gaps. The roadmap records
candidate edges, the Fold compiler call lane, and compile_commands/Cargo
module resolution as next stages; literature notes cite the call-graph and
name-resolution papers found through paperbridge.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 15:12:04 -06:00
trvon
48436f35b7
feat: resolve C/C++ and Rust calls across files and typed receivers
C++ calls now resolve through the include closure: header prototypes pair
with definitions in other translation units, lookup walks class (including
in-repository bases), namespace, and `using` scopes outward, and static or
anonymous-namespace definitions stay file-local. Member calls resolve only
through explicitly declared receiver types (parameters, locals, fields,
this, smart pointers, aliases); template parameters stay unknown. Calls
hidden by the most vexing parse are recovered, casts are no longer calls,
reference-returning and conversion-operator declarations are named
correctly, and benign `= {}` default-argument recoveries no longer drop
prototypes or flag files.

Rust method calls resolve through a crate-wide impl index for self, typed
parameters and lets, struct fields, Self-returning constructors, dyn
traits, and Type::/Self:: associated calls, with foreign imports and
generics never guessed. Calls inside expression macros are re-parsed.

Every unresolved call records source.unresolved-reason, weaker resolutions
record source.resolution/source.extraction, and metrics.resolution reports
per-language call-site coverage. Declarations gain facts consumed by
caller-status queries (qualified names, linkage, virtual, trait impls,
attributes, name references, parse-incomplete). C++/Rust External targets
include the reason in their identity; out-of-line C++ methods keep their
IDs.

Linear node/edge scans and per-node ancestor walks are replaced with
indexes, cutting a YAMS scan from 575 s to 23 s.

New labeled cpp_xtu and rust_methods corpora run three times in the
quality gate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-22 15:11:04 -06:00
trvon
050b1b105b
feat: support explicit cross-worktree structural diffs
Some checks failed
build / build-linux (push) Successful in 1m2s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
2026-09-05 12:34:35 -06:00
trvon
01836ba3f5
feat: resolve Rust grouped imports and module aliases
Some checks failed
build / build-linux (push) Successful in 1m9s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Expand module-scoped use trees into exact import paths and bindings. Resolve renamed public symbols and module aliases without global-name fallback; keep unknown and block-local bindings conservative.

Add positive and negative integration tests and an exact three-repeat import benchmark to the quality gate.
2026-09-04 23:11:19 -06:00
trvon
3fec92f10c
feat: make source graphs accurate across C++ JS TS Dart and Rust
Some checks failed
build / build-linux (push) Successful in 1m3s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Use pinned grammar frontends and scoped heuristic resolution to recover declarations and prevent false dependencies. Constrain filesystem traversal and normalize Fold root aliases.

Add exact multilingual fixtures, seventeen regression tests, and a three-repeat benchmark to the quality gate.
2026-09-04 23:05:06 -06:00
trvon
b074efd009
chore: ignore local Pi harness state
Some checks failed
build / build-linux (push) Successful in 1m1s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
2026-09-01 18:27:37 -06:00
trvon
2eabfe8376
docs: define architecture evidence and release contracts 2026-09-01 18:27:23 -06:00
trvon
a8c7cc22e5
test: add reproducible architecture benchmark campaign 2026-09-01 18:25:40 -06:00
trvon
1079a18993
feat: probe Tree-sitter P4 availability during setup 2026-09-01 18:25:21 -06:00
trvon
992f101316
feat: add evidence-aware architecture analysis 2026-09-01 18:18:30 -06:00
bb8b4ef4b3 Merge pull request 'bench: harden architecture scan evidence' (#1) from bench/yams-architecture-reproducibility into main
Some checks failed
build / build-linux (push) Successful in 38s
build / build-macos (push) Has been cancelled
build / release (push) Has been cancelled
Reviewed-on: #1
2026-08-30 22:09:34 +00:00
trvon
f26d541181
chore: remove tracked Python bytecode
Some checks failed
build / build-linux (pull_request) Successful in 35s
build / build-macos (pull_request) Has been cancelled
build / release (pull_request) Has been cancelled
2026-08-30 14:26:22 -06:00
trvon
b6e51e5076
docs: clarify architecture evidence boundaries 2026-08-30 14:26:22 -06:00
trvon
2f162372c2
bench: fingerprint benchmark working trees 2026-08-30 14:26:22 -06:00
trvon
e03c2a299b
fix(fold): normalize imported finding paths 2026-08-30 14:26:21 -06:00
trvon
8c73f39cc4
ci: use Forgejo artifact actions; disable unsupported cache
Some checks are pending
build / build-macos (push) Waiting to run
build / release (push) Blocked by required conditions
build / build-linux (push) Successful in 37s
2026-08-30 10:34:22 -06:00