refactor: unify impact-level rendering format between audit and fn-impact commands#1874
Conversation
…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 SummaryThis PR extracts the duplicated impact-level rendering logic from
Confidence Score: 5/5Safe 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
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"]
%%{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"]
Reviews (3): Last reviewed commit: "fix: use strict null check for emptyMess..." | Re-trigger Greptile |
Codegraph Impact Analysis9 functions changed → 6 callers affected across 4 files
|
Summary
BEHAVIOR CHANGE:
codegraph audit's impact-level text output now matchesfn-impact's icon+truncation format, per this issue's own recommendation.renderAuditFunction(audit.ts) andprintFnImpactLevels(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.--jsonoutput is tested at the CLI level), no.claude/skills/hooks parse the plain-text format (all pass--json), and both call sites already sourcelevelsfrom the samebfsTransitiveCallersfunction soname/kind/file/lineare always populated identically — no data-shape gap to handle.renderImpactLevels(levels, opts)(newsrc/presentation/impact-levels.ts) using the richer fn-impact format as canonical; adopted in both call sites, removingprintFnImpactLevelsentirely.Closes #1756
Test plan
npm test— full suite green (3519 passed, 0 failed), zero test updates needed since nothing asserted on the old formatnpm run lint/npm run typecheck— cleancodegraph audit <fn> -Tandcodegraph fn-impact <fn> -Tagainst 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'saudit/diff-impactexample 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.