feat: halstead metrics, maintainability index, and docs update by carlos-alm · Pull Request #142 · optave/ops-codegraph-tool · GitHub
Skip to content

feat: halstead metrics, maintainability index, and docs update#142

Closed
carlos-alm wants to merge 5 commits into
mainfrom
feat/halstead-maintainability-index
Closed

feat: halstead metrics, maintainability index, and docs update#142
carlos-alm wants to merge 5 commits into
mainfrom
feat/halstead-maintainability-index

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

  • Halstead metrics & Maintainability Index — extends codegraph complexity with Halstead volume, difficulty, effort, estimated bugs, and MI per function. New --health flag for full Halstead view, --sort mi to rank by worst MI. Stored in function_complexity DB table
  • Pagination & streaming — bounded query results with paginate.js helpers for context-friendly output across CLI and MCP
  • Bug fixes — exclude uncomputed MI=0 rows from threshold filtering; strict type validation for threshold values
  • Docs update — adds complexity, communities (feat: louvain community detection for module boundary analysis #133/feat: louvain community detection + fix complexity build regression #134), and manifesto (feat: manifesto-driven pass/fail rule engine #138) to all 7 doc files: README, CLAUDE.md, BACKLOG, titan-paradigm, recommended-practices, CLI examples, MCP examples. Updates MCP tool count 21→24 (25 multi-repo), marks backlog items 6/11/21/22 as done

Test plan

  • npm test passes
  • codegraph complexity -T shows cognitive, cyclomatic, nesting, MI columns
  • codegraph complexity --health -T shows Halstead columns (volume, diff, effort, bugs, LOC, SLOC)
  • codegraph complexity --sort mi -T sorts ascending by MI
  • codegraph complexity --above-threshold -T filters to flagged functions only
  • Verify no stale "21 tools" references remain in docs (should be 24/25)
  • Verify BACKLOG items 6, 11, 21, 22 are marked DONE

Add formal code health metrics per function: Halstead volume, difficulty,
effort, bugs estimate, LOC/SLOC, and the industry-standard Maintainability
Index (MI) normalized to 0-100 (Microsoft convention). MI below 20 flags
functions needing refactoring attention.

- DB migration v9: 14 new columns on function_complexity table
- HALSTEAD_RULES registry for JS/TS/TSX operator/operand classification
- computeHalsteadMetrics(), computeLOCMetrics(), computeMaintainabilityIndex()
- complexity command: MI column in default view, --health flag for full
  Halstead view, --sort mi|volume|effort|bugs|loc options
- stats/context/explain commands surface MI per function
- MCP tool schema updated with new sort values and health property
- Config: maintainabilityIndex threshold { warn: 20, fail: null }
- 29 new tests (18 unit + 11 integration)

Impact: 16 functions changed, 30 affected

Impact: 16 functions changed, 30 affected
…sults

Add offset/limit pagination to data functions so MCP clients get bounded
results with metadata to request more, and CLI consumers can process
results incrementally via NDJSON.

- New src/paginate.js with paginate(), paginateResult(), MCP_DEFAULTS,
  MCP_MAX_LIMIT utilities
- Pagination support in listFunctionsData, queryNameData, whereData,
  rolesData, listEntryPointsData
- Export limiting for DOT/Mermaid (truncation comments) and JSON
  (edge pagination)
- MCP tool schemas updated with limit/offset props and sensible defaults
  (e.g. list_functions: 100, query_function: 50)
- CLI --limit, --offset, --ndjson flags on query, where, roles, flow
- Programmatic API exports from index.js
- 33 new integration tests covering all pagination scenarios

Impact: 19 functions changed, 18 affected
The --above-threshold filter for maintainabilityIndex now requires
MI > 0, consistent with the exceeds array logic that already guards
against uncomputed rows from pre-migration databases.

Impact: 1 functions changed, 4 affected

Impact: 1 functions changed, 1 affected
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
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.
@greptile-apps

greptile-apps Bot commented Feb 27, 2026

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

21 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment thread src/paginate.js
* @returns {{ items: any[], pagination?: { total: number, offset: number, limit: number, hasMore: boolean, returned: number } }}
*/
export function paginate(items, { limit, offset } = {}) {
if (limit === undefined && limit !== 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic error: && limit !== 0 should be removed or the operator should be ||

The condition currently checks if limit is undefined AND not zero, but when limit is undefined, the second check is always true and redundant. Based on the docstring ("When limit is undefined the input is returned unchanged"), this should just be:

Suggested change
if (limit === undefined && limit !== 0) {
if (limit === undefined) {

or to handle null as well:

Suggested change
if (limit === undefined && limit !== 0) {
if (limit == null) {

Comment thread src/paginate.js
* @returns {object} - Result with paginated field + `_pagination` (if active)
*/
export function paginateResult(result, field, { limit, offset } = {}) {
if (limit === undefined && limit !== 0) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same logic error as line 31: && limit !== 0 is redundant and confusing

Suggested change
if (limit === undefined && limit !== 0) {
if (limit === undefined) {

@carlos-alm carlos-alm closed this Feb 27, 2026
@carlos-alm carlos-alm deleted the feat/halstead-maintainability-index branch February 27, 2026 02:08
@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

21 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

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