Communitygithub.com

Qualitätsprüfung

Überprüft einen Diff, Branch, PR oder vorhandenen Code (einen Pfad oder das gesamte Repository) auf Codequalität anhand von ~/.claude/CODING_STANDARDS.md unter Verwendung des Deep-Module-Vokabulars.

Was ist Qualitätsprüfung?

Dieser Skill führt eine gründliche Design- und Testqualitätsprüfung für eine angegebene Codebasis, einen Diff, Branch oder PR durch. Er lädt eine standardisierte Bewertungsmatrix aus `~/.claude/CODING_STANDARDS.md` und verwendet ein spezifisches Vokabular (Modul, Schnittstelle, Naht, Adapter, Tiefe, Hebelwirkung, Lokalität), um Ergebnisse zu formulieren. Der Skill analysiert Modultiefe und -verantwortung, Zustandsbesitz und Unveränderlichkeit, Konzeptbesitz und Typen (einschließlich der Vermeidung ungültiger Zustände), Abhängigkeitsinjektion und -konfiguration, Fehlersichtbarkeit, Benennung und Lesbarkeit von Funktionen sowie Testqualität. Bei der Überprüfung eines gesamten Codebestands hinterfragt er auch die wichtigsten Designentscheidungen des Produkts im Vergleich zu alternativen Richtungen. Er ist für die Verwendung mit Benutzeranfragen wie „Qualitätsüberprüfung“, „Codequalität prüfen“, „gegen meine Codierungsstandards prüfen“ oder dem Befehl `/quality-review` optimiert. Der Skill unterscheidet sich von einer Fehlerjagd; er konzentriert sich auf Designprobleme, nicht auf Korrektheit, wobei letztere Aufgabe dem Befehl `/code-review` vorbehalten bleibt.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mattac21/skills/tree/HEAD/skills/quality-review

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht Qualitätsprüfung?

Ziel: $ARGUMENTS

Überprüfen Sie das Ziel auf Design- und Testqualität. Melden Sie Ergebnisse; bearbeiten Sie keinen Code.

1. Die Bewertungsmatrix laden

Lesen Sie beides, bevor Sie den Code ansehen:

  • ~/.claude/CODING_STANDARDS.md ist die Bewertungsmatrix. Jedes Ergebnis zitiert einen seiner Abschnittsüberschriften.
  • design-vocabulary.md enthält die Begriffe, um Ergebnisse zu formulieren, und die Tests, die unten zu deren Überprüfung verwendet werden.

Lesen Sie auch das AGENTS.md / CLAUDE.md des Repositorys, falls vorhanden. Wenn diese Dateien besagen, dass das Repository bewusst etwas tut, das die Standards nicht empfehlen, erwähnen Sie dies einmal im Bericht, anstatt jede Instanz zu markieren. Eine Gewohnheit, die Sie nur im Code beobachten (jedes Modul liest die Umgebung, jeder Test patcht), ist keine dokumentierte Entscheidung: Neuer Code, der ihr folgt, ist trotzdem ein Ergebnis.

2. Das Ziel auflösen

  • Kein Argument: der aktuelle Branch gegen seinen Basis-Branch. git merge-base HEAD origin/main (oder master), dann git diff <base>...HEAD plus nicht committete Änderungen von git diff HEAD.
  • PR-Nummer oder URL: gh pr diff <n> und gh pr view <n> --json baseRefName,headRefName,files.
  • Branch: git diff <base>...<branch>.
  • Pfad, oder . für das gesamte Repository: Überprüfen Sie den vorhandenen Code unter diesem Pfad so, wie er ist, ohne Diff. Dies ist der Codebase-Modus, siehe unten.

3. Genug lesen, um das Design zu beurteilen

Änderungsmodus (Diff, Branch, PR)

Ein Diff allein kann nicht zeigen, ob ein Modul tief ist. Lesen Sie für jedes geänderte Modul die gesamte Datei und durchsuchen Sie nach seinen Aufrufern und seinen Tests. Tiefe, Besitz und Duplizierung sind Urteile über die Aufrufstellen, sehen Sie sich diese also an.

Begrenzen Sie die Ergebnisse auf das, was die Änderung einführt oder verschlechtert. Ein bereits bestehendes Problem in Code, den der Diff berührt, ist im Umfang, wenn die Änderung der natürliche Moment war, es zu beheben; eines in unberührtem Code ist nicht im Umfang.

Neue Module erhalten eine Überprüfung auf Modulebene, wie im Codebase-Modus: Gehen Sie Typen und Lesbarkeit so vollständig durch wie die anderen Abschnitte. Listen Sie für jedes neue oder wesentlich umgeschriebene Modul jede Funktion mit ihren Parameter- und Rückgabetypen auf, bevor Sie es beurteilen, und notieren Sie jede untypisierte Map, dict oder Tupel, die es akzeptiert, zurückgibt oder Schlüssel daraus liest, sowie jeden einbuchstabigen Namen.

Messen Sie die zyklomatische Komplexität für jede geänderte Quelldatei, bevor Sie die Lesbarkeit beurteilen, mit dem üblichen Tool der Sprache: zum Beispiel radon cc -s für Python, gocyclo für Go, die complexity-Regel von eslint für JavaScript/TypeScript, cognitive_complexity von Clippy für Rust, PMD für Java. Führen Sie es durch die eigenen Tools des Repositorys aus, falls vorhanden, oder einen einmaligen Runner (uvx, npx, go run), falls nicht. Bevorzugen Sie ein Tool, das kurzschließende boolesche Operanden zählt; einige (rufs C901 zum Beispiel) überspringen sie und untertreiben die schlimmsten Funktionen. Wenn kein Tool verfügbar ist, zählen Sie Entscheidungspunkte manuell, wie die Bewertungsmatrix sie definiert. Eine Funktion, die der Diff hinzufügt und die über 10 liegt, oder eine bestehende, die der Diff über 10 drückt oder weiter erhöht, ist ein Kandidat. Bewerten Sie bei einer bestehenden Funktion auch die Basisversion (schreiben Sie git show :` in eine Scratchpad-Datei und messen Sie diese), damit das Ergebnis sagen kann, was die Änderung hinzugefügt hat.

Wenn der Diff mehr als etwa 150 Zeilen Quellcode hinzufügt, starten Sie parallel zwei general-purpose Subagenten, während Sie die Designabschnitte überprüfen, jeder mit dem Diff, der Liste der geänderten Dateien und den Überprüfungsregeln aus Schritt 4 für seine Abschnitte: einer für Typen, Lesbarkeit und „Neigen Sie zu unveränderlichen Daten, wo es sich auszahlt“, der andere für Tests, wobei die Assertionsprüfungen auf jeden neuen Test angewendet werden. Überprüfen Sie, was jeder zurückgibt, bevor Sie es behalten.

Codebase-Modus (Pfad oder .)

Alles unter dem Pfad ist im Umfang, aber die Hürde für ein Ergebnis steigt mit der Größe des Umfangs. Ein einzelnes Modul oder kleines Verzeichnis (grob unter 1.500 Zeilen Quellcode) erhält Ergebnisse auf Modul-, Funktions- und Benennungsebene: Gehen Sie Typen und Lesbarkeit so vollständig durch wie die anderen Abschnitte. Ein Paket oder das gesamte Repository erhält nur die großen Probleme: die Designentscheidungen und Architekturmuster, die die Codebasis zurückhalten. Gleiches gilt, wenn der Benutzer ein Feature oder Tool benennt (z. B. „die gesamte CLI“), das sich als ein Modul herausstellt: Beurteilen Sie es auf Modulebene. Fragen Sie bei jedem Kandidaten auf Paket- oder Repository-Ebene:

  • Wie viele Module, Tests oder zukünftige Änderungen zahlen dafür? Ein Aufwand, der auf eine Funktion beschränkt ist, ist auf dieser Ebene eine Kleinigkeit.
  • Würde die Behebung ändern, wie neuer Code in diesem Repository geschrieben wird? Wenn die Behebung ein paar lokale Zeilen ohne Auswirkung auf Aufrufer sind, lassen Sie es weg.
  • Ist es ein Muster oder ein Einzelfall? Einzelne Instanzen zählen nur als Beleg für ein Muster.

Beispiele für große Probleme: ein externes System ohne besitzendes Modul, sodass jeder Aufrufer Auth und Paginierung neu macht; Richtlinie und Orchestrierung in den Einstiegspunkten verschmolzen, sodass Entscheidungen nur End-to-End getestet werden können; Zustandsbesitz auf Module aufgeteilt, die jeweils das Speicherlayout kennen; Clients und Konfiguration zur Importzeit erstellt, sodass nichts ohne die echte Umgebung getestet werden kann; eine Testsuite, die Interna durchgehend patcht, weil es keine Schnittstellen gibt. Eine lange Funktion, eine falsch benannte Variable, eine einzelne geschluckte Ausnahme oder eine schwache Assertion ist allein kein großes Problem.

Diese Probleme erstrecken sich über Module, erstellen Sie also eine Karte, bevor Sie Dateien im Detail lesen:

  • die Module (Dateien oder Pakete) und grob, was jedes tut, von git ls-files <path> und einem Überfliegen der Spitze jedes Moduls
  • wie die Hauptteile verbunden sind: was ruft was auf, und wie bewegen sich Zustand und Daten zwischen Einstiegspunkten, Modulen und externen Systemen
  • jedes externe System (API, Datenbank, Warteschlange, Dateiformat, Modell) und jedes Modul, das direkt damit spricht
  • jeden Ort, an dem Umgebung oder Konfiguration gelesen wird (os.environ, getenv, process.env, Flag-Parsing)
  • veränderlichen Zustand auf Modulebene und Importzeit-Effekte (Clients, Verbindungen, Caches, Sperren, die im Modulbereich erstellt werden)
  • die Einstiegspunkte und das Testverzeichnis mit welchen Modulen jede Testdatei übt

Grep reicht für das meiste davon aus. Halten Sie die Karte kurz; sie ist ein Arbeitsindex, kein Teil des Berichts.

Wenn der Umfang klein ist (grob unter 3.000 Zeilen Quellcode), überprüfen Sie ihn direkt von der Karte und starten Sie parallel zwei general-purpose Subagenten, jeder mit der Dateiliste und den Überprüfungsregeln aus Schritt 4 für seine Abschnitte. Einer erhält nur die Abschnitte Typen, Lesbarkeit und „Neigen Sie zu unveränderlichen Daten, wo es sich auszahlt“ der Bewertungsmatrix. Der andere erhält nur den Abschnitt Tests und muss die Assertionsprüfungen auf jeden Test anwenden. So erhalten diese Abschnitte volle Aufmerksamkeit, anstatt das, was nach den früheren übrig bleibt. Überprüfen Sie, was jeder zurückgibt, bevor Sie es behalten. Teilen Sie es andernfalls in Bereiche verwandter Module auf, jeweils mit ihren Tests, und geben Sie jeden Bereich einem general-purpose Subagenten, der parallel gestartet wird. Geben Sie jedem den Bewertungsmatrix-Pfad, den Vokabular-Pfad, die Karte, seine Dateiliste, die Überprüfungsregeln aus Schritt 4 und die Hürde für große Probleme oben, und sagen Sie ihm, nichts zu bearbeiten. Ein Subagent, der nur seinen eigenen Bereich sieht, driftet zu lokalen Kleinigkeiten ab, bitten Sie ihn also um die Designmuster, die er in seinem Bereich sieht, und die Belege für jedes (Datei:Zeile), nicht um eine Liste von Ergebnissen auf Zeilenebene. Module-übergreifende Probleme kommen von der Karte, arbeiten Sie diese also selbst aus, kombinieren Sie sie dann mit den Mustern der Subagenten, führen Sie diejenigen zusammen, die dieselbe zugrunde liegende Entscheidung aus verschiedenen Bereichen gesehen haben, und überprüfen Sie die Belege für jedes erneut, bevor Sie berichten.

4. Gegen jeden Abschnitt prüfen

Gehen Sie die Standards in Reihenfolge durch: Module, Zustand, Typen, Abhängigkeiten und Konfiguration, Fehler, Lesbarkeit, Tests. Überprüfen Sie jeden Kandidaten, bevor Sie ihn behalten:

  • Flaches Modul oder Durchgang: Wenden Sie den Löschtest an. Nennen Sie die Aufrufer und sagen Sie, welche Komplexität in ihnen wieder auftauchen würde, oder zeigen Sie, dass nichts passieren würde.
  • Abstraktion, die sich ihren Platz nicht verdient hat: Zählen Sie die Adapter an der Schnittstelle. Ein Test-Fake zählt. Ein Adapter mit nichts dahinter ist ein Ergebnis; zwei sind eine echte Schnittstelle.
  • Fehlende Abstraktion: Überprüfen Sie die entgegengesetzte Richtung genauso gründlich. Suchen Sie nach einem Anliegen, das inline an drei oder mehr Stellen behandelt wird, sowohl innerhalb eines Moduls als auch modulübergreifend.
  • Fehlender Besitzer / dupliziertes Anliegen: Listen Sie jeden Ort, an dem das Anliegen geschrieben ist (Datei:Zeile), nicht „dies erscheint an mehreren Stellen“.
  • Konzept ohne Besitzer: Listen Sie jeden Ort, an dem es dargestellt, geparst oder erstellt wird (Datei:Zeile), und jede Signatur, bei der gleich typisierte Parameter mit unterschiedlichen Bedeutungen nebeneinanderstehen. Identifikatoren zählen als Konzepte, nicht nur strukturierte Daten. Namen und IDs verschiedener Art, die als derselbe primitive Typ übergeben werden (ein Quell- und ein Ziel-Repository-Name, ein Branch-Name und ein Ref, zwei Arten von IDs), sind der Hauptfall, den es zu fangen gilt. Sagen Sie dann, welche Art von Besitzer passt. Wenn Aufrufer das Konzept halten und übergeben, empfehlen Sie einen Typ dafür. Wenn sie nur etwas damit tun müssen, empfehlen Sie, es innerhalb des Moduls zu verstecken, das die Arbeit erledigt. Standardmäßig kein Domain-Typ.
  • Ordnungsbeschränkungen oder handgebaute Schlüssel/Pfade/IDs: Zeigen Sie den Aufrufer, der die Sequenzierung oder Konstruktion durchführt.
  • Gemeinsam genutzter veränderlicher Zustand, Ladezeit-Effekte, tief gelesene Konfiguration: Nennen Sie die globale Variable oder den Importzeit-Aufruf und den Test oder die zweite Konfiguration, die es blockiert.
  • Snapshot-Schreibvorgänge: Zeigen Sie den Lesevorgang, den langlaufenden Schritt und den Rückschreibevorgang.
  • Veränderliche Daten, die besser unveränderlich wären: Melden Sie es nur, wenn die Veränderlichkeit konkrete Kosten hat. Zeigen Sie den zweiten Halter, der eine unerwartete Änderung sieht, den Cache oder Schlüssel, den es unsicher macht, oder die Änderung, die weit weg von dem Ort vorgenommen wird, an dem der Wert erstellt wurde. Eine veränderliche Struktur mit einem Besitzer, der sie durch seinen eigenen Code ändert, ist kein Ergebnis. Wenn die unveränderliche Version die Leistung kosten würde, sagen Sie, was memoisiert oder geteilt werden soll und wo dieser Cache lebt.
  • Darstellbarer ungültiger Zustand: Nennen Sie den Zustand, der niemals eintreten darf, und zeigen Sie den Typ, der ihn erlaubt (optionale Felder, die zusammen gesetzt sein müssen, Kombinationen von Booleschen Werten, ein String mit wenigen erlaubten Werten). Listen Sie die Wächter oder None-Prüfungen auf, die nur deshalb existieren (Datei:Zeile). Schlagen Sie die Form vor, die ihn unmöglich macht, und sagen Sie, welche Wächter diese Änderung löscht.
  • Dict oder Tupel als Konzept: Listen Sie die gelesenen Schlüssel und jede Funktion, die sie liest (Datei:Zeile), und jeden Ort, an dem das Dict erstellt wird. Schlagen Sie den Datensatztyp im vorhandenen Stil des Repositorys vor (ein Pydantic-Modell oder Dataclass, ein TypeScript-Interface, ein Go-Struct, was auch immer das Repository bereits verwendet), der nur die Felder enthält, die der Code verwendet, und sagen Sie, wo die Nutzlast hinein geparst wird.
  • Modul, das ein externes System besitzt: Überprüfen Sie, ob seine Funktionen eine Anmeldeinformation, Identität, Basis-URL oder einen Cache über Modul-Globals oder Umgebungslesevorgänge pro Aufruf teilen und ob Tests mehrere seiner Funktionen patchen. Wenn ja, empfehlen Sie eine Client-Klasse mit domänenbenannten Methoden, die beim Start erstellt und übergeben wird, und nennen Sie die Patches, die der Fake ersetzen würde.
  • Fehlende Dokumentationskommentare: Listen Sie jede nicht-triviale Funktion ohne einen auf (Datei:Zeile) und was ihr Dokumentationskommentar sagen müsste, was die Signatur nicht sagt (ein Fallback, ein Fehlermodus, ein Zustand, den sie berührt, eine Eingabeform). Gruppieren Sie sie in ein Lesbarkeitsergebnis pro Modul.
  • Einbuchstabige Namen: Melden Sie sie als ein gruppiertes Lesbarkeitsergebnis, das jeden auflistet (Datei:Zeile) mit einem vorgeschlagenen Namen. Sie zählen als ein Ergebnis zum Lesbarkeitslimit, nie als Grund, sie fallen zu lassen.
  • Geschluckte Fehler: Zeigen Sie den Pfad vom Fehler zu einem Ergebnis, das sich ändert, während nur eine Logzeile es aufzeichnet.
  • Name mit mehreren Bedeutungen: Durchsuchen Sie ihn und listen Sie auf, was er an jeder Stelle hält.
  • Name, der seine Ebene oder sein Objekt verbirgt: Zeigen Sie die Aufrufkette oder die Aufrufstellen, an denen er mehrdeutig gelesen wird, und schlagen Sie den Ersatz vor.
  • Funktion, die mehr als eine Sache tut: Versuchen Sie, ihre Ein-Satz-Zusammenfassung zu schreiben. Wenn Sie es nicht können, zitieren Sie den Zweig, den try-Block oder den Modusparameter, der Sie daran hindert.
  • Zu komplexe Funktion: Geben Sie für jeden Kandidaten aus der Komplexitätsmessung seinen Score an, listen Sie dann die Phasen auf, die er in Reihenfolge ausführt (Eingabe filtern, holen, beanspruchen, validieren, bauen, erstellen, aufzeichnen, benachrichtigen, ...) mit ihren Zeilenbereichen und der Fehlerregel jeder Phase. Schlagen Sie die Aufteilung als benannte Funktionen vor, eine pro Phase oder Entscheidung, mit Signaturen, und sagen Sie, was jedes extrahierte Stück testbar macht ohne Patchen; normalerweise werden die Entscheidungen zu reinen Funktionen und das Original liest sich als eine kurze Sequenz benannter Schritte. Ein Ergebnis pro Funktion. Über 20 rangiert es mit den Designerkenntnissen; 11 bis 20 ist ein Lesbarkeitsergebnis, das nicht auf das Lesbarkeitslimit angerechnet wird. Lassen Sie eine Aufteilung nicht fallen, weil die Funktion ein Einstiegspunkt ist oder weil das Repository größere hat.
  • Test-Assertions: Nennen Sie den Produktfehler, der die Assertion fehlschlagen lassen würde. Wenn Sie das nicht können, ist das das Ergebnis. Bei parametrisierten oder tabellengesteuerten Fällen verfolgen Sie jede Eingabe durch den Code und sagen Sie, welcher Teil davon das Verhalten erreicht, nach dem der Fall benannt ist. Ein Fall, dessen unterscheidende Eingabe von einem früheren Zweig verbraucht wird, deckt dieses Verhalten nicht ab, selbst wenn ein Test dafür existiert. Überprüfen Sie ebenso, dass der Fixture oder Fake tatsächlich die Eingabe produzieren kann, die jeden Wächter oder Verweigerungspfad auslösen würde. Wenn nie, ist der Wächter ungetestet.
  • Test-Doubles: Sagen Sie, worum es im Test geht, dann ob der Double außerhalb dieser Grenze sitzt oder Produktlogik reimplementiert.
  • Tests, die Interna patchen: Zeigen Sie auf die Entscheidung, die herausgezogen werden sollte, oder die Abhängigkeit, die übergeben werden sollte, da dies die eigentliche Behebung ist.
  • Vorgeschlagene Schnittstelle oder Port in der Behebung eines Ergebnisses: Geben Sie ihm Operationen, die in der Domäne benannt sind (close_ticket(id)), nicht Transportverben (get/post/put). Ein Port, der nur Anfragen weiterleitet, fällt beim Löschtest durch, und sein Fake müsste das Routing reimplementieren. Überprüfen Sie jede vorgeschlagene Schnittstelle gegen den Löschtest, bevor Sie sie melden.

Geben Sie Tests die gleiche Tiefe wie die Abschnitte davor, selbst wenn die früheren Abschnitte viele Ergebnisse liefern. Führen Sie jede Testprüfung oben gegen jede Testdatei aus: Nennen Sie für jede Assertion den Produktfehler, der sie fehlschlagen lassen würde. Ein sicherheitsrelevantes Verhalten ohne fehlschlagende Assertion (Schwärzung, eine Auth-Prüfung, eine Genehmigungshürde) rangiert mit den Designerkenntnissen.

Lassen Sie alles fallen, was Sie nicht konkretisieren können. Lassen Sie Stil-Kleinigkeiten fallen, die die Standards nicht abdecken. Melden Sie hier keine Korrektheitsfehler, es sei denn, sie folgen direkt aus einem Qualitätsproblem (z. B. ein Snapshot-Schreibvorgang, der Daten verliert); erwähnen Sie sie in einer Zeile und verweisen Sie auf /code-review (oder den entsprechenden Befehl des Agents).

Verwandte Skills