feat(analysis): symbol-level scan enrichment (blastRadius + community) + converge resolver#265
Merged
Merged
Conversation
…) + converge resolver Extends scan-result graph enrichment beyond the file-granular signals with the finding's enclosing-symbol signals, and converges the twice-cloned enclosing-symbol resolver onto one shared home. Shared resolver: - New `@opencodehub/analysis` `enclosing-symbol.ts` is the canonical `(uri,line) → symbol` lookup (NodeRow / NodesByFile / indexNodesByFile / findEnclosingSymbolId + ENCLOSING_SYMBOL_KINDS / SCIP_SYMBOL_KINDS). analysis is the cycle-free home — cli and ingestion both already depend on it. - Deletes the cli clone (`find-enclosing-symbol.ts`), re-points ingest-sarif; converges the scip-index clone (keeps its in-memory-graph projection, delegates the index/lookup to the shared impl gated on SCIP_SYMBOL_KINDS). The clone's own header had flagged this convergence as the deferred follow-up. Symbol signals in buildScanEnrichment: - blastRadius: upstream `runImpact` on the enclosing symbol, MEMOIZED per symbol (N findings in one symbol = one traversal) and CAPPED at 200 distinct symbols; the cap is applied in sorted-symbol order (deterministic) and recorded in the run stamp (`sources: ["graph","impact-capped"]`) so a capped scan never reads as "no dependents". blastRadius 0 is emitted as a real signal. - community: one batched MEMBER_OF read + one Community-node read → symbol→label map (the verdict pattern); no per-finding traversal. - File signals (busFactor, temporalFixDensity) unchanged; per-result output merges file + symbol signals, keyed by primaryLocationLineHash. - enrichmentVersion bumped 1 → 2. Still omitted (honest, not lossy — all ResultEnrichment fields optional): centrality (PageRank recompute) and cochangeScore (temporal table). Tests: shared resolver test relocated to analysis (18 cases); new scan-enrich cases for blastRadius (real runImpact over a CALLS edge), community (MEMBER_OF), file+symbol merge, and the no-enclosing-symbol fallback. analysis 177 + ingestion 638 + cli 346 green; full workspace 0 fail; biome ci clean. Note: e2e on a live scan couldn't exercise symbol signals in this environment (scanner binaries absent → 0 findings; WASM parse left Function startLine/endLine empty → no enclosing resolution). Logic is covered at the unit level with populated fixtures; the wiring path is the same one F1 verified end-to-end.
Merged
theagenticguy
pushed a commit
that referenced
this pull request
Jun 30, 2026
🤖 Automated release via release-please --- <details><summary>root: 0.10.4</summary> ## [0.10.4](root-v0.10.3...root-v0.10.4) (2026-06-30) ### Features * **analysis:** symbol-level scan enrichment (blastRadius + community) + converge resolver ([#265](#265)) ([817a54d](817a54d)) </details> <details><summary>cli: 0.10.4</summary> ## [0.10.4](cli-v0.10.3...cli-v0.10.4) (2026-06-30) ### Features * **analysis:** symbol-level scan enrichment (blastRadius + community) + converge resolver ([#265](#265)) ([817a54d](817a54d)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Completes the F1 follow-up (the "full thing"): scan findings now carry symbol-level graph signals — blast radius and community — on top of the file-granular signals already shipped, and the twice-cloned enclosing-symbol resolver is converged onto one shared home.
Shared resolver (the deferred refactor, now done)
The
(uri,line) → enclosing symbollookup existed as two clones —cli/ingest-sarifandingestion/scip-index— with the clone's own header flagging convergence as out-of-scope-until-needed. A third consumer (scan enrichment) made it worth doing:@opencodehub/analysis/enclosing-symbol.tsis the canonical impl (NodeRow,NodesByFile,indexNodesByFile,findEnclosingSymbolId,ENCLOSING_SYMBOL_KINDS,SCIP_SYMBOL_KINDS).analysisis the cycle-free home —cliandingestionboth already depend on it.Symbol signals in
buildScanEnrichmentrunImpacton the enclosing symbol, memoized per symbol (N findings in one symbol = one traversal) and capped at 200 distinct symbols. The cap runs in sorted-symbol order (deterministic) and is recorded in the run stamp (sources: ["graph","impact-capped"]) so a capped scan never reads as "no dependents".blastRadius: 0is emitted as a real signal.MEMBER_OFread + one Community-node read (theverdictpattern); no per-finding traversal.primaryLocationLineHash.enrichmentVersion1 → 2.Still omitted (honest, not lossy — all fields optional):
centrality(PageRank recompute) andcochangeScore(temporal table).Tests / validation
runImpactover a CALLS edge, community via MEMBER_OF, file+symbol merge, no-enclosing-symbol fallback.biome ciclean; typecheck clean.Honest e2e note
A live scan couldn't exercise the symbol path in my sandbox (scanner binaries absent → 0 findings; the WASM parse left
FunctionstartLine/endLine empty → no enclosing resolution). The logic is covered at the unit level with populated fixtures, and the wiring path is the same one F1 verified end-to-end. CI's matrix will exercise it on real indexers.🤖 Generated with Claude Code