Skip to content

refactor: unify impact-level rendering format between audit and fn-impact commands#1874

Closed
carlos-alm wants to merge 2 commits into
fix/issue-1755-leiden-deltamod-directed-complexityfrom
fix/issue-1756-dedupe-impact-level-rendering
Closed

refactor: unify impact-level rendering format between audit and fn-impact commands#1874
carlos-alm wants to merge 2 commits into
fix/issue-1755-leiden-deltamod-directed-complexityfrom
fix/issue-1756-dedupe-impact-level-rendering

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

BEHAVIOR CHANGE: codegraph audit's impact-level text output now matches fn-impact's icon+truncation format, per this issue's own recommendation.

  • renderAuditFunction (audit.ts) and printFnImpactLevels (queries-cli/impact.ts) duplicated impact-level rendering with different formats: audit.ts's was plain-text/unlimited, impact.ts's had icons/file:line/truncation-at-20.
  • Investigated downstream dependencies before changing anything: no test asserts on the old text format (only --json output is tested at the CLI level), no .claude/skills/hooks parse the plain-text format (all pass --json), and both call sites already source levels from the same bfsTransitiveCallers function so name/kind/file/line are always populated identically — no data-shape gap to handle.
  • Extracted renderImpactLevels(levels, opts) (new src/presentation/impact-levels.ts) using the richer fn-impact format as canonical; adopted in both call sites, removing printFnImpactLevels entirely.

Closes #1756

Test plan

  • npm test — full suite green (3519 passed, 0 failed), zero test updates needed since nothing asserted on the old format
  • npm run lint / npm run typecheck — clean
  • Manual: codegraph audit <fn> -T and codegraph fn-impact <fn> -T against this repo's own graph now render impact levels identically; zero-impact case correctly preserves each command's existing empty-state convention (audit suppresses, fn-impact shows "No callers found.")

Filed #1873 for a pre-existing, unrelated finding: docs/examples/CLI.md/MCP.md's audit/diff-impact example output blocks are already stale relative to the current implementation.

Stacked on #1872 (base branch fix/issue-1755-leiden-deltamod-directed-complexity) — only the presentation diff is this issue's change.

…pact commands

`renderAuditFunction` (presentation/audit.ts) and `printFnImpactLevels`
(presentation/queries-cli/impact.ts) both rendered the same
`Record<number, ImpactLevelEntry[]>` transitive-caller-levels shape
(produced by the shared `bfsTransitiveCallers` BFS) but with two
different, independently-maintained text formats.

Extract a single `renderImpactLevels(levels, opts)` helper into a new
presentation/impact-levels.ts module and adopt it in both call sites,
using the richer icon+truncation format from fn-impact as the canonical
one (per issue #1756's recommendation). `opts.emptyMessage` lets audit.ts
suppress the "No callers found." line, since its "Impact: N transitive
dependent(s)" line already conveys a zero count and none of its other
subsections (Calls/Called by/Tests) print an explicit empty message either.

Investigated downstream dependents before making this change:
- No test asserts on audit.ts's exact text output; tests/integration/audit.test.ts
  only exercises the auditData data layer, and all CLI-level audit/fn-impact
  tests (tests/integration/cli.test.ts, tests/unit/queries-unit.test.ts) use
  --json.
- No skill or hook in .claude/ parses this text; every `codegraph audit`
  invocation across .claude/skills/ already passes --json.
- docs/examples/CLI.md and MCP.md do document an audit output example, but
  it was already stale relative to the current implementation independent of
  this change (wrong header/complexity/impact wording, single-line "Calls:"
  list) -- filed as #1873 rather than fixing inline.
- README.md/CLAUDE.md/ROADMAP.md contain no example output text for audit's
  impact-level rendering (checked directly) -- docs check acknowledged.

BEHAVIOR CHANGE: `codegraph audit`'s impact-level text output now matches
`codegraph fn-impact`'s icon+truncation format (per-level header with count,
`^ <icon> <name>  <file>:<line>` per entry, truncated at 20 with "... and N
more") instead of the old plain `Level {n}: name1, name2, ...` comma list.
--json/--ndjson output is unaffected.

Fixes #1756

Impact: 9 functions changed, 6 affected
@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR extracts the duplicated impact-level rendering logic from audit.ts and queries-cli/impact.ts into a new shared module src/presentation/impact-levels.ts, making the two commands' text output visually identical. The audit command now renders impact levels with icons, file:line references, and per-level truncation rather than the former plain comma-joined names.

  • New renderImpactLevels(levels, opts) in impact-levels.ts is the canonical renderer; opts.emptyMessage (defaulting to " No callers found.") and opts.limit (default 20) give callers the flexibility to preserve each command's existing empty-state convention.
  • printFnImpactLevels is deleted from impact.ts; both call sites now delegate to the shared function.
  • The emptyMessage !== null guard (strict null check) correctly honours the documented null-means-silent contract, and the default sort by numeric level key matches the old behaviour.

Confidence Score: 5/5

Safe to merge — the change is a straightforward extraction of duplicated rendering logic into a well-typed shared module with no behavioural surprises.

Both call sites are updated consistently, the strict-null guard on emptyMessage correctly honours the documented contract, the sort and truncation logic are faithful copies of the deleted function, and the typecheck + full test suite pass cleanly with zero test changes needed.

No files require special attention.

Important Files Changed

Filename Overview
src/presentation/impact-levels.ts New shared renderer; correct strict-null guard, configurable limit/emptyMessage, and level-sorted iteration identical to the removed printFnImpactLevels.
src/presentation/audit.ts renderImpactSection now delegates to renderImpactLevels with emptyMessage:null, correctly suppressing the empty-state line that the count line above already communicates.
src/presentation/queries-cli/impact.ts printFnImpactLevels removed; fnImpact now calls renderImpactLevels with default opts, preserving the original "No callers found." empty-state message.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["codegraph audit"] -->|"renderImpactSection(fn)"| C
    B["codegraph fn-impact"] -->|"fnImpact(name, ...)"| D

    C["renderImpactLevels(fn.impact.levels,\n{ emptyMessage: null })"]
    D["renderImpactLevels(r.levels)\n(emptyMessage defaults to 'No callers found.')"]

    C --> E["impact-levels.ts\nrenderImpactLevels(levels, opts)"]
    D --> E

    E --> F{levels empty?}
    F -->|yes + emptyMessage !== null| G["console.log(emptyMessage)"]
    F -->|yes + emptyMessage === null| H["(silent)"]
    F -->|no| I["sort by numeric level\nfor each level: print header + up to limit entries\n+ truncation notice if needed"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["codegraph audit"] -->|"renderImpactSection(fn)"| C
    B["codegraph fn-impact"] -->|"fnImpact(name, ...)"| D

    C["renderImpactLevels(fn.impact.levels,\n{ emptyMessage: null })"]
    D["renderImpactLevels(r.levels)\n(emptyMessage defaults to 'No callers found.')"]

    C --> E["impact-levels.ts\nrenderImpactLevels(levels, opts)"]
    D --> E

    E --> F{levels empty?}
    F -->|yes + emptyMessage !== null| G["console.log(emptyMessage)"]
    F -->|yes + emptyMessage === null| H["(silent)"]
    F -->|no| I["sort by numeric level\nfor each level: print header + up to limit entries\n+ truncation notice if needed"]
Loading

Reviews (3): Last reviewed commit: "fix: use strict null check for emptyMess..." | Re-trigger Greptile

Comment thread src/presentation/impact-levels.ts
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

9 functions changed6 callers affected across 4 files

  • renderImpactSection in src/presentation/audit.ts:67 (3 transitive callers)
  • ImpactLevelRef.name in src/presentation/impact-levels.ts:14 (0 transitive callers)
  • ImpactLevelRef.kind in src/presentation/impact-levels.ts:15 (0 transitive callers)
  • ImpactLevelRef.file in src/presentation/impact-levels.ts:16 (0 transitive callers)
  • ImpactLevelRef.line in src/presentation/impact-levels.ts:17 (0 transitive callers)
  • RenderImpactLevelsOpts.emptyMessage in src/presentation/impact-levels.ts:26 (0 transitive callers)
  • RenderImpactLevelsOpts.limit in src/presentation/impact-levels.ts:28 (0 transitive callers)
  • renderImpactLevels in src/presentation/impact-levels.ts:41 (5 transitive callers)
  • fnImpact in src/presentation/queries-cli/impact.ts:232 (1 transitive callers)

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm carlos-alm deleted the branch fix/issue-1755-leiden-deltamod-directed-complexity July 6, 2026 22:20
@carlos-alm carlos-alm closed this Jul 6, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 6, 2026
@carlos-alm

Copy link
Copy Markdown
Contributor Author

Recreated as #1931 — this PR was inadvertently closed when its stacked base branch was deleted after #1925 merged. Continuing there.

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.

1 participant