rtk-ai/rtk

rtk lint drops cognitive-complexity scores and method identity, losing irreducible info during summarization

Open

#2,217 opened on Jun 2, 2026

View on GitHub
 (1 comment) (0 reactions) (0 assignees)Rust (48,085 stars) (2,914 forks)batch import
area:clibughelp wantedpriority:medium

Description

Summary

CONTRIBUTING states that rtk's output "must be a valid, useful subset of the original tool's output, not a different format." rtk lint violates this for ESLint: it collapses findings to rule + file + count, discarding each finding's message body. For most rules the message is recoverable from the rule name, but for rules whose message carries quantitative payload — notably sonarjs/cognitive-complexity — the dropped text is the actionable information and cannot be reconstructed from what's shown.

Steps to reproduce

Run rtk lint and eslint . on a project with a sonarjs/cognitive-complexity violation, and compare.

Expected vs actual

Expected: a useful subset of ESLint's output — i.e. enough to act on each finding.

Actual: the complexity score, the threshold, and which method is over are all dropped.

rtk lint (actual):

Top files:
  Item.tsx (1 issues)
    sonarjs/cognitive-complexity (1)
  seed-dev-users.ts (1 issues)
    sonarjs/cognitive-complexity (1)

eslint . (original):

app/(main)/items/ui/components/Item.tsx
  34:25  error  Refactor this function to reduce its Cognitive Complexity from 24 to the 15 allowed  sonarjs/cognitive-complexity

scripts/seed-dev-users.ts
  754:39  warning  Refactor this function to reduce its Cognitive Complexity from 20 to the 15 allowed  sonarjs/cognitive-complexity

What's lost

For cognitive-complexity, two things matter and both disappear:

  1. The score and threshold (from 24 to the 15 allowed) — irreducible. This is how far over you are and how big the refactor is. 24 → 15 and 16 → 15 are very different jobs; the summary makes them identical. The current score cannot be reconstructed from the rule name.
  2. Which method is too complex — the summary only names the file, which can hold many functions. Knowing which one is over is what lets you act. (ESLint itself only emits a line:col here, not the symbol name — so ideally rtk resolves and surfaces the offending function name; at minimum it should preserve the location as a pointer.)

Why this is worse than "just add a verbose mode"

  • The loss is uneven across rules. no-unused-vars and no-img-element are well-described by their rule name alone. cognitive-complexity is not — its message body is the finding. A good summary would retain message bodies for rules whose name isn't self-describing.
  • The (1) / 3x counts can be misread as the metric. Seeing sonarjs/cognitive-complexity (3x) invites confusion with a complexity score; it's actually a violation count.
  • It can invert RTK's value proposition. Recovering the number means opening the tee'd raw log (..._lint.log) and reading the full output — spending more tokens than un-summarized eslint would have for this class of finding.

Suggested directions

  • Retain the message body for findings whose rule isn't in a "self-describing" set — or simply retain message bodies for all error-severity findings.
  • Special-case the quantitative SonarJS rules (e.g. cognitive-complexity and other sonarjs/* rules that embed numbers) so their numeric message survives summarization.
  • For cognitive-complexity specifically, surface the offending function/method identity (resolved name if feasible, otherwise the line:col location).

Environment

  • rtk: 0.42.0
  • OS: macOS (Darwin 25.3.0)
  • ESLint: 9.39.4
  • eslint-plugin-sonarjs: 4.0.3

Contributor guide