Skip to content

fix(cli): distinguish zero role matches from an unbuilt graph in roles --role - #2531

Merged
carlos-alm merged 3 commits into
mainfrom
fix/issue-2390
Aug 16, 2026
Merged

fix(cli): distinguish zero role matches from an unbuilt graph in roles --role#2531
carlos-alm merged 3 commits into
mainfrom
fix/issue-2390

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Closes #2390

Problem

codegraph roles --role <X> with zero matches always said No classified symbols found. Run "codegraph build" first. — even on a fully and correctly built graph where the role simply has no members. Per the issue, this cost real time across 5 of 14 agents in an org rollout, each re-running codegraph build for nothing.

rolesData's count conflates two different states:

  • the graph has no classified symbols at all (genuinely worth rebuilding), and
  • this --role filter matched nothing (the graph is fine).

Fix

rolesData (src/domain/analysis/roles.ts) now also returns totalClassified: the classified-symbol count ignoring the --role filter but still respecting the --file/-T (noTests) filters. It's computed via one extra lightweight query, only when a role filter is active (free — identical to rows.length — in the common unfiltered case).

The CLI (src/presentation/queries-cli/overview.ts) uses this to print:

No symbols with role "entry". (548 classified symbols in graph.)

instead of the misleading rebuild suggestion, whenever the graph is otherwise non-empty. The original message is preserved for the genuine zero-graph case.

No native/Rust changes — this is a TypeScript query/presentation-layer fix only; domain/analysis/ and presentation/queries-cli/ have no Rust mirror (the dual-engine parity requirement applies to graph extraction, not CLI query formatting).

Scope note

While auditing queries-cli/ for the same conflation (per the issue's suggestion), found an identical bug in codegraph exports <file> (a file with legitimately zero exports gets told to rebuild). Filed separately as #2530 to keep this PR to one concern.

Test plan

  • tests/integration/roles.test.ts: 3 new tests on rolesDatatotalClassified matches the unfiltered count when a role filter has zero matches, equals count when no filter is applied, and respects the file filter.
  • tests/presentation/queries-cli.test.ts: 2 new tests on the CLI's roles() formatter — role-specific zero-match message when the graph is otherwise classified, and the original rebuild message preserved when the graph genuinely has none.
  • Verified all 5 new tests fail without the fix (reverted the two source files, confirmed failures, restored).
  • Full suite: npm test — 5313 passed.
  • npm run lint clean.
  • codegraph diff-impact --staged -T — bounded impact (2 files, 2 transitive callers, benchmark script + MCP passthrough only, both benign additive changes).

…s --role (#2390)

rolesData conflated "the graph has no classified symbols at all" with "this
--role filter matched nothing" — both produced count:0, so a correctly built
graph with e.g. no entry-classified symbols told the user to rebuild, which
changes nothing. rolesData now also returns totalClassified (the classified
count ignoring the role filter, respecting file/noTests), computed via one
extra COUNT-style query only when a role filter is active. The CLI uses it to
print "No symbols with role X. (N classified symbols in graph.)" instead of
the rebuild suggestion whenever the graph is otherwise non-empty.

docs check acknowledged

Impact: 3 functions changed, 2 affected
@greptile-apps

greptile-apps Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR now distinguishes an unbuilt graph from valid role or file/test scopes with no matching classified symbols.

  • Adds scoped and graph-wide classified-symbol counts to rolesData.
  • Produces accurate role-specific and scope-specific empty-result messages.
  • Adds integration and presentation regression coverage for filtered, unfiltered, and genuinely empty graphs.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/domain/analysis/roles.ts Adds scoped and unscoped classified-symbol counts so empty filtered results can be distinguished from an unbuilt graph.
src/presentation/queries-cli/overview.ts Selects the appropriate empty-result message and accurately labels scoped versus graph-wide counts.
tests/integration/roles.test.ts Covers scoped totals, graph-wide fallback totals, and genuinely empty graph behavior.
tests/presentation/queries-cli.test.ts Covers role-specific, scope-specific, and rebuild-oriented CLI messages.

Reviews (3): Last reviewed commit: "fix(cli): label the role-specific classi..." | Re-trigger Greptile

Comment thread src/presentation/queries-cli/overview.ts
@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

2 functions changed2 callers affected across 2 files

  • rolesData in src/domain/analysis/roles.ts:40 (2 transitive callers)
  • roles in src/presentation/queries-cli/overview.ts:369 (1 transitive callers)

…verything (#2390)

Greptile's review of the #2390 fix correctly flagged that totalClassified is
itself scoped by --file/--no-tests, so a filter combination that excludes
every classified symbol from that scope (an empty file, or a role that only
exists in test files under -T) still fell through to the misleading rebuild
message even though the graph is healthy outside that scope.

Adds totalClassifiedUnscoped: a fully unfiltered (no role, no file, no
noTests) count, computed only in the now-doubly-empty case. The CLI uses it
to report which scope excluded everything instead of blaming the build.

docs check acknowledged

Impact: 3 functions changed, 2 affected
@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review — added totalClassifiedUnscoped to handle the file/no-tests scoped-zero case you flagged, so the CLI no longer recommends a rebuild when a --file/--no-tests scope excludes everything but the graph is healthy elsewhere.

Comment thread src/presentation/queries-cli/overview.ts Outdated
#2390)

Greptile's second review round on the #2390 fix flagged that totalClassified
stays scoped by --file/--no-tests even in the role-specific message branch,
so combining --role with --file/--no-tests displayed that scoped count while
calling it "classified symbols in graph" — inaccurate whenever those filters
narrow the count below the true graph-wide total.

The message now describes the actual scope ("in file X", "in non-test
files", or both) instead of always claiming "in graph".

docs check acknowledged

Impact: 1 functions changed, 1 affected
@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review — fixed the scoped-count-mislabeled-as-graph-wide finding in d6afc74. Also replied inline on the other open comment: that one describes a scenario already fixed by the prior commit (e5de8c2), verified by 2 tests that fail without the fix — its diff_hunk shows it's anchored to the pre-e5de8c27 commit (a30efcd), so it looks like a re-surfaced round-1 finding rather than a new one.

@carlos-alm
carlos-alm merged commit 18f8149 into main Aug 16, 2026
35 checks passed
@carlos-alm
carlos-alm deleted the fix/issue-2390 branch August 16, 2026 01:15
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 16, 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.

bug(cli): roles --role <X> with zero matches says "Run codegraph build first" on a fully-built graph

1 participant