Tracking issue for the Go / cgo / Go+C extraction work. Method: count a construct in source, count the same thing in the graph, treat any mismatch as a defect. Every item was minimised to a dummy fixture before filing, measured on one real Go + C/C++ repository (~1150 Go files, eBPF C probes, a Windows C++ driver — counts only), and carries a SQL detection recipe that works on any indexed repo. Each fix PR ships a reproduce-first test (RED proven before the change) and a fresh field census on the same tree.
Ledger — bugs
| Issue |
Defect |
PR |
State |
Measured effect |
| #1906 |
Weak short-name strategies fabricate CALLS for Go selector calls |
#1907 |
open, CI green |
suffix_match 3817 → 113, same_module 3267 → 224; weak share of CALLS 36.0% → 12.4%, lsp_* 8481 → 10672 (re-resolved, not deleted) |
| #1909 |
Method QNs ignore the receiver — same-name methods collapse onto one node |
#1913 |
open, CI green |
Close methods 15 → 86, Process 12 → 47, Task 1 → 8; kills the flat same_module key |
| #1910 |
Multiple init() per package collapse onto one QN |
#1915 |
open, CI green |
init nodes 7 → 29, matching source exactly |
| #1926 |
cgo's import "C" resolves to an arbitrary project symbol named C |
#1931 |
open, CI green |
27 false IMPORTS → 0 |
| #1927 |
field_type_hint binds by receiver variable-name substring, not declared type |
#1936 |
open, CI green |
1484 → 356; single-char receivers 376 → 0; Go→C/C++ 34 → 0; zero relocation |
| #1928 |
USAGE/WRITES/READS never consult the #725 cross-language guard (both resolvers) |
#1937 |
open, CI green |
Go→C/C++ WRITES 835 → 0, USAGE 1545 → 0; 6432 cross-language refs dropped, none same-language; CALLS/IMPORTS byte-identical |
| #1934 |
A Go import can resolve to a Function/Method (Strategies 1b + 3 are language-blind) |
#1938 |
open, CI green |
IMPORTS targets: Method 85 → 0, Function 4 → 0, Folder 2206 kept |
| #1935 |
Go struct fields never extracted (find_class_body stops one level above field_declaration_list) |
#1940 |
open, CI green |
0 → 4533 Field nodes with declared types; blank _ padding skipped |
| #1942 |
A bare Go reference binds a struct Field (found field-validating #1940) |
#1944 |
open, CI green |
USAGE onto Go fields 21308 → 0, WRITES 5191 → 0 |
Combined stack (#1937 + #1940 + #1944) vs main: USAGE 29198 → 21035, WRITES 2681 → 774, +4533 field nodes — the graph gets nodes and loses junk edges.
Ledger — design-shaped (awaiting maintainer ack, no PR)
| Issue |
Gap |
Damage |
| #1911 |
Build-tag twin files collide on one QN — draft PR #1946 (τ #-suffix, #495 pattern), ready on design ack |
2177 τ-suffixed nodes / 372 files; swallowed-twin files 319 → 281; CALLS +62 — no edge-mass loss |
| #1929 |
cgo invisible — draft PR #1947: //export → 22 export_linkage contracts (exact), C.* CALLS 1 → 0, preamble flagged in coverage; C-grammar preamble parse stays open |
39 call-shaped C.f( → 0 CALLS; 12 preamble functions → 0 nodes on main |
| #1930 |
Go chan/goroutines unmodelled — draft PR #1949: grammar-precise send/receive/select → gochan topology |
Channel nodes 2 → 205, EMITS 1 → 162, LISTENS_ON 2 → 256 on the measured repo; range/go/element-types deferred |
Ledger — CI
| Issue |
Problem |
PR |
State |
| #1952 |
test-windows-guards setup flake (nodes: None): counts read from list_projects, whose stats publish asynchronously — the index response carries them synchronously |
#1958 |
open; root cause reproduced off-CI deterministically, setup steps also retry once |
| #1959 |
CI never indexes Go end to end — the only binary-level harness fixtures are TS-only, which is where this whole defect family hid |
#1961 (stacked on #1958) |
open; polyglot fixture (structs, build-tag twins, cgo, channels) + Go-definition count in the path-equality gate; measured 28/46/12 defs, go=7, equal across ASCII/Latin-1/Cyrillic |
Merge order
Cross-cutting theme
One failure mode at every layer: a heuristic binds by name shape and nothing checks the language or what the name can denote. #1906 (CALLS, guarded) → #1927 (field_type_hint, exempted on a false premise) → #1928 (references, never guarded) → #1934 (imports, label-blind) → #1942 (references, label-blind). Guarding one relocates mass to the next unguarded one — which is why every fix PR above now carries negative/exact-count probes (ei_edge_count_is, zero-project-edge assertions, parallel-twin fixtures) rather than floor-only asserts, closing #1932's original test-infra gap in place.
Verified working (audit surface closed, no issues needed)
Generics (receiver-qualified QNs unwrap generic_type; no [ in any QN) · embedding + interface dispatch (lsp_embed_dispatch 42, lsp_interface_dispatch 79, fan-out via 434 IMPLEMENTS) · //go:linkname (body-less decls get nodes; callers bind lsp_direct) · defer/closures (attributed to the enclosing named function) · implicit interface satisfaction + method values (lsp_callable_alias) · TESTS edges and Variable coverage · internal import resolution (2206/~2242 same-module imports → correct package Folder; residual was #1934). Assembly (.s): untested — no fixtures in the measured repo.
Detection recipes (run on any indexed repo)
-- call-graph shape
SELECT json_extract(properties,'$.strategy') AS strategy, count(*) AS n,
round(avg(json_extract(properties,'$.confidence')), 3) AS conf
FROM edges WHERE type='CALLS' GROUP BY 1 ORDER BY n DESC;
-- node recovery vs source: grep -rc '^func init()' --include='*.go' .
SELECT count(*) FROM nodes WHERE name='init';
-- swallowed twins: a file whose only node is its own __file__
SELECT file_path, count(*) c FROM nodes GROUP BY 1 HAVING c = 1;
-- cross-language reference edges (any Go↔C/C++ row is suspect)
SELECT e.type, count(*) FROM edges e
JOIN nodes s ON s.id=e.source_id JOIN nodes t ON t.id=e.target_id
WHERE s.file_path LIKE '%.go'
AND (t.file_path LIKE '%.c' OR t.file_path LIKE '%.h'
OR t.file_path LIKE '%.cpp' OR t.file_path LIKE '%.hpp')
GROUP BY 1;
-- references onto Go fields (must be zero: field access is selector-only)
SELECT e.type, count(*) FROM edges e JOIN nodes t ON t.id=e.target_id
WHERE t.label='Field' AND t.file_path LIKE '%.go'
AND e.type IN ('READS','WRITES','USAGE') GROUP BY 1;
-- Go import targets (anything not Folder/Module/File is false)
SELECT t.label, count(*) FROM edges e
JOIN nodes s ON s.id=e.source_id JOIN nodes t ON t.id=e.target_id
WHERE e.type='IMPORTS' AND s.file_path LIKE '%.go' GROUP BY 1;
Every census lives inline in its issue's body (and in the fix PR's description); issues in this family are self-contained.
Related work in other ecosystems: #1893 (Swift, method-QN class), #1276 (Python, closed), #495 (Rust cfg twins — the pattern #1911 wants), #725 (cross-language CALLS guard), #1114 (dispatch fan-out), #787 (file attribution).
Tracking issue for the Go / cgo / Go+C extraction work. Method: count a construct in source, count the same thing in the graph, treat any mismatch as a defect. Every item was minimised to a dummy fixture before filing, measured on one real Go + C/C++ repository (~1150 Go files, eBPF C probes, a Windows C++ driver — counts only), and carries a SQL detection recipe that works on any indexed repo. Each fix PR ships a reproduce-first test (RED proven before the change) and a fresh field census on the same tree.
Ledger — bugs
suffix_match3817 → 113,same_module3267 → 224; weak share of CALLS 36.0% → 12.4%,lsp_*8481 → 10672 (re-resolved, not deleted)Closemethods 15 → 86,Process12 → 47,Task1 → 8; kills the flatsame_modulekeyinit()per package collapse onto one QNinitnodes 7 → 29, matching source exactlyimport "C"resolves to an arbitrary project symbol namedCIMPORTS→ 0field_type_hintbinds by receiver variable-name substring, not declared typeUSAGE/WRITES/READSnever consult the #725 cross-language guard (both resolvers)WRITES835 → 0,USAGE1545 → 0; 6432 cross-language refs dropped, none same-language; CALLS/IMPORTS byte-identicalimportcan resolve to aFunction/Method(Strategies 1b + 3 are language-blind)Method85 → 0,Function4 → 0,Folder2206 keptfind_class_bodystops one level abovefield_declaration_list)Fieldnodes with declared types; blank_padding skippedField(found field-validating #1940)Combined stack (#1937 + #1940 + #1944) vs main: USAGE 29198 → 21035, WRITES 2681 → 774, +4533 field nodes — the graph gets nodes and loses junk edges.
Ledger — design-shaped (awaiting maintainer ack, no PR)
#-suffix, #495 pattern), ready on design ack//export→ 22export_linkagecontracts (exact),C.*CALLS 1 → 0, preamble flagged in coverage; C-grammar preamble parse stays openC.f(→ 0 CALLS; 12 preamble functions → 0 nodes on mainchan/goroutines unmodelled — draft PR #1949: grammar-precise send/receive/select →gochantopologygo/element-types deferredLedger — CI
test-windows-guardssetup flake (nodes: None): counts read fromlist_projects, whose stats publish asynchronously — the index response carries them synchronouslyMerge order
import "C"pseudo-package #1931, fix(pipeline): never bind a Go import to a symbol #1938.lsp_type_dispatch; complementary (consumes fix(extract): descend into Go struct field_declaration_list #1940's field nodes, replaces the weak path fix(pipeline): bind field_type_hint by owning QN segment, not substring #1936 tightens). Overlapsextract_defs.cwith fix(extract): descend into Go struct field_declaration_list #1940 — whichever merges second rebases.Cross-cutting theme
One failure mode at every layer: a heuristic binds by name shape and nothing checks the language or what the name can denote. #1906 (CALLS, guarded) → #1927 (
field_type_hint, exempted on a false premise) → #1928 (references, never guarded) → #1934 (imports, label-blind) → #1942 (references, label-blind). Guarding one relocates mass to the next unguarded one — which is why every fix PR above now carries negative/exact-count probes (ei_edge_count_is, zero-project-edge assertions, parallel-twin fixtures) rather than floor-only asserts, closing #1932's original test-infra gap in place.Verified working (audit surface closed, no issues needed)
Generics (receiver-qualified QNs unwrap
generic_type; no[in any QN) · embedding + interface dispatch (lsp_embed_dispatch42,lsp_interface_dispatch79, fan-out via 434IMPLEMENTS) ·//go:linkname(body-less decls get nodes; callers bindlsp_direct) ·defer/closures (attributed to the enclosing named function) · implicit interface satisfaction + method values (lsp_callable_alias) · TESTS edges andVariablecoverage · internal import resolution (2206/~2242 same-module imports → correct packageFolder; residual was #1934). Assembly (.s): untested — no fixtures in the measured repo.Detection recipes (run on any indexed repo)
Every census lives inline in its issue's body (and in the fix PR's description); issues in this family are self-contained.
Related work in other ecosystems: #1893 (Swift, method-QN class), #1276 (Python, closed), #495 (Rust cfg twins — the pattern #1911 wants), #725 (cross-language CALLS guard), #1114 (dispatch fan-out), #787 (file attribution).