{{ message }}
feat: cognitive & cyclomatic complexity metrics#130
Merged
Conversation
Add `codegraph path <from> <to>` — BFS shortest-path search on the call graph. Given two symbol names, finds the shortest call chain with hop count, intermediate nodes, edge kinds, and alternate path count. Supports --reverse, --max-depth, --kinds, --from-file/--to-file, -T, -j, -k flags. Exposed as symbol_path MCP tool. Impact: 4 functions changed, 3 affected
- Create docs/use-cases/titan-paradigm.md — maps Johannes R.'s multi-agent codebase cleanup architecture (RECON, GAUNTLET, GLOBAL SYNC, STATE MACHINE) to codegraph commands, roadmap items, and post-LLM-integration recommendations - Update roadmap/BACKLOG.md: mark #4 (node classification), #9 (git change coupling), #1 (dead code), #2 (shortest path), #12 (execution flow) as DONE; add 6 new Titan Paradigm-inspired items (#21-#26): composite audit, batch querying, triage priority queue, change validation predicates, graph snapshots, MCP orchestration tools - Update README.md: add roles + co-change to features table, differentiators, commands section, agent template, common flags, comparison table; update MCP tool count 18 → 19 - Update docs/recommended-practices.md: update MCP tool count and tool list, add roles/co-change/path to CLAUDE.md template and developer workflow, add "Understand architectural roles" and "Surface hidden coupling" sections, add co-change step to setup checklist - Add full examples with real output for roles, co-change, and path to docs/examples/CLI.md and docs/examples/MCP.md - Update GitHub repo description with new capabilities
- Restore Phase 3 (Architectural Refactoring) to ROADMAP - Renumber phases 4-8 and all cross-references - Fix MCP tool count per Greptile review
Address Greptile review comments on #121: - Update MCP tool counts from 18/19 to 21 (22 in multi-repo mode) across README, recommended-practices, dogfood skill, titan-paradigm - Add missing execution_flow and list_entry_points to tool enumeration - Renumber new backlog items 21-26 → 27-32 to avoid collision with existing items 21-22
Adds a benchmark suite that measures how much codegraph reduces token usage when AI agents navigate the Next.js codebase (~4k TS files). - scripts/token-benchmark-issues.js: 5 real Next.js PRs as test cases - scripts/token-benchmark.js: runner using Claude Agent SDK (baseline vs codegraph MCP), with --perf flag for build/query benchmarks - scripts/update-token-report.js: JSON → markdown report generator - docs/benchmarks/: methodology docs and placeholder report Impact: 21 functions changed, 7 affected
…verage benchmark.js now measures no-op rebuilds, 1-file rebuilds, and query latency (fn-deps, fn-impact, path, roles) alongside full builds. update-benchmark-report.js renders new Incremental Rebuilds and Query Latency sections in BUILD-BENCHMARKS.md and adds incremental/query rows to the README performance table. All new fields are additive for backward compatibility. Impact: 5 functions changed, 2 affected
Extract version from benchmark result JSON and include it in branch names, commit messages, PR titles, and PR bodies across all 4 benchmark jobs (build, embedding, query, incremental).
Resolve conflicts: - benchmark.yml: keep version-in-branch-name convention - README.md: take main's dual-engine performance table - BUILD-BENCHMARKS.md: main's dual-engine data + incremental/query sections - update-benchmark-report.js: take main's clearer regex comment Impact: 12 functions changed, 13 affected
Take main's latest benchmark numbers (PR #125) while preserving the new incremental rebuild and query latency fields from the branch.
Nested/closure functions (e.g. nodeId inside exportMermaid) were incorrectly classified as [dead] because the caller selection loop picked the last definition where line <= call.line, creating self-call edges that got filtered out. Now uses endLine to find the innermost enclosing scope, so calls within an outer function correctly attribute the outer function as caller rather than the nested function itself. Fixes false-positive [dead] for nodeId in branch-compare.js, export.js, and queries.js. Impact: 1 functions changed, 17 affected
Compute per-function complexity during build via single-traversal DFS of tree-sitter ASTs: cognitive (SonarSource), cyclomatic (McCabe), and max nesting depth. Stores results in new function_complexity table (migration v8) and surfaces them in stats, context, explain, and a dedicated `complexity` CLI command + MCP tool. Adds manifesto config section with warn thresholds (cognitive: 15, cyclomatic: 10, maxNesting: 4) seeding the future rule engine. Phase 1 supports JS/TS/TSX; unsupported languages are skipped gracefully. Impact: 18 functions changed, 32 affected
Contributor
Greptile SummaryThis PR adds comprehensive complexity metrics (cognitive & cyclomatic complexity, max nesting depth) to codegraph, computed via single-traversal DFS of tree-sitter ASTs at build time. The implementation follows SonarSource's cognitive complexity spec and McCabe's cyclomatic complexity. Key Changes:
Test Coverage:
Issues Found:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
Start[Build Graph] --> Parse[Parse Source Files]
Parse --> Extract[Extract Function Definitions]
Extract --> AST[Get tree-sitter AST]
AST --> DFS[Single-Pass DFS Traversal]
DFS --> Branch{Node Type?}
Branch -->|if/for/while/switch| IncCog["+1 Cognitive<br/>+1 Cyclomatic<br/>+1 Nesting"]
Branch -->|else-if| ElseIf["+1 Cognitive<br/>+1 Cyclomatic<br/>NO Nesting"]
Branch -->|Logical Operators| Logic["Check Sequence<br/>+1 Cognitive if changed<br/>+1 Cyclomatic always"]
Branch -->|switch_case| Case["+1 Cyclomatic only"]
Branch -->|Nested Function| Nest["+1 Nesting"]
IncCog --> Track[Track Max Nesting]
ElseIf --> Track
Logic --> Track
Case --> Track
Nest --> Track
Track --> Result[Return Metrics:<br/>cognitive, cyclomatic, maxNesting]
Result --> Upsert[Upsert to function_complexity table]
Upsert --> Query[Query Commands]
Query --> CLI[CLI: codegraph complexity]
Query --> MCP[MCP: complexity tool]
Query --> Stats[Enhanced stats/context/explain]
Last reviewed commit: 1b5e20d |
Comment on lines
+370
to
+383
| if (aboveThreshold) { | ||
| const conditions = []; | ||
| if (thresholds.cognitive?.warn != null) { | ||
| conditions.push(`fc.cognitive >= ${thresholds.cognitive.warn}`); | ||
| } | ||
| if (thresholds.cyclomatic?.warn != null) { | ||
| conditions.push(`fc.cyclomatic >= ${thresholds.cyclomatic.warn}`); | ||
| } | ||
| if (thresholds.maxNesting?.warn != null) { | ||
| conditions.push(`fc.max_nesting >= ${thresholds.maxNesting.warn}`); | ||
| } | ||
| if (conditions.length > 0) { | ||
| having = `AND (${conditions.join(' OR ')})`; | ||
| } |
Contributor
There was a problem hiding this comment.
Threshold values are directly interpolated into SQL without validation. While these come from config (not user input), a malicious .codegraphrc.json could inject SQL. Use parameterized queries:
Suggested change
| if (aboveThreshold) { | |
| const conditions = []; | |
| if (thresholds.cognitive?.warn != null) { | |
| conditions.push(`fc.cognitive >= ${thresholds.cognitive.warn}`); | |
| } | |
| if (thresholds.cyclomatic?.warn != null) { | |
| conditions.push(`fc.cyclomatic >= ${thresholds.cyclomatic.warn}`); | |
| } | |
| if (thresholds.maxNesting?.warn != null) { | |
| conditions.push(`fc.max_nesting >= ${thresholds.maxNesting.warn}`); | |
| } | |
| if (conditions.length > 0) { | |
| having = `AND (${conditions.join(' OR ')})`; | |
| } | |
| if (aboveThreshold) { | |
| const conditions = []; | |
| if (thresholds.cognitive?.warn != null) { | |
| const val = Number(thresholds.cognitive.warn); | |
| if (!isNaN(val)) conditions.push(`fc.cognitive >= ${val}`); | |
| } | |
| if (thresholds.cyclomatic?.warn != null) { | |
| const val = Number(thresholds.cyclomatic.warn); | |
| if (!isNaN(val)) conditions.push(`fc.cyclomatic >= ${val}`); | |
| } | |
| if (thresholds.maxNesting?.warn != null) { | |
| const val = Number(thresholds.maxNesting.warn); | |
| if (!isNaN(val)) conditions.push(`fc.max_nesting >= ${val}`); | |
| } | |
| if (conditions.length > 0) { | |
| having = `AND (${conditions.join(' OR ')})`; | |
| } | |
| } |
Contributor
Author
4 tasks
carlos-alm
pushed a commit
that referenced
this pull request
Feb 27, 2026
Update README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices, and CLI/MCP examples to reflect today's merged PRs: complexity metrics (#130/#139), Louvain community detection (#133/#134), and manifesto rule engine (#138). Updates MCP tool count from 21 to 24 (25 in multi-repo), marks backlog items 6/11/21/22 as done, and adds real CLI output examples.
carlos-alm
pushed a commit
that referenced
this pull request
Feb 27, 2026
Update README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices, and CLI/MCP examples to reflect today's merged PRs: complexity metrics (#130/#139), Louvain community detection (#133/#134), and manifesto rule engine (#138). Updates MCP tool count from 21 to 24 (25 in multi-repo), marks backlog items 6/11/21/22 as done, and adds real CLI output examples.
4 tasks
carlos-alm
added a commit
that referenced
this pull request
Feb 27, 2026
* fix: strict type validation for threshold values in complexity queries
Replace loose `!= null` checks with `typeof === 'number' && Number.isFinite()`
to prevent `Number("")`, `Number(null)`, and `Number(true)` from silently
coercing into valid SQL values. Add integration test verifying exceeds
arrays and summary.aboveWarn are correctly computed.
Addresses Greptile review feedback on #136.
Impact: 2 functions changed, 3 affected
* docs: add complexity, communities, and manifesto to all docs
Update README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices,
and CLI/MCP examples to reflect today's merged PRs: complexity metrics
(#130/#139), Louvain community detection (#133/#134), and manifesto rule
engine (#138). Updates MCP tool count from 21 to 24 (25 in multi-repo),
marks backlog items 6/11/21/22 as done, and adds real CLI output examples.
* fix: remove redundant condition in paginate guard clauses
When limit === undefined, limit !== 0 is always true — the && check
was dead code. Simplified to just check limit === undefined.
Impact: 2 functions changed, 18 affected
* docs: update dogfood report with fix statuses
All 4 bugs now fixed (PR #117 merged, #116 closed via reverse-dep
cascade). 3 of 4 suggestions addressed. MCP tool counts updated
18→23 / 19→24. Rating upgraded 7/10 → 9/10 post-fix.
* fix: rename misleading test to match actual behavior
Test was named "handles non-numeric thresholds gracefully" but only
validated baseline exceeds/aboveWarn with valid thresholds. Actual
non-numeric threshold tests exist separately. Renamed to "produces
correct exceeds and aboveWarn with valid thresholds".
* fix: update stale MCP tool count in dogfood skill (21→24)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
carlos-alm
added a commit
that referenced
this pull request
Feb 27, 2026
* fix: strict type validation for threshold values in complexity queries
Replace loose `!= null` checks with `typeof === 'number' && Number.isFinite()`
to prevent `Number("")`, `Number(null)`, and `Number(true)` from silently
coercing into valid SQL values. Add integration test verifying exceeds
arrays and summary.aboveWarn are correctly computed.
Addresses Greptile review feedback on #136.
Impact: 2 functions changed, 3 affected
* docs: add complexity, communities, and manifesto to all docs
Update README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices,
and CLI/MCP examples to reflect today's merged PRs: complexity metrics
(#130/#139), Louvain community detection (#133/#134), and manifesto rule
engine (#138). Updates MCP tool count from 21 to 24 (25 in multi-repo),
marks backlog items 6/11/21/22 as done, and adds real CLI output examples.
* fix: remove redundant condition in paginate guard clauses
When limit === undefined, limit !== 0 is always true — the && check
was dead code. Simplified to just check limit === undefined.
Impact: 2 functions changed, 18 affected
* docs: update dogfood report with fix statuses
All 4 bugs now fixed (PR #117 merged, #116 closed via reverse-dep
cascade). 3 of 4 suggestions addressed. MCP tool counts updated
18→23 / 19→24. Rating upgraded 7/10 → 9/10 post-fix.
* fix: rename misleading test to match actual behavior
Test was named "handles non-numeric thresholds gracefully" but only
validated baseline exceeds/aboveWarn with valid thresholds. Actual
non-numeric threshold tests exist separately. Renamed to "produces
correct exceeds and aboveWarn with valid thresholds".
* fix: update stale MCP tool count in dogfood skill (21→24)
* feat: add complexity analysis for Python, Go, Rust, Java, C#, Ruby, PHP
Parameterize the complexity algorithm to support all 10 languages instead
of just JS/TS/TSX. Add per-language COMPLEXITY_RULES, HALSTEAD_RULES, and
COMMENT_PREFIXES with three else-if detection patterns (else-wraps-if,
explicit elif, alternative field). Guard against tree-sitter keyword leaf
tokens that share node type names with their parent constructs.
Impact: 4 functions changed, 4 affected
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Zeeeepa
pushed a commit
to Zeeeepa/codegraph
that referenced
this pull request
Jun 22, 2026
* feat: add codegraph path for A→B symbol pathfinding Add `codegraph path <from> <to>` — BFS shortest-path search on the call graph. Given two symbol names, finds the shortest call chain with hop count, intermediate nodes, edge kinds, and alternate path count. Supports --reverse, --max-depth, --kinds, --from-file/--to-file, -T, -j, -k flags. Exposed as symbol_path MCP tool. Impact: 4 functions changed, 3 affected * docs: add Titan Paradigm use case, update docs with roles/co-change/path - Create docs/use-cases/titan-paradigm.md — maps Johannes R.'s multi-agent codebase cleanup architecture (RECON, GAUNTLET, GLOBAL SYNC, STATE MACHINE) to codegraph commands, roadmap items, and post-LLM-integration recommendations - Update roadmap/BACKLOG.md: mark optave#4 (node classification), optave#9 (git change coupling), optave#1 (dead code), optave#2 (shortest path), optave#12 (execution flow) as DONE; add 6 new Titan Paradigm-inspired items (optave#21-optave#26): composite audit, batch querying, triage priority queue, change validation predicates, graph snapshots, MCP orchestration tools - Update README.md: add roles + co-change to features table, differentiators, commands section, agent template, common flags, comparison table; update MCP tool count 18 → 19 - Update docs/recommended-practices.md: update MCP tool count and tool list, add roles/co-change/path to CLAUDE.md template and developer workflow, add "Understand architectural roles" and "Surface hidden coupling" sections, add co-change step to setup checklist - Add full examples with real output for roles, co-change, and path to docs/examples/CLI.md and docs/examples/MCP.md - Update GitHub repo description with new capabilities * docs: restore Architecture Refactoring phase, fix references - Restore Phase 3 (Architectural Refactoring) to ROADMAP - Renumber phases 4-8 and all cross-references - Fix MCP tool count per Greptile review * fix: correct MCP tool counts and backlog ID collisions Address Greptile review comments on optave#121: - Update MCP tool counts from 18/19 to 21 (22 in multi-repo mode) across README, recommended-practices, dogfood skill, titan-paradigm - Add missing execution_flow and list_entry_points to tool enumeration - Renumber new backlog items 21-26 → 27-32 to avoid collision with existing items 21-22 * feat: add token savings benchmark (codegraph vs raw navigation) Adds a benchmark suite that measures how much codegraph reduces token usage when AI agents navigate the Next.js codebase (~4k TS files). - scripts/token-benchmark-issues.js: 5 real Next.js PRs as test cases - scripts/token-benchmark.js: runner using Claude Agent SDK (baseline vs codegraph MCP), with --perf flag for build/query benchmarks - scripts/update-token-report.js: JSON → markdown report generator - docs/benchmarks/: methodology docs and placeholder report Impact: 21 functions changed, 7 affected * feat: extend benchmarks with incremental builds and expanded query coverage benchmark.js now measures no-op rebuilds, 1-file rebuilds, and query latency (fn-deps, fn-impact, path, roles) alongside full builds. update-benchmark-report.js renders new Incremental Rebuilds and Query Latency sections in BUILD-BENCHMARKS.md and adds incremental/query rows to the README performance table. All new fields are additive for backward compatibility. Impact: 5 functions changed, 2 affected * ci: include version in automated benchmark commits and PRs Extract version from benchmark result JSON and include it in branch names, commit messages, PR titles, and PR bodies across all 4 benchmark jobs (build, embedding, query, incremental). * fix: update remaining 19-tool references to 21-tool in README * docs: remove "viral" from titan paradigm LinkedIn reference * fix: use endLine for scope-aware caller selection in nested functions Nested/closure functions (e.g. nodeId inside exportMermaid) were incorrectly classified as [dead] because the caller selection loop picked the last definition where line <= call.line, creating self-call edges that got filtered out. Now uses endLine to find the innermost enclosing scope, so calls within an outer function correctly attribute the outer function as caller rather than the nested function itself. Fixes false-positive [dead] for nodeId in branch-compare.js, export.js, and queries.js. Impact: 1 functions changed, 17 affected * feat: add cognitive & cyclomatic complexity metrics Compute per-function complexity during build via single-traversal DFS of tree-sitter ASTs: cognitive (SonarSource), cyclomatic (McCabe), and max nesting depth. Stores results in new function_complexity table (migration v8) and surfaces them in stats, context, explain, and a dedicated `complexity` CLI command + MCP tool. Adds manifesto config section with warn thresholds (cognitive: 15, cyclomatic: 10, maxNesting: 4) seeding the future rule engine. Phase 1 supports JS/TS/TSX; unsupported languages are skipped gracefully. Impact: 18 functions changed, 32 affected --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Zeeeepa
pushed a commit
to Zeeeepa/codegraph
that referenced
this pull request
Jun 22, 2026
* fix: strict type validation for threshold values in complexity queries
Replace loose `!= null` checks with `typeof === 'number' && Number.isFinite()`
to prevent `Number("")`, `Number(null)`, and `Number(true)` from silently
coercing into valid SQL values. Add integration test verifying exceeds
arrays and summary.aboveWarn are correctly computed.
Addresses Greptile review feedback on optave#136.
Impact: 2 functions changed, 3 affected
* docs: add complexity, communities, and manifesto to all docs
Update README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices,
and CLI/MCP examples to reflect today's merged PRs: complexity metrics
(optave#130/optave#139), Louvain community detection (optave#133/optave#134), and manifesto rule
engine (optave#138). Updates MCP tool count from 21 to 24 (25 in multi-repo),
marks backlog items 6/11/21/22 as done, and adds real CLI output examples.
* fix: remove redundant condition in paginate guard clauses
When limit === undefined, limit !== 0 is always true — the && check
was dead code. Simplified to just check limit === undefined.
Impact: 2 functions changed, 18 affected
* docs: update dogfood report with fix statuses
All 4 bugs now fixed (PR optave#117 merged, optave#116 closed via reverse-dep
cascade). 3 of 4 suggestions addressed. MCP tool counts updated
18→23 / 19→24. Rating upgraded 7/10 → 9/10 post-fix.
* fix: rename misleading test to match actual behavior
Test was named "handles non-numeric thresholds gracefully" but only
validated baseline exceeds/aboveWarn with valid thresholds. Actual
non-numeric threshold tests exist separately. Renamed to "produces
correct exceeds and aboveWarn with valid thresholds".
* fix: update stale MCP tool count in dogfood skill (21→24)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Zeeeepa
pushed a commit
to Zeeeepa/codegraph
that referenced
this pull request
Jun 22, 2026
* fix: strict type validation for threshold values in complexity queries
Replace loose `!= null` checks with `typeof === 'number' && Number.isFinite()`
to prevent `Number("")`, `Number(null)`, and `Number(true)` from silently
coercing into valid SQL values. Add integration test verifying exceeds
arrays and summary.aboveWarn are correctly computed.
Addresses Greptile review feedback on optave#136.
Impact: 2 functions changed, 3 affected
* docs: add complexity, communities, and manifesto to all docs
Update README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices,
and CLI/MCP examples to reflect today's merged PRs: complexity metrics
(optave#130/optave#139), Louvain community detection (optave#133/optave#134), and manifesto rule
engine (optave#138). Updates MCP tool count from 21 to 24 (25 in multi-repo),
marks backlog items 6/11/21/22 as done, and adds real CLI output examples.
* fix: remove redundant condition in paginate guard clauses
When limit === undefined, limit !== 0 is always true — the && check
was dead code. Simplified to just check limit === undefined.
Impact: 2 functions changed, 18 affected
* docs: update dogfood report with fix statuses
All 4 bugs now fixed (PR optave#117 merged, optave#116 closed via reverse-dep
cascade). 3 of 4 suggestions addressed. MCP tool counts updated
18→23 / 19→24. Rating upgraded 7/10 → 9/10 post-fix.
* fix: rename misleading test to match actual behavior
Test was named "handles non-numeric thresholds gracefully" but only
validated baseline exceeds/aboveWarn with valid thresholds. Actual
non-numeric threshold tests exist separately. Renamed to "produces
correct exceeds and aboveWarn with valid thresholds".
* fix: update stale MCP tool count in dogfood skill (21→24)
* feat: add complexity analysis for Python, Go, Rust, Java, C#, Ruby, PHP
Parameterize the complexity algorithm to support all 10 languages instead
of just JS/TS/TSX. Add per-language COMPLEXITY_RULES, HALSTEAD_RULES, and
COMMENT_PREFIXES with three else-if detection patterns (else-wraps-if,
explicit elif, alternative field). Guard against tree-sitter keyword leaf
tokens that share node type names with their parent constructs.
Impact: 4 functions changed, 4 affected
---------
Co-authored-by: github-actions[bot] <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
function_complexitytable (migration v8) with indexes; incremental cleanup integrated into builder pipelinecodegraph complexityCLI command with sorting, filtering (file/kind/target), threshold-aware output, and JSON modestats,context, andexplaincommands with complexity datacomplexitytool exposing all query options to AI agentsmanifesto.rules) with configurable warn/fail thresholds seeding the future rule engineTest plan
complexitytool routes tocomplexityDatawith all argsnode src/cli.js build .logs "Complexity: 63 functions analyzed"node src/cli.js complexity --limit 5shows top complex functionsnode src/cli.js stats -Tincludes complexity summary lineCloses #21, closes #6. Seeds #22.