mcpField
P
performance-review

performance-review

github.com/atholaTesting & quality34375 installsUpdated 4d ago
Repository

About performance-review

A static-analysis skill that reviews code for time- and space-complexity hotspots. It always scans Python and can add selected language and call-graph coverage when optional dependencies are available.

Key features

  1. 01Scan Python with stdlib AST
  2. 02Detect time and space hotspots
  3. 03Optional JS/TS and systems-language scans
  4. 04Upgrade severity using call-graph data
  5. 05Generate categorized Markdown findings

Use cases

  1. 01Review changed code before merging
  2. 02Triage suspected slow functions
  3. 03Check refactors for quadratic patterns
  4. 04Inspect AI-generated code for nested-loop hotspots

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/athola/claude-night-market --skill performance-review

After installing, type/performance-reviewin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

modules/
gauntlet-integration.md
kuva-visualization.md
memory-allocation-lenses.md
space-complexity.md
time-complexity.md

Details

From the project README

Performance Review

Static-analysis review of time and space complexity hotspots.

The skill runs in three escalating tiers. Tier 1 uses Python's stdlib ast and always runs. Tier 2 uses tree-sitter to extend detection to JS/TS, Go, Rust, Java, and C/C++ when the tiers extra is installed. Tier 3 walks the gauntlet call graph forward from each finding and raises its severity one step when a callee holds a hotspot, and runs when the gauntlet plugin is importable and a .gauntlet/graph.db exists. Without them, Tiers 2 and 3 no-op and Tier 1 still produces findings on Python source.

Quick Start

/performance-review                  # scan changed files
/performance-review path/to/file.py  # scan one file
/performance-review --tier 1         # force Tier 1 only

Programmatic use:

from pensive.skills.performance_review import PerformanceReviewSkill

skill = PerformanceReviewSkill()
result = skill.analyze(context, "src/module.py")
for f in result.issues:
    print(f"[{f.severity}] {f.file}:{f.line} {f.message}")

When To Use

  • Pre-merge review of code that runs on user-scaled inputs.
  • Triage of a function that "feels slow" before reaching for a profiler.
  • Audit a refactor for newly introduced O(n²) patterns.
  • Guardrail for AI-generated code where nested-loop hot spots are common.

When NOT to Use

  • The target needs runtime measurement (memory profile, CPU time on real data). Use Skill(parseltongue:python-performance) instead: that skill drives cProfile, py-spy, and benchmarks.
  • General refactoring guidance not focused on hotspots: use Skill(pensive:code-refinement) whose algorithm-efficiency module covers broader optimization patterns. This skill detects; that skill teaches.
  • Deciding whether a hand-rolled loop transform (unrolling, manual SIMD, strength reduction) is worth keeping: use Skill(leyline:loop-optimization) for the hand-vs-compiler rule. This skill flags hotspot shapes, not transformation choices.
  • Architecture-level performance (sharding, caching layers, queue placement): use Skill(pensive:architecture-review).

Required Progress Items

  1. perf-review:context-established
  2. perf-review:scan-complete
  3. perf-review:findings-categorized
  4. perf-review:integration-checked
  5. perf-review:report-generated
  6. perf-review:findings-verified

Workflow

Step 1: Context (perf-review:context-established)
  • Identify target files. If invoked with no argument, use git diff --name-only. If invoked with a path, scope to that.
  • Note language(s) involved. Tier 1 covers Python; non-Python files need the tiers extra for Tier 2 coverage.
Step 2: Tier 1 AST scan (perf-review:scan-complete)

Load modules/time-complexity.md for the time-side patterns and modules/space-complexity.md for space-side. Each module documents the AST shape of every detector.

Alongside the automated scan, load modules/memory-allocation-lenses.md and apply its three manual lenses (unbounded external-source collections, hot-path recompute, serial blocking I/O) by reading the target files.

For each Python target file, call:

from pensive.skills.performance_review import PerformanceReviewSkill

result = PerformanceReviewSkill().analyze(context, path)

The visitor walks the AST once and emits ReviewFinding records.

Step 3: Categorize and rank (perf-review:findings-categorized)

Group findings by severity:

  • HIGH: O(n²) or worse on input-sized iterables (T1, T2).
  • MEDIUM: Unbounded allocation or per-iteration overhead (T3, T4, S1, S3).
  • LOW: Style-level inefficiencies (T5, T6, S2).
  • CRITICAL: Reserved for Tier-3 transitive upgrades.

Within a severity, sort by file then line. Suppress findings the user has explicitly marked acceptable (TODO/comment markers) at module-load time of the target.

Step 4: Tier 2/3 enrichment (perf-review:integration-checked)

Load modules/gauntlet-integration.md for the contract.

If tree_sitter_language_pack is importable, run Tier 2 on non-Python files that were skipped at Step 2. If gauntlet is importable and a .gauntlet/graph.db exists in the scanned file's directory or any parent, run Tier 3 to upgrade severities based on hotspots in transitive callees.

Without the extra, this step is a no-op and the report notes "Tier 2/3 not available: install pensive with the tiers extra for multi-language and call-chain coverage." A file that tree-sitter cannot parse adds a warning and yields no Tier 2 findings.

Step 5: Report (perf-review:report-generated)

Emit a markdown report:

## Performance Review: <target>

### HIGH (<count>)
- src/foo.py:42: Nested loop over the same iterable 'items'.
  Suggestion: sort + two pointers, or hash-set membership.

### MEDIUM (<count>)
- ...

### LOW (<count>)
- ...

Tier coverage: 1 (always) | 2 (gauntlet ✓/✗) | 3 (graph ✓/✗)

The report is informational. Apply fixes via Skill(pensive:code-refinement) or hand-merge.

Tiered Analysis

TierSourceWhen it runsWhat it covers
1stdlib astAlways (Python source only)T1-T6, S1-S3
2tree_sitter_language_packWhen importable, non-Python filesT1, T2, S1 on JS/TS, Go, Rust, Java, C/C++ (Java and C: T1 only)
3gauntlet.graph.GraphStoreWhen importable and .gauntlet/graph.db is found above the fileOne-step severity upgrade when a CALLS-reachable function holds a hotspot

Output Format

Findings use the shared ReviewFinding dataclass from pensive.skills.base:

ReviewFinding(
    file="src/module.py",
    line=42,
    severity="HIGH",  # LOW | MEDIUM | HIGH | CRITICAL
    category="time",  # time | space
    message="Nested loop over the same iterable 'items'.",
    suggestion="Sort + two pointers, or hash-set membership.",
    anchor="verbatim source text at file:line",
    code_snippet="",
)

This shape matches every other pensive review skill, so the findings can flow into Skill(pensive:unified-review) without translation.

Cross-Plugin Dependencies

DependencyRequired?Effect when missing
tree_sitter_language_packOptional (tiers extra)Tier 2 returns []; Python coverage unchanged
gauntlet.graph.GraphStoreOptional (gauntlet plugin, not on PyPI)Tier 3 returns []; severities are not upgraded

The optional-import contract follows the precedent in plugins/leyline/src/leyline/tokens.py:25-32: try-import to a module-level sentinel, then early-return on None inside each tier helper. plugins/gauntlet/hooks/precommit_gate.py:35-40 is the boolean-flag variant of the same shape. See modules/gauntlet-integration.md for the exact code shape.

Supporting Modules

  • modules/time-complexity.md: T1-T6 detector patterns and AST shapes.
  • modules/space-complexity.md: S1-S3 detector patterns.
  • modules/gauntlet-integration.md: Tier 2/3 contract, fallback semantics, examples.
  • modules/kuva-visualization.md: Rendering benchmark data as charts with kuva (criterion, pytest-benchmark, ad-hoc tables). Covers when chart evidence satisfies proof-of-work requirements.
  • modules/memory-allocation-lenses.md: Manual review lenses (not AST detectors) for unbounded collections fed from external sources, hot-path recompute that should be memoized, and serial blocking I/O over unbounded sets. Apply by reading the code; the detector-test rule in Testing does not cover these because nothing is automated.

Verification

A perf-review finding is only useful if the caller can confirm it is real. Use this checklist before treating any finding as worth fixing:

  1. Reproduce under a profiler. Run cProfile, py-spy, or the language-specific equivalent on the hotspot. The findings pinpoint AST shapes; the profiler validates the runtime impact.
  2. Re-run the failing benchmark. If benches/ exists, the hotspot should show up in numbers, not just AST scans.
  3. Compare numbers before and after the proposed fix. The fix is wrong if numbers do not move. Capture both timings as evidence references like [E1] (before) and [E2] (after). When 3+ data points exist, render a kuva chart and attach it to the PR (see modules/kuva-visualization.md).
  4. Sample two or three reported hotspots manually. Findings can be true at the AST level and false at the call-graph level when callers short-circuit. Manual sampling catches that.

The Skill(imbue:proof-of-work) discipline applies: claims like "the hotspot is fixed" require evidence, not assertion.

Testing

A test file already lives at plugins/pensive/tests/skills/test_performance_review.py covering the AST-shape detectors. Two rules for changes here:

  • Add a new detector with a test. Any new T-* or S-* pattern added to the modules ships with a test that has the smallest AST sample exercising it.
  • Add a regression test for any false positive removed. When the skill stops firing on a shape that used to look hot, the reason should appear as a test case so the regression is discoverable later.

The Iron Law applies: a new detector without a failing test first is a request to skip TDD on a code-analysis component, which is exactly the place where TDD pays off most.

Verify Findings Are Grounded (perf-review:findings-verified)

Write findings to .review/findings.json, run the citation verifier (Skill(imbue:review-core) Step 5), and drop or label UNVERIFIED any the verifier rejects.

Exit Criteria

  • A perf-review report file exists for the requested target.
  • Every finding carries a severity label and a concrete suggestion the caller can act on.
  • Time-complexity (T1-T6) and space-complexity (S1-S3) detectors have been run; tier coverage is reported.
  • Tier 2 (tree-sitter) and Tier 3 (graph store) contracts honor the optional-import sentinel: missing modules return [] rather than raising.
  • Each new detector ships with a smallest-AST test that fails before the detector exists; each removed false positive ships with a regression test.
  • Findings flow into Skill(pensive:unified-review) without translation when invoked from the unified entry point.
  • Every reported finding carries a Location + verbatim Anchor confirmed by citation_verifier.py (exit 0), or unverified findings were dropped or labeled UNVERIFIED

Comments

Markdown supported