Repository navigation
sync: integrate upstream checkpoint 13B - #30
Conversation
A Go selector call x.foo() whose receiver the Go LSP cannot type falls through to the generic registry resolver, which binds it by bare short name to an arbitrary same-named project symbol. Stdlib calls are the worst case: f.Close() on an *os.File gets a CALLS edge to whatever project Close wins candidate ranking (measured on a real Go repo: confidence 0.11, 15 candidates; suffix_match + unique_name were 36% of all CALLS edges, and one 14-line stdlib-only function got 3 out of 3 false outbound edges). Extend the TS/JS receiver-aware guard (DeusData#592/DeusData#606) to Go: - extract_calls.c: flag Go call_expression with a selector_expression callee as is_method, mirroring the TS/JS member_expression flag. - registry.c: add cbm_go_suppress_weak_method_match. Unlike the TS/JS drop-list, field_type_hint is KEPT (Go struct fields carry declared types, so the hint is receiver-aware — lrp_go_s8_field_type_hint), and unique_name is dropped only when its confidence carries the import-unreachability penalty (the stdlib-hijack shape); an unpenalized lone candidate inside the caller's import closure never enters the field-type-hint upgrade and must survive. - pass_calls.c / pass_parallel.c: feed the Go gate next to the TS/JS one; the drop still defers to the emit path so service/route/HTTP edges stay main-identical. Reproduce-first: pipeline_go_receiver_suppresses_weak_method_edge is RED without the extractor flag (the f.Close -> project Close edge exists) and GREEN with it; typed same-package calls, bare local calls and import-qualified cross-package calls still resolve. The old extraction contract test used Go as the flag-exempt language — Python takes that role, and extract_go_selector_call_flags_is_method pins the new behavior. Signed-off-by: Ilya Brykau <ilya.brykau@orca.security>
A Go method's QN was the flat package form (proj.pkg.method) — the receiver was ignored, so every same-name method in a package collided on one QN and the graph upsert kept exactly one node. Measured on a real Go repo: 20 Process/Name methods across 15 files kept 2 nodes; 9 different Task() methods fused into one chimera node carrying all nine bodies' call edges; 19 structs pointed DEFINES_METHOD at a single shared method node; a _test.go mock Close outranked the production Close in the dedupe tie-break. The upsert's own comment calls kind-disambiguated QNs 'the real cure'. Qualify the QN with the receiver type (proj.pkg.Recv.method), the same shape as Go interface members and the C++ out-of-line method path right below it in extract_func_def: - extract_defs.c: def.qualified_name = parent_class + name whenever the receiver type resolves; go_receiver_type_name becomes the shared cbm_go_receiver_type_name (exported via helpers.h) so both sides of the contract use one formula. - extract_unified.c (compute_func_qn): mirror branch for method_declaration, so method-body calls keep exact source attribution instead of degrading to File-node fallback (calls_find_source). - Consumers already agree: pxc_build_lsp_def passes the def QN and parent_class (receiver_type) verbatim into the Go LSP registries, and check_go_class_implements explicitly supports class-qualified method QNs (its path (b)). Side effect: resolve_same_module's exact module.name hash no longer matches concrete methods, which kills the conf-0.9 false edges where an interface-typed call bound to an unrelated same-package method. Fixes DeusData#1909 Signed-off-by: Ilya Brykau <ilya.brykau@orca.security>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…hod-receiver-qn Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Brings the branch up to date with main (989 commits since the 2026-09-28 merge). Four conflicts, all additive on both sides: - pipeline.h / registry.c: main added cbm_suppress_weak_import_bound_call (DeusData#2127) at the same anchor as cbm_go_suppress_weak_method_match; both kept. - pass_calls.c / pass_parallel.c: drop_plain_call now chains the Go selector guard and main's Python import-binding guard, in the same order in both resolvers. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Review follow-up for DeusData#1907 (asks from the 2026-09-28 review): - pipeline_go_receiver_parallel_suppresses_weak_method_edge: parallel twin of pipeline_go_receiver_suppresses_weak_method_edge. The guard is wired into pass_parallel.c as well as pass_calls.c, but the four-file fixture only runs the sequential resolver, so the parallel hunk was bound by no test. The fixture is shared (write_go_receiver_fixture) and padded with 52 Go files past MIN_FILES_FOR_PARALLEL, with CBM_WORKERS=4, in the shape of the Python parallel twin. - registry.c: cbm_go_suppress_weak_method_match builds on the shared weak_short_name_strategy list and narrows it in two places only (field_type_hint kept, unique_name only when penalized). Behaviour is unchanged; weak_call_guards_share_one_drop_list now binds the Go guard to the shared list too. - test_extraction.c: the flag-exempt comment names the current flag set (Perl, Python, TS/JS/TSX and Go) and Rust as the exempt language. Refs DeusData#1906 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…usData#1041) A controller routed with ASP.NET Core attributes produced no Route node and no HANDLES edge: [Route("api/[controller]")] class QuotesController [HttpGet("{symbol}")] -> nothing [HttpPost] + [Route("orders/{id}/confirm")] -> nothing Root cause: the route extractor only knew decorator calls (Flask, FastAPI, Express-style) and Spring/JAX-RS annotation names. HttpGet/HttpPost/.../ Route matched none of them, the class-prefix join ran only for Java and Kotlin, and ASP.NET templates are relative ("{symbol}", "api/[controller]"), while the path filter and ensure_one_decorator_route accept only '/'-prefixed paths. DeusData#1759 made every stacked C# attribute visible as DECORATES but did not turn any of them into a route. Fix: a C# path in push_method_def, next to the JVM prefix join, that reads the attributes of the action and of its class: - HttpGet/Post/Put/Delete/Patch/Head/Options with or without a template, [Route] on the class and on the action, [AcceptVerbs("GET", Route = "x")]; qualified names and the "Attribute" suffix are accepted. - [controller] is the class name minus "Controller", [action] the method name minus "Async" (the ASP.NET Core default) or its [ActionName], and [area] comes from [Area]. - A template is relative to the class prefix; "/" or "~/" overrides it. - Constraints, defaults and optional markers reduce to the bare parameter ("{id:int}", "{code:regex(^\d{{3}}$)}", "{page=1}" -> "{id}", "{code}", "{page}"), so the path is '/'-led and canonicalizes like every other decorator route. This works with both the current cbm_route_canon_path and the depth-matched variant. An action without a verb or [Route] attribute stays route-less, and other C# attributes never become routes. Known limits, unchanged in kind from the JVM path: one route per action (a stacked [HttpGet] + [HttpHead] records the first), and a [Route] inherited from a base controller in another file is not applied. Proof on jellyfin/jellyfin (shallow clone, depth 1, 208c278): Route nodes 0 -> 360, HANDLES 0 -> 388, e.g. GET /Items/{itemId}/Images/{imageType} <- ImageController.GetItemImage. Tests (edge_types_probe, exact Route-name sets): the DeusData#1692 controller, the DeusData#1041 AuthController, [controller]/[action]/[ActionName]/[AcceptVerbs] tokens, "/" and "~/" overrides with constraints plus a controller without a class [Route], and a non-controller C# control. Refs DeusData#1692 Refs DeusData#1041 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…hod-receiver-qn Brings the branch up to date with the updated DeusData#1907 head, which carries main 9f85f10 and the DeusData#1907 review follow-up. One conflict in tests/test_pipeline.c, at the shared anchor: keep this branch's pipeline_go_method_caller_keeps_lsp_join and the shared write_go_receiver_fixture plus its sequential and parallel probes. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Review follow-up for DeusData#1913 (asks from the 2026-09-28 review), plus one finding from the review of the updated head: - store.h: CBM_INDEX_FORMAT_VERSION 3 -> 4. Every Go method QN changes (pkg.method -> pkg.Recv.method), so an index built before this change and refreshed incrementally would mix flat and receiver-qualified method nodes, with the old fused nodes keeping their stale edges. The bump routes such an index through one full rebuild. - pipeline_go_method_caller_keeps_lsp_join: the by-name assertion would also pass for a binding onto the decoy other.Decoy.helper. The test now pins the edge by QN suffix on both ends (.svc.Repo.Install -> .svc.Repo.helper) with an lsp_* strategy, and asserts no edge to the decoy. - extract_defs.c: the receiver-qualified def QN is Go-only. The templ grammar is Go-derived and reaches the same receiver branch, but its call-scope QN (compute_func_qn) stays flat, so a templ method would get a def QN no call names and its calls would degrade to the File node. extract_templ_method_qn_matches_call_scope pins def QN == call scope. - pass_semantic.c: the check_go_class_implements comment no longer describes Go method QNs as flat. Refs DeusData#1909 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
cbm_fqn_compute_source_lang returns NULL only when the module QN cannot be built (arena exhaustion). The receiver-qualified branches then passed that NULL to "%s". Both sides now fall back to the flat QN together, so the def and its calls still agree. Allocation-failure path only; no change on any normal run. (Raised in our security review of the updated head.) Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
A package-relative from-import (`from . import x`, `from .. import x`,
`from . import x as y`) has a module made only of dots. The extractor joined
it to the imported name with another '.', recording "..x" for `from . import x`:
the parent package. The import resolver then missed the real binding and fell
to the symbol-name guess (the lexicographically first same-named definition in
the project), so the import map, and the Python LSP binding that consumes it,
sent every call to an unrelated function at import_map / lsp_callable_alias
confidence. On home-assistant, 7,175 caller/callee pairs bound to another
integration's function (webhook's `async_register` to accuweather's).
Join without the extra separator when the module already ends in '.'.
`from .m import f` (".m.f") and absolute imports are unchanged.
Tests: python_package_relative_import_paths (extraction: the recorded paths);
pipeline_python_package_relative_imports{,_parallel} (all three forms resolve
to the own / parent package, never to the namesake that sorts first, without a
name guess, on both resolvers); pipeline_python_from_import_bare_call_issue1237
{,_parallel} (DeusData#1237 guard: a plain from-import and bare calls bind the imported
def and keep it across a re-index that adds a file).
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…-routes-v2 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…eusData#1692) An ASP.NET MVC GET form action and its POST submit share one method name, so both overloads collapse into one Method node whose merged properties keep only one route. The parallel resolver emitted each definition's route at node creation and kept both; the sequential one rebuilt decorator routes from the merged properties afterwards and kept only the last. On six ASP.NET corpora the sequential run lost 28 HANDLES edges this way. Both resolvers now call cbm_pipeline_emit_def_route() per definition at node creation (the parallel block moved into it unchanged), so the venues agree. The later decorator-route pass still skips handlers it already has. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The parallel resolver re-picks a multi-candidate registry match through try_field_type_hint. That helper capitalizes the receiver VARIABLE name and accepts any candidate whose QN contains it as a substring: `t.Run` on a *testing.T became `T` and bound a project `TBench.Run`. The sequential resolver has no such step. The Go selector guard treated field_type_hint as receiver-aware and kept it, so the same weak pick it drops in sequential mode survived in parallel mode under a new name. On caddy + prometheus, parallel and sequential CALLS diverged by 1,684 (this branch) and 5,560 (with receiver-qualified method QNs, which put type names into more QNs). At base the gap is 84. SCIP precision of Go field_type_hint is 0.016 at base. Go no longer takes the hint. The guard keeps field_type_hint on the shared weak list, and the fixture of both twins now pins the `t.Run` case. A typed field call (lrp_go_s8, `s.repo.Find()`) resolves through the Go LSP and is unaffected. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
RED on its own: push_nested_class_nodes does not look through decorated_definition. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…art CI selection fix DeusData#2684) Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
push_nested_class_nodes descended into field/template/declaration and conditional wrappers but not into Python's decorated_definition, so a decorated nested class (`@dataclass class Meta:` inside a class) was never extracted: no Class node, no Method nodes, and the calls in it fell to the FILE node. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…-routes-v2 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…e LSP RED on F11a alone: py_process_class walks a nested class under the module, so none of its LSP rows join the method nodes. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
py_process_class qualified every class under the module, so a class nested in a class (proj.m.Outer.Inner, the QN extraction gives it) was walked as proj.m.Inner: its methods' LSP rows carried callers no node has and never joined. A typed-parameter call in such a method got no edge at all, a self call fell to unique_name and a constructor to same_module. A nested class, decorated or not, is now walked under its enclosing class through the same py_process_class_in the function-local classes use. Tests: pipeline_python_nested_class_methods_resolve(_parallel). Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…-routes-v2 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
A PHP file's import evidence is written as complete only when every `use` either resolved or is proven absent. A global-namespace class use such as `use Exception;` had no absence proof, so one such line left the whole file's bindings unknown, and its project imports reached the PHP LSP as File QNs again (the DeusData#2520 path). An unaliased global class use is now proven absent when no PHP file declares a class-like symbol of that name (Class, Interface, Trait, Enum, File or Module; namespaced ones included, so the proof stays conservative). Aliased global uses keep the old, unknown verdict. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
DeusData#1913 makes Go method nodes receiver-qualified (<dir>.<Recv>.<Method>). The Go doc-link model still let every method claim the flat node <dir>.<name>: - doclink_go.c go_scan_method pushed a claim record; - doc_links_go.c go_add_claim put it in the flat table. So a type, function or value that shares its name with a method in its directory became a graph_gap ("lost its node to the method"), although the graph now gives it that node. Base reports the same graph_gap for this shape, because there the method really did take the node. So this completes DeusData#1913's QN scheme for one of its consumers; it is not a regression DeusData#1913 causes. - A method record now carries w `-`: it claims no flat name. - The resolver no longer enters methods into the flat table. Methods are found through their receiver (the member table), which was already the first lookup. - The flat fallback in go_method_node is now unreachable. It stays, with a comment saying so. Corpus, before = this branch's tree, par x2, r1 == r2: - terraform: graph_gap rows 9 -> 0, doc-link MENTIONS 528 -> 536 (+8, -0). All 8 new edges were judged correct: e.g. [AbsProviderConfig] now lands on the type, not on the method RootProviderConfig.AbsProviderConfig. - vault, prometheus: unchanged. - prometheus incremental == full for MENTIONS. - The 3 -> 4 index-format bump already forces a full rebuild, so no stored scope blob mixes the two meanings. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
) main's Go doc-link tests were written against flat Go method QNs, where `(A) Close` and `(B) Close` shared one node `alpha.Close`. That is the fused-node defect DeusData#1913 removes. The expectations move to the new scheme, and each changed assertion pins an edge onto, or a count of, the receiver-qualified node (production: the previous commit and DeusData#1913): - sources: RefM's source is p.pkg.S.M, not p.pkg.M. - forms: [Widget.Run] lands on alpha.Widget.Run, [beta.Thing.Do] on beta.Thing.Do. - plain_text, struct_fields: Run's doc is the source alpha.Widget.Run. - lookup_order: two alpha.Run sources and beta.Promoted named no node any more, so they held vacuously. They are now alpha.Widget.Run and beta.Embedded.Promoted. The alias links land on beta.Thing.Do and alpha.Deep10.End. - node_owner, the positive contract that replaces the fused case: - two Method nodes, alpha.A.Close and alpha.B.Close, and none named alpha.Close; - [A.Close] and [B.Close] are edges, not graph_gap rows; - each method's own [Target] is an edge from its own doc line (9 and 12), with no unresolved row; - the type Open keeps alpha.Open: [Open] is the type (no graph_gap), [B.Open] is the method, and UsesOpen has 2 targets. - scope_blob: - method records carry w `-`; - swapping two methods of one name no longer changes the blob; - a func/type pair swap still does (new case); - the k1-k3 records follow (a method neither keeps nor contests a name); - a new k4 keeps the "two on one line contest it" rule covered with a var and a const. - incremental_equals_full: - [b.T.M], [b.W.Name] and [b.V.Name] all resolve, and U.M's [Target] is an edge; - removing T.M breaks only [b.T.M]; - swapping V.Name and W.Name moves nothing and is now an ordinary closure repair instead of a forced full rebuild. - scope_delta_rules: - a method/function swap is LOCAL; - removing the method of such a pair is LOCAL with the name "Open" (a member left); - new func/type cases keep the GLOBAL keeper-change rules covered for swap and removal. - workers_agree: [p01.T3.Close] now resolves (exact edge, no row). The graph_gap reason stays covered by the named Shared assertion: one function declared by every file of a package, which is still a gap. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…wn-absent fix(php): prove an unaliased global class use absent from the project
…rofiles The read-only analysis profile and the fast scout profile serve the graph subagents (codebase-memory-auditor, codebase-memory-scout). Their server instructions listed tools only. Like the default profile, they now state as facts which structural questions the graph answers (where a symbol is defined, who calls a function, what it calls, and for analysis also call chains, data flow and change impact), keywords first: analysis 190 -> 648 characters, scout 199 -> 427, well within Claude Code's 4,096-character cut. The profile names, check_index_coverage and the absence of index_repository are unchanged. Stacked on DeusData#2698. Refs DeusData#509 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…ile-scope Conflict in tests/test_edge_types_probe.c: both sides added tests after et_handles_exact (the R1 + R2 DATA_FLOWS tests and the DeusData#1692 ASP.NET overload test); both are kept. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…iscovery feat(mcp): load the structural tools upfront and say what the graph answers
…uctions feat(mcp): state the structural questions in the scout and analysis profiles
…index fix(php): index trait methods by receiver while flattening (DeusData#1265)
…y-namespace-effect-allowlist Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Conflict in tests/test_pipeline.c: this branch and DeusData#2703 (on main) each registered two Go tests at the same place in the suite list; both pairs are kept. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…nto fix/go-method-receiver-qn Brings main 32445b2 in through the refreshed DeusData#1907. No conflicts. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
When an agent greps for a symbol that the graph knows, the PreToolUse augmentation (Grep, Glob and Bash searches) lists the matching symbols. It now closes with one line that is cbm's own statement, outside the untrusted symbol block, naming the graph tools for the usual next question: [codebase-memory] For these symbols, trace_path lists callers and callees, get_code_snippet returns the exact source, and search_graph finds related symbols by name. The line carries no repository-derived value and is stated as facts, as Claude Code asks of hook context. It is appended at the string's real end into reserved room: the list loop's offset can run past its cap when a row is truncated, so appending at that offset could have written past the buffer. Searches without a hit, errors and non-search events are unchanged. Refs DeusData#509 Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…le-scope fix(routes): scope DATA_FLOWS pairing at the test-file boundary (R1 + R2)
…g-future-facts fix(python): docstrings and __future__ imports are no namespace barriers
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…w-up-hint feat(hooks): name the graph follow-up tools in every search augmentation
…eceiver-qn fix(extract): receiver-qualify Go method QNs
…t-allowlist fix(python): a top-level call of a harmless same-module function keeps the package namespace
Integrate pinned checkpoint 4c80d89 as a true merge. Preserve native CLI operations and record source adaptations and focused validation.
|
Caution Review failedThe pull request is closed.
Tip 🎯 Customize your risk assessments
✅ Automatic approvals, with your rules
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
Independent review update (2026-11-02): 13B is a 119-commit upstream integration with 47 changed files; keep draft. Verify runtime graph edge identity and false-positive/false-negative changes across Python TYPE_CHECKING/C3, PHP traits, Go receiver-qualified calls, ASP.NET routes, and LSP payload compatibility. Confirm old index format-4 data and semantic coverage version-9 behavior across incremental/full reindex. Verify CLI-first boundaries (no MCP server, transport or test reinstatement), native hook command guidance, installer limits and manual-only GitHub Actions. Prior 1,502 focused ASan/UBSan tests are worker-reported, not Jenkins at current SHA. Require independent source review, targeted regression evidence, native Windows where applicable, and Jenkins exact-head qualification before merge. Coordinate with #31 lifetime-lock fix; no assumption that #31 is qualified. |
|
Re-review: head unchanged ( |
Scope and ancestry
Draft, pending independent review and qualification. Integrates upstream checkpoint 13B from fork base
27b731cec45e2353303738ac6d8e77acbef42b7cto upstream4c80d89edf1283cfeaa7e60ecbf40c9d2eb2b689. True merge408d24dfb657c280ec36e7e7cc913c1ef1612b6ahas those exact parents; branch heada7170e7e5adds the integration and continuation receipts. The upstream range comprises 119 commits. No unmerged PR dependency; base is main.Shared work includes Python import and C3 resolution, PHP trait and global-use resolution, Go receiver identity and multiple returns, ASP.NET routes, extraction and registry corrections. CLI hook guidance was adapted to native commands; MCP server and its tests are excluded. Review of the 47-file change and security/semantic effects is not complete. Installer resource limits and Jenkins-only policy must remain intact. Index format remains 4; semantic coverage version is 9 according to the receipt. Existing-index compatibility still needs independent review.
Verification and outstanding work
The prior integration receipt
docs/upstream-sync/13b.mdrecords a successful development build and 1,502 focused ASan/UBSan tests, with two additional focused tests passing. Those are worker-reported receipts, not an independent review or Jenkins qualification. At45d0b6d37, the GitHub Actions policy checker and its four tests passed; the policy checker also passed at the current documentation-only successor; Actions triggers are manual/reusable only and Jenkins remains the automatic CI authority. Jenkins discovery, full gate at the exact head, native Windows checks, cross-platform compatibility, and independent source review are pending. No Jenkins result is claimed for this head. Main remains 900 commits behind upstream; this branch is 781 commits behind. The prior 13C–13H work is separate and unqualified, and an unresolved 13I merge is preserved separately.Known open high-priority work includes daemon lifetime-lock DeusData#2207, ADR reindex persistence DeusData#2315/DeusData#2864 and the remaining priority list; their status must be reviewed independently. Keep this PR draft until those applicable issues, security and graph semantics are assessed and all required gates are met.