Skip to content

fix: include constant nodes in edge building (#487)#495

Merged
carlos-alm merged 5 commits intomainfrom
fix/487-constant-nodes-edge-building
Mar 17, 2026
Merged

fix: include constant nodes in edge building (#487)#495
carlos-alm merged 5 commits intomainfrom
fix/487-constant-nodes-edge-building

Conversation

@carlos-alm
Copy link
Contributor

Summary

  • Add 'constant' to the WHERE kind IN (...) SQL clause in build-edges.js so exported constants participate in edge resolution and become visible to all graph queries (where, fn-impact, query, roles, etc.)
  • Also adds missing 'record' kind to build-edges.js to match CORE_SYMBOL_KINDS
  • Updates 4 downstream query files (context.js, watcher.js, export.js, graph-enrichment.js) to include 'constant' in their kind filters

Closes #487

Test plan

  • All integration tests pass (504/504)
  • All graph tests pass (139/139)
  • After rebuild, codegraph where BUILTIN_RECEIVERS -T returns results
  • codegraph fn-impact BUILTIN_RECEIVERS -T reports correct dependents
  • codegraph roles --role dead -T no longer misclassifies active constants

…in backlog

These two items deliver the highest immediate impact on agent experience
and graph accuracy without requiring Rust porting or TypeScript migration.
They should be implemented before any Phase 4+ roadmap work.

- #83: hook-optimized `codegraph brief` enriches passively-injected context
- #71: basic type inference closes the biggest resolution gap for TS/Java
Impact: 14 functions changed, 0 affected
…487)

The edge-building stage excluded 'constant'-kind nodes from the node
lookup maps, so no import/dependency edges were ever created for
exported constants. This made them invisible to where, fn-impact,
query, roles, and all other graph queries. Also adds missing 'record'
kind to build-edges.js to match CORE_SYMBOL_KINDS.

Impact: 6 functions changed, 33 affected
@claude
Copy link

claude bot commented Mar 17, 2026

Claude finished @carlos-alm's task —— View job


Reviewing PR #495: Include constant nodes in edge building

Review Progress:

  • Phase 1: Root cause analysis
  • Phase 2: Configuration change detection
  • Phase 3: Test integrity check
  • Phase 4: Code quality assessment
  • Phase 5: Backlog compliance rating
  • Final assessment and recommendation

Root Cause Analysis

Problem Being Solved: Exported constants were invisible to graph queries because the edge-building stage excluded 'constant' nodes from lookup maps, preventing import/dependency edges from being created for them.

Why This Approach: The fix correctly addresses the root cause by adding 'constant' (and missing 'record') to the SQL WHERE clauses in build-edges.js:31 and updating 4 downstream query files to maintain consistency. This is not hiding symptoms - it's fixing a genuine oversight where CORE_SYMBOL_KINDS includes 'constant' but the edge builder didn't.

Risk Assessment: Very low risk. This is purely additive (more edges, more visibility) with no breaking changes to existing behavior.

Configuration Change Detection

No configuration changes detected. No linting rules, test timeouts, build config, or TypeScript flags were modified.

Test Integrity Check

No test integrity concerns. According to the PR description, all integration tests (504/504) and graph tests (139/139) pass. No test files were modified. The change is purely in the core graph building logic.

Code Quality Assessment

Strengths:

  • Systematic consistency: The fix updates all 6 files that use hardcoded kind lists, ensuring no edge cases are missed
  • Correct SQL syntax: All WHERE clauses properly add 'constant' to the kind filters (build-edges.js:31, context.js:98, watcher.js:60+63, export.js:70+71+311, graph-enrichment.js:45+46)
  • Matches CORE_SYMBOL_KINDS: The hardcoded lists now align with the canonical CORE_SYMBOL_KINDS from shared/kinds.js which includes both 'constant' and 'record'
  • No breaking changes: Purely additive - existing edges remain unchanged, new constant nodes become visible

Minor observations:

  • String literal consistency: All files use single quotes consistently ('constant', 'record')
  • Proper SQL formatting: Multi-line WHERE clauses maintain proper indentation and readable structure
  • The commit fixes both 'constant' (the main issue) and 'record' (missed in an earlier update) in one go

Architecture alignment: The fix addresses the discrepancy between CORE_SYMBOL_KINDS (the authoritative constant) and the hardcoded SQL strings. Ideally these hardcoded lists would be eliminated in favor of dynamically building SQL from CORE_SYMBOL_KINDS, but that's a broader refactoring outside the scope of this bug fix.

No security, performance, or maintainability concerns identified.

Backlog Compliance

  • Zero-dep: ✓ — Uses only existing tree-sitter/SQLite infrastructure
  • Foundation-aligned: ✓ — Improves graph accuracy without adding dependencies or cloud calls
  • Problem-fit: 5 — Directly fixes missed dependencies (constant imports were invisible, causing "no callers" hallucinations)
  • Breaking: No — Purely additive, no existing behavior changes
  • Tier: 1

Critical Concerns

None identified. This is a straightforward, well-implemented bug fix.

Final Recommendation

  • Rating: ⭐⭐⭐⭐☆ (4/5)
  • Action: APPROVE
  • Reasoning: Clean bug fix that systematically addresses a real graph accuracy issue. The implementation is consistent across all affected files, properly tested, and directly improves the core problem codegraph exists to solve (preventing hallucinated "no callers" results for exported constants). Only minor deduction for lack of test demonstrating the fix working end-to-end.

Suggested follow-up (not blocking): Consider refactoring the hardcoded SQL kind lists to use CORE_SYMBOL_KINDS dynamically to prevent this type of inconsistency in the future.


@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 17, 2026

Greptile Summary

This PR fixes issue #487 by including 'constant' nodes in the edge-building pipeline so that exported constants participate in graph queries (where, fn-impact, roles, etc.). It also back-fills the missing 'record' kind in build-edges.js to align with CORE_SYMBOL_KINDS. The changes are applied consistently across build-edges.js, context.js, watcher.js, export.js, and graph-enrichment.js.

Two issues were found during review:

  • iterWhere not updated (src/shared/generators.js): The streaming generator path for the where command still uses ALL_SYMBOL_KINDS (the original 10 core kinds), which does not include 'constant'. The non-streaming whereData / whereSymbolImpl path was updated to EVERY_SYMBOL_KIND. The two paths now return different kinds, so iterWhere callers (including the integration test in pagination.test.js and any external consumers via domain/queries.js) will not see constant nodes.

  • whereSymbolImpl picks up parameter and property beyond the stated goal: The switch from ALL_SYMBOL_KINDS to EVERY_SYMBOL_KIND in symbol-lookup.js also activates 'parameter' and 'property' in codegraph where results. These are Phase-1 sub-declaration kinds and their inclusion in symbol search output was not mentioned in the PR description. This may add significant noise for common identifier names (e.g., searching for id would now surface every function parameter and class property named id).

Confidence Score: 3/5

  • Safe to merge for the core edge-building fix, but two unintended side-effects in the where query path should be addressed first.
  • The central change (adding 'constant' + 'record' to build-edges.js) is correct and well-scoped. The downstream updates to context.js, watcher.js, export.js, and graph-enrichment.js are consistent. However, the iterWhere generator in generators.js was not updated, creating a divergence between streaming and non-streaming where paths. Additionally, symbol-lookup.js uses EVERY_SYMBOL_KIND which brings in 'parameter' and 'property' — a broader behavioral change than described that could cause noisy where results.
  • src/domain/analysis/symbol-lookup.js and the untouched src/shared/generators.js need attention.

Important Files Changed

Filename Overview
src/domain/graph/builder/stages/build-edges.js Core fix: adds 'constant' and 'record' to the node pre-load query so constants are included in both lookup maps (nodesByName, nodesByNameAndFile) used during edge resolution. Change is targeted and correct.
src/domain/analysis/symbol-lookup.js Switches whereSymbolImpl from ALL_SYMBOL_KINDS to EVERY_SYMBOL_KIND, unintentionally adding 'parameter' and 'property' to where results beyond the stated goal of adding 'constant'. Also updates FUNCTION_KINDS to include 'constant' for findMatchingNodes.
src/shared/generators.js Not modified in this PR, but iterWhere still uses ALL_SYMBOL_KINDS (no constant), creating a divergence from the updated whereSymbolImpl path. The streaming and non-streaming where paths now return different kinds.
src/domain/analysis/context.js Straightforward addition of 'constant' to the kind filter in explainFunctionImpl. Consistent with the fix goal.
src/domain/graph/watcher.js Adds 'constant' to both findNodeInFile and findNodeByName prepared statements. Consistent and correct.
src/features/export.js Adds 'constant' to the kind filters in both loadFunctionLevelEdges and exportGraphSON. Consistent with the fix goal.
src/features/graph-enrichment.js Adds 'constant' to both n1.kind and n2.kind filters in prepareFunctionLevelData. Consistent and correct.
docs/roadmap/BACKLOG.md Moves items #83 and #71 from Tier 1/2 into a new "Tier 0" section at the top of the backlog. Documentation-only change, no code impact.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI / MCP
    participant SL as symbol-lookup.js
    participant GEN as generators.js (iterWhere)
    participant BE as build-edges.js
    participant DB as SQLite nodes table

    Note over CLI,DB: codegraph where SOME_CONSTANT (non-streaming)
    CLI->>SL: whereData(target)
    SL->>DB: SELECT * FROM nodes WHERE kind IN<br/>(...CORE_SYMBOL_KINDS, 'parameter', 'property', 'constant')
    DB-->>SL: rows including constant nodes ✅
    SL-->>CLI: results with constants

    Note over CLI,DB: codegraph where SOME_CONSTANT (streaming / iterWhere)
    CLI->>GEN: iterWhere(target)
    GEN->>DB: SELECT * FROM nodes WHERE kind IN<br/>(CORE_SYMBOL_KINDS — no constant ❌)
    DB-->>GEN: rows WITHOUT constant nodes
    GEN-->>CLI: results missing constants

    Note over CLI,DB: Graph build — buildEdges (after this PR)
    CLI->>BE: buildEdges(ctx)
    BE->>DB: SELECT id,name,kind,file,line FROM nodes<br/>WHERE kind IN (...CORE_SYMBOL_KINDS, 'record', 'constant') ✅
    DB-->>BE: allNodes including constants
    BE->>BE: populate nodesByName / nodesByNameAndFile
    BE->>DB: INSERT edges (calls, imports, receiver…)
Loading

Comments Outside Diff (2)

  1. src/shared/generators.js, line 91-103 (link)

    iterWhere not updated — constants invisible to streaming path

    iterWhere still uses ALL_SYMBOL_KINDS (the 10 core kinds, no constant), while whereSymbolImpl in symbol-lookup.js was upgraded to EVERY_SYMBOL_KIND. The two paths are supposed to be equivalent — they back the same logical where operation — but after this PR they diverge: calling whereData() returns constants while iterating iterWhere() silently skips them.

    iterWhere is exported as a public API through domain/queries.js and is exercised in tests/integration/pagination.test.js, so this gap will surface for any caller that uses the generator form.

    And on line 103, update the stmt.iterate call accordingly:

        for (const node of stmt.iterate(`%${target}%`, ...EVERY_SYMBOL_KIND)) {

    You'll also need to add the import at the top of generators.js:

    import { EVERY_SYMBOL_KIND } from './kinds.js';
  2. src/domain/analysis/symbol-lookup.js, line 106-111 (link)

    whereSymbolImpl now includes parameter and property nodes — broader than intended

    Switching from ALL_SYMBOL_KINDS to EVERY_SYMBOL_KIND adds 'parameter' and 'property' to the WHERE kind IN (...) filter in addition to 'constant'. The PR description states the goal is to include constants; it does not mention surfacing function parameters or class/struct properties in codegraph where results.

    EVERY_SYMBOL_KIND is defined as:

    export const EVERY_SYMBOL_KIND = [...CORE_SYMBOL_KINDS, ...EXTENDED_SYMBOL_KINDS];
    // EXTENDED_SYMBOL_KINDS = ['parameter', 'property', 'constant']

    So whereSymbolImpl will now return parameter nodes (e.g., every function argument named id) and property nodes in addition to constants. Depending on repo size this can produce very noisy results for common short names.

    If the intent is only to add constant, consider building the kinds list more explicitly:

    If parameter and property are intentionally included (Phase 1 feature graduation), please document that in the PR description so the broader change is explicit.

Last reviewed commit: 8266b33

@carlos-alm
Copy link
Contributor Author

@greptileai

…es (#487)

whereSymbolImpl used ALL_SYMBOL_KINDS (core 10, no constant) so
codegraph where could not find constants. findMatchingNodes defaulted
to FUNCTION_KINDS which also excluded constant. Switch whereSymbolImpl
to EVERY_SYMBOL_KIND and add constant to FUNCTION_KINDS default.

Impact: 1 functions changed, 6 affected
@carlos-alm
Copy link
Contributor Author

Fixed in 8266b33 — addressed the Greptile feedback about whereSymbolImpl and findMatchingNodes not finding constants:

  1. whereSymbolImpl: Replaced ALL_SYMBOL_KINDS (core 10, excludes constant) with EVERY_SYMBOL_KIND (includes constant, parameter, property). codegraph where <constant> now returns results.
  2. findMatchingNodes: Added 'constant' to the FUNCTION_KINDS default array. This fixes codegraph fn-impact, codegraph context, and codegraph deps for constant symbols.

All 1862 tests pass, lint clean.

@greptileai

@carlos-alm carlos-alm merged commit 7b6a0ce into main Mar 17, 2026
13 checks passed
@carlos-alm carlos-alm deleted the fix/487-constant-nodes-edge-building branch March 17, 2026 11:23
@github-actions github-actions bot locked and limited conversation to collaborators Mar 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Edge building excludes constant nodes from dependency graph

1 participant