fix(stats): stop double-counting dead symbols in the roles map (#2383) - #2522
Merged
Conversation
The `dead` key was injected into the flat roles map as the sum of its own dead-* sub-roles, so any total over the map (including the printed "classified symbols" headline) counted every dead symbol twice. deadTotal is now returned as a sibling of roles instead of a peer key, and the text renderer shows it as an indented sub-group heading. docs check acknowledged: internal stats aggregation bugfix, no README/CLAUDE.md/ROADMAP surface area changed. Impact: 7 functions changed, 0 affected
Contributor
Greptile SummaryThe PR separates the aggregate dead-symbol count from the flat roles map, preventing dead symbols from inflating classified-symbol totals.
Confidence Score: 5/5The PR appears safe to merge, with both stats engines and the text renderer consistently using the corrected role-count shape. The aggregate dead count is removed from the disjoint roles map, retained as a sibling result field, and verified against the granular dead-role sum without leaving a concrete caller or output path broken. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
A["SQL or native role counts"] --> B["Aggregate granular dead-* roles"]
B --> C["roles: disjoint role counts"]
B --> D["deadTotal: aggregate count"]
C --> E["Classified-symbol headline"]
C --> F["Live-role grid"]
C --> G["Dead sub-role details"]
D --> G
Reviews (1): Last reviewed commit: "merge: bring branch up to date with main" | Re-trigger Greptile |
Contributor
Codegraph Impact Analysis6 functions changed → 9 callers affected across 3 files
|
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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
codegraph statsdouble-counted every dead symbol. Therolesmap contained the four granulardead-*sub-roles and an aggregatedeadkey that was their sum, sitting as a peer in the same flat map — so any total over the map (including the printed "classified symbols" headline) counted dead symbols twice.Root cause was in
countRoles(SQL path) andaggregateRolesFromNative(native path) insrc/domain/analysis/module-map.ts— both injectedroles.dead = deadTotalinto the same object that already held the fourdead-*counts.Changes
countRoles/aggregateRolesFromNativenow return{ roles, deadTotal }—deadTotalis a sibling field in the stats result, never a peer key insideroles.stats -jnow emits the shape the issue proposed:{ "roles": {...no aggregate dead key...}, "deadTotal": N }.printRoles(text output) now renders the dead family as an indented sub-group under a singledead Nheading instead of interleaving it with the other roles in one sorted grid.printCountGridcosmetic bug: a column value at or beyond the fixed pad width ran straight into the next column with no separator (e.g.dead-unresolved 86dead 86).crates/codegraph-core'sfetch_role_countsdoes a rawGROUP BY rolewith no aggregate injected — the double-count was purely in the JS aggregation layer that both engines' stats paths share.Verification
npx vitest run tests/integration/roles.test.ts: 22/22 pass (updated theroles.deadassertion todeadTotal, added a regression test asserting the map no longer carries an aggregatedeadpeer key)codegraph diff-impact --staged: 7 functions changed, 0 external callers affected beyondstats()rolesno longer containsdead,deadTotalcorrectly sums the four sub-roles, and the text headline total now matches the sum of disjoint categoriesNote: a full local
npm testrun in this environment (Node v26.4.0, no other version available) shows ~200 unrelated failures that also reproduce on an untouchedorigin/maincheckout and do not touch any file this PR changes; CI (which pins Node 22, per.github/workflows/ci.yml) has been consistently green on recentmainpushes. Filed as #2521 for separate tracking — not blocking this fix.Closes #2383