Skip to content

fix(extract): give Go build-constrained twin files distinct QNs - #1946

Draft
ilyabrykau-orca wants to merge 1 commit into
DeusData:mainfrom
ilyabrykau-orca:fix/go-buildtag-twin-qn
Draft

fix(extract): give Go build-constrained twin files distinct QNs#1946
ilyabrykau-orca wants to merge 1 commit into
DeusData:mainfrom
ilyabrykau-orca:fix/go-buildtag-twin-qn

Conversation

@ilyabrykau-orca

Copy link
Copy Markdown

Part of #1911draft implementation-proposal: this changes what gets extracted (Go func/method QNs in build-constrained files), so per CONTRIBUTING it's opened as a draft for design review; the design is the one proposed in the issue body (the #495 Rust-cfg #-suffix pattern). Will mark ready on a maintainer design ack.

What

Build-constrained twin files (//go:build lines, GOOS/GOARCH filename suffixes) legally define the same symbols; the upsert kept ONE node per QN by the smallest-file-path rule — a 2-line stub beat the 63-line implementation and took all 25 inbound CALLS; a bpf2go GOARCH twin pair lost 39/40 nodes; coverage stayed silent.

How

  • τ = compacted //go:build expression, else the official GOOS/GOARCH filename suffix (cbm_go_build_tau, computed once per file). Folded into func/method QNs (MirrorConfig#unix), mirrored on the call-scope side (go_tau_scope_qn) so body-call attribution stays exact. Types/vars stay plain — parent_class/DEFINES_METHOD joins keep working.
  • Two #-aware seams make suffixed defs resolvable (both also close a latent gap for Rust cfg twins, whose QNs already carry #):
    • cbm_registry_add indexes the simple name as the part before # (identifiers cannot contain one);
    • the LSP registry's exact pkg.name lookup falls back to a sole #-suffixed variant (lookup_func_sole_tau_variant) — the dominant real-world shape is a constrained file with no in-tree twin, and its callers keep their lsp_direct/lsp_strategy_cross_file edges. Two+ variants are genuinely ambiguous without the caller's build configuration and fail closed. The pipeline's LSP-join leaf gate learns the same rule.

Scope (deliberately the issue's "minimal PR")

QN disambiguation only. τ-aware resolution (preferring the caller's own constraint, and module.name#τ same-module keys) is the declared follow-up — unconstrained callers of a genuine twin pair currently resolve as ambiguous rather than binding an arbitrary twin, which is strictly better than today's bind-everyone-to-the-stub.

Tests (reproduce-first)

  • extract_go_buildtag_tau_in_func_qns: //go:build linux && amd64#linux&&amd64, _windows_amd64.go#windows_amd64, _linux_test.go#linux, types stay plain, unconstrained files carry no #. RED on main.
  • pipeline_go_buildtag_twins_both_survive: RED on main (count_nodes_named == 1, expected 2); GREEN with both twins as nodes AND a sole-variant caller edge staying alive (UseFlush → FlushDisk#linux, lsp_strategy_cross_file @ 0.92).
  • 854 green across extraction/pipeline/registry/lsp probes/go_lsp/parallel; full scripts/test.sh venue leg green; git clang-format --diff clean.

Field census

Pending: the validation index of the reference Go+C repo is currently blocked by a live-daemon rendezvous conflict on this machine (isolated-HOME one-shots get conflicting CBM process is active); numbers (bpf2go twin-pair node recovery 43+1 → ~86, Close 63 → 66, CALLS deltas) will follow as a PR comment once it clears. Expected shapes are in #1911's body.

#1932 tracks the family.

@github-actions

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

Go build-constrained twin files (//go:build lines, GOOS/GOARCH filename
suffixes) legally define the same symbols in one package. The indexer
ignored the constraints, so the graph upsert kept ONE node per QN by the
smallest-file-path rule: a 2-line stub beat the 63-line real
implementation and took all 25 inbound CALLS; a bpf2go GOARCH twin pair
lost 39 of 40 nodes; parse coverage stayed clean so nothing flagged it.

Fold the per-file build constraint tau into Go func/method QNs with the
same #-suffix move Rust cfg twins got in DeusData#495: tau is the compacted
//go:build expression when present, else the official GOOS/GOARCH
filename suffix (cbm_go_build_tau in helpers.c, computed once per file
in cbm_extract_file). The scope builder mirrors the def formula
(go_tau_scope_qn) so body calls in constrained files stay attributed.
Types and vars stay plain, keeping parent_class / DEFINES_METHOD joins
intact.

Two #-aware seams make the suffixed defs resolvable (both also close a
latent gap for Rust cfg twins, which already carry such QNs):

- cbm_registry_add indexes the simple name as the part before '#'
  (identifiers cannot contain one), so callers keep resolving by name.
- The LSP registry's exact pkg.name lookup falls back to a SOLE
  #-suffixed variant (lookup_func_sole_tau_variant) - the dominant
  real-world shape is a constrained file with no in-tree twin, and its
  callers must keep their lsp_direct/lsp_strategy_cross_file edges. Two
  or more variants are genuinely ambiguous without the caller's build
  configuration and fail closed; tau-aware preference for the caller's
  own constraint is the declared follow-up. The pipeline's LSP-join
  leaf gate learns the same rule.

Reproduce-first tests: extract_go_buildtag_tau_in_func_qns
(//go:build compaction, GOOS_GOARCH and _test filename forms, types
stay plain, unconstrained files carry no '#') and
pipeline_go_buildtag_twins_both_survive (RED on main:
count_nodes_named == 1, expected 2; plus the sole-variant caller edge
staying alive). 854 tests green across extraction/pipeline/registry/
lsp probes/go_lsp/parallel suites.

Part of DeusData#1911 (minimal PR: QN disambiguation; tau-aware same-module
resolution is the follow-up)

Signed-off-by: Ilya Brykau <ilya.brykau@orca.security>
@ilyabrykau-orca

Copy link
Copy Markdown
Author

CI retrigger (no-op amend): test-lsan-macos failed in test_cli installer/skill probes and test_daemon_ipc (no LeakSanitizer report anywhere in the log) — none of which this Go-extraction diff touches, and the same job is green on every sibling PR in today's waves (#1907 #1913 #1937 #1938 #1944 #1947 #1949). Same runner-environment day as #1952. No semantic changes.

@ilyabrykau-orca
ilyabrykau-orca force-pushed the fix/go-buildtag-twin-qn branch from d4c7f01 to dcbb7fd Compare August 30, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant