Skip to content

feat(analysis): symbol-level scan enrichment (blastRadius + community) + converge resolver#265

Merged
theagenticguy merged 1 commit into
mainfrom
feat/scan-symbol-signals
Jun 30, 2026
Merged

feat(analysis): symbol-level scan enrichment (blastRadius + community) + converge resolver#265
theagenticguy merged 1 commit into
mainfrom
feat/scan-symbol-signals

Conversation

@theagenticguy

Copy link
Copy Markdown
Owner

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 symbol lookup existed as two clonescli/ingest-sarif and ingestion/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:

  • New @opencodehub/analysis/enclosing-symbol.ts is the canonical impl (NodeRow, NodesByFile, indexNodesByFile, findEnclosingSymbolId, ENCLOSING_SYMBOL_KINDS, SCIP_SYMBOL_KINDS). analysis is the cycle-free home — cli and ingestion both already depend on it.
  • cli clone deleted, ingest-sarif re-pointed; scip-index converged (keeps its in-memory-graph projection, delegates index/lookup to the shared impl).

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 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: 0 is emitted as a real signal.
  • community — one batched MEMBER_OF read + one Community-node read (the verdict pattern); no per-finding traversal.
  • File signals (busFactor, temporalFixDensity) unchanged; per-result output merges file + symbol signals, keyed by primaryLocationLineHash. enrichmentVersion 1 → 2.

Still omitted (honest, not lossy — all fields optional): centrality (PageRank recompute) and cochangeScore (temporal table).

Tests / validation

  • Shared-resolver test relocated to analysis (18 cases). New scan-enrich cases: blastRadius via a real runImpact over a CALLS edge, community via MEMBER_OF, file+symbol merge, no-enclosing-symbol fallback.
  • analysis 177 + ingestion 638 + cli 346 green; full workspace 0 failures; biome ci clean; 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 Function startLine/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

…) + 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.
@theagenticguy theagenticguy merged commit 817a54d into main Jun 30, 2026
38 checks passed
@theagenticguy theagenticguy deleted the feat/scan-symbol-signals branch June 30, 2026 03:10
@github-actions github-actions Bot mentioned this pull request Jun 30, 2026
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>
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