Alle Skills

tdd (Matt Pocock)

Entwickelt Features und behebt Bugs testgetrieben mit Red-Green-Refactor und Integrationstests.

mattpocock tdd: Kein Lift, wenn der Prompt bereits test-first verlangt, und etwa 1.7x die Tokens

SituativSicher

Codex CLI · gpt-6-astra

22.7 / 30

Lift gegenüber ohne Skill: +0.00 · Situativ · 18 Läufe

Situativ: der Lift +0.00 liegt unter +1.0. Für „Empfohlen“ sind insgesamt 22/30, eine Ausgabequalität von 3.5 und ein Lift von +1.0 nötig.

SOTA

Bestanden

Getestet mit Codex.

Gilt für Codex, Claude Code

Codex CLI 0.166 (SOTA-Stufe): 18 bewertete Läufe. Ein Bestehen hier deckt gemäß unserer Stufenregel auch Claude Code ab; über die zweite Stufe sagt es nichts aus.

Punktzahlen

Jede Dimension reicht von 0 bis 5, und die sechs ergeben zusammen die Gesamtpunktzahl von 30. 5 ist in jeder Dimension besser. Kosten 5 bedeutet günstig und schnell. Installation 5 bedeutet einfach.

Trigger-Zuverlässigkeit
5.0
Lift gegenüber ohne Skill
2.0
Ausgabequalität
4.7
Token- und Zeitkosten
2.0
Installation und Portabilität
4.0
Sicherheit
5.0

Sicherheitsprüfung

Sicher

Statischer Scan: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Manuelle Prüfung: Sicher in einer Sandbox ohne Netzwerk auszuführen (keine Befunde). Ein sauberer Scan beweist nicht, dass ein Skill sicher ist.

Installieren

npx skills@latest add mattpocock/skills --skill tdd

Quelle

Fixierter Commit: 4ae2317ddb22b046e26455e4f9c9b3aaaf62212d

Getestet: 2026-11-02

Was wir getestet haben

  • Eine Funktion nach einer präzisen Spezifikation implementieren — slugify(text, max_length=None) in slug.py (Python 3, nur Standardbibliothek) mit TDD implementieren. Spezifikation: Text kleinschreiben; jede Folge von Zeichen, die keine ASCII-Buchstaben oder -Ziffern sind, durch ein einzelnes '-' ersetzen; führende und abschließende '-' entfernen; ein leeres Ergebnis…
  • Eine kleine zustandsbehaftete Klasse implementieren — ratelimiter.py schreiben (Python 3, nur Standardbibliothek) test-first (red-green-refactor) mit class RateLimiter(limit, window_seconds, clock=time.monotonic): ein Sliding-Window-Limiter pro Schlüssel. allow(key) gibt True zurück und zeichnet den Aufruf auf, wenn weniger als limit…
  • Einen Rundungsfehler beheben — Kunden sagen, cart_total in cart.py sei manchmal einen Cent daneben im Vergleich zu unserem Buchhaltungssystem, das bei jedem Schritt kaufmännisch auf den Cent rundet (jede Zeilensumme, die rabattierte Zwischensumme und die Steuer). Beispiel: cart_total([(1.005, 1)]) sollte 1.09 zurückgeben und…

Vorteile

  • Der Skill wurde erkannt, ohne genannt zu werden: Skill-Datei in 6/6 Treatment-Läufen gelesen.
  • Hohe absolute Qualität mit dem Skill: 4.67 von 5.

Nachteile

  • Kein messbarer Lift gegenüber ohne Skill (+0.00, im Rauschen).
  • Ein Ein-Satz-Prompt erzielte 4.67 gegenüber 4.67 mit dem Skill (+0.00).
  • Verbraucht 1.7x die Tokens von ohne Skill.
  • Testhinweis: Der Ein-Satz-Arm (6 Läufe) wurde später auf einem anderen Rechner als Kontroll- und Treatment-Arm ergänzt.
  • n=2 pro Aufgabe und Variante; Unterschiede unter etwa 1 Punkt sind Rauschen.

Bewertung

Codex CLI 0.166 (gpt-6-astra, niedriges Reasoning) auf einem Mac-Testrechner, einem frischen temporären Projekt und temporären HOME/TMPDIR/Caches pro Lauf; Skill installiert (Treatment) oder nicht vorhanden (Kontrolle) oder nicht vorhanden mit der Kernanforderung des Skills in einem an den Prompt angehängten Satz (One-Liner-Gruppe); 2 Läufe pro Gruppe und Aufgabe; Netzwerk aus; Schreiben nach /tmp blockiert. Die Prompts nennen den Skill nie (außer der unten genannten Formulierung). Da die Beschreibung dieses Skills nur auslöst, wenn nach TDD / test-first gefragt wird, sagen die Prompts das („using TDD“, „test-first (red-green-refactor)“, „Do it test-first“). Dieselben Worte erhält die Kontrollgruppe, der Test prüft also, ob der Skill eine einfache TDD-Anfrage verbessert.

Drei-Arm-Vergleich

VarianteDurchschnittsnote (0-5)Tokens pro Lauf
Ohne Skill4.6786k
Ein-Satz-Prompt4.67178k
Mit Skill4.67146k

Gemessen mit Codex CLI über 18 Läufe, bewertet durch regelbasierte Prüfungen ohne LLM-Richter. Gesamt 22.7 / 30, Urteil Situativ.

Offenlegung: Der Ein-Satz-Arm (6 Läufe) wurde später auf einem anderen Rechner als Kontroll- und Treatment-Arm ergänzt.

Urteil: Situativ (22.7 / 30). Quelle: mattpocock/skills, skills/engineering/tdd, gepinnt auf Commit 4ae2317. Installation: npx skills@latest add mattpocock/skills --skill tdd. Lizenz: MIT (Repo-LICENSE).

Was es ist

Der Skill tdd aus Matt Pococks Skills-Repo (engineering/tdd): der Red-Green-Zyklus plus zwei Referenzdateien dazu, was ein guter Test ist und wann man mockt. Etwa 570 Wörter in SKILL.md; reines Markdown, keine Skripte. Er triggert, wenn der Nutzer testgetriebenes Arbeiten möchte.

So haben wir getestet

Codex CLI 0.166 (gpt-6-astra, low reasoning) auf einem Mac-Testgerät, pro Lauf ein frisches temporäres Projekt und temporäre HOME/TMPDIR/Caches, Skill installiert (Mit-Skill-Gruppe) oder nicht vorhanden (Kontrollgruppe) oder nicht vorhanden, aber mit der Kernanforderung des Skills als einem an den Prompt angehängten Satz (Ein-Satz-Gruppe), 2 Läufe pro Gruppe und Aufgabe, Netzwerk aus, Schreibzugriffe auf /tmp blockiert. Die Prompts nennen den Skill nie (außer der unten genannten Formulierung).

Da die Beschreibung dieses Skills nur triggert, wenn der Nutzer TDD / test-first verlangt, sagen die Prompts das auch („using TDD“, „test-first (red-green-refactor)“, „Do it test-first“). Dieselben Worte erhält die Kontrollgruppe, der Test prüft also, ob der Skill eine schlichte TDD-Anfrage verbessert.

  1. Eine Funktion nach präziser Spezifikation implementieren — Implementiere slugify(text, max_length=None) in slug.py (Python 3, nur Standardbibliothek) mit TDD. Spezifikation: Text in Kleinbuchstaben umwandeln; jede Folge von Zeichen, die keine ASCII-Buchstaben oder -Ziffern sind, durch ein einzelnes '-' ersetzen; führende und abschließende '-' entfernen; ein leeres Ergebnis…
  2. Eine kleine zustandsbehaftete Klasse implementieren — Schreibe ratelimiter.py (Python 3, nur Standardbibliothek) test-first (red-green-refactor) mit der Klasse RateLimiter(limit, window_seconds, clock=time.monotonic): ein Sliding-Window-Limiter pro Schlüssel. allow(key) gibt True zurück und zeichnet den Aufruf auf, wenn weniger als limit…
  3. Einen Rundungsfehler beheben — Kunden sagen, cart_total in cart.py liege manchmal um einen Cent neben unserem Buchhaltungssystem, das bei jedem Schritt kaufmännisch auf den Cent rundet (jede Zeilensumme, die rabattierte Zwischensumme und die Steuer). Beispielsweise sollte cart_total([(1.005, 1)]) 1.09 zurückgeben und…

Die Bewertung erfolgt programmatisch (versteckte Tests / Trefferquote bei eingebauten Problemen / Constraint-Prüfungen / Rendern+OCR, wo relevant), 0–5 pro Lauf. Kein LLM-Richter hat eine Punktzahl entschieden.

Ergebnisse

Der Ein-Satz-Prompt für die dritte Gruppe: "Arbeite test-first in vertikalen Scheiben: Schreibe einen fehlschlagenden Test über die öffentliche Schnittstelle, bestätige, dass er fehlschlägt, schreibe den minimalen Code zum Bestehen, wiederhole das Ganze und refaktoriere erst, wenn alles grün ist; schreibe nicht alle Tests im Voraus."

AufgabePunktzahl KontrolleEin-SatzMit SkillToken KontrolleToken Ein-SatzToken mit SkillSkill gelesen
t1-slugify5.05.05.079k184k135k2/2
t2-ratelimiter5.05.05.099k183k169k2/2
t3-cart-bugfix4.04.04.079k164k133k2/2

Durchschnitt: 4.67 ohne vs. 4.67 mit Skill (Delta +0.0). Token pro Lauf: 86k vs. 146k (1.70x); Zeit 50s vs. 67s. Ein-Satz-Gruppe: 4.67 (Zuwachs des Skills gegenüber dem Ein-Satz-Prompt: +0.0; Zuwachs des Ein-Satz-Prompts gegenüber ohne Skill: +0.0); Token des Ein-Satz-Prompts 178k pro Lauf, der Skill kostet also 0.82x so viel wie der Ein-Satz-Prompt.

Was dabei herauskam

  • Da der Prompt bereits test-first verlangte, tat die Kontrollgruppe es ebenfalls: Bei den beiden Bauaufgaben bestanden alle Läufe beider Gruppen alle Prüfungen, einschließlich „Test vor der Implementierung geschrieben“. Der Skill fügte dort nichts Messbares hinzu.
  • Bei der Bugfix-Aufgabe (Cart-Rundung) behoben alle vier Läufe mit und ohne Skill den Fehler und bestanden die versteckten Tests, und alle vier scheiterten an derselben Prozessprüfung: Fix oder Test kamen im selben Schritt wie das jeweils andere, statt zuerst ein fehlschlagender Test. Der Skill änderte daran nichts.
  • Der Skill wurde in 6/6 Mit-Skill-Läufen gelesen. Er ließ den Agenten viel mehr Arbeit erledigen (24–26 Befehle statt 8–10 bei den Bauaufgaben) für dasselbe Ergebnis: etwa 1.7x Token.
  • Die Korrektheit bei den versteckten Tests lag in beiden Gruppen bei 100%.
  • Ein-Satz-Version (test-first in vertikalen Scheiben, ein fehlschlagender Test nach dem anderen): Durchschnitt 4.67, identisch mit Kontrolle und Skill, bei 178k Token pro Lauf gegenüber 86k für die Kontrolle (2.1x) und 146k für den Skill. Die Ein-Satz-Agenten führten im Schnitt 27 Befehle pro Lauf aus gegenüber 9 bei der Kontrolle und 23 beim Skill, weil sie die Testschleife wiederholt durchliefen.
  • Jede Gruppe schrieb in allen Läufen ihre eigenen Tests und bestand alle versteckten Tests; Tests vor der Implementierung wurden in allen drei Gruppen in 4 von 6 Läufen erfüllt, die Anfrage „test first“ auf Prompt-Ebene leistete also bereits, wofür der Skill gedacht ist.

Bewertung nach Dimensionen

DimensionPunktzahlBegründung
1_output_quality4.67

Durchschnitt 4.67/5 mit Skill (programmatische Prüfungen, siehe Tabelle pro Aufgabe).

2_lift_vs_no_skill2.0

+0.00 Punkte gegenüber 4.67 ohne Skill (n=2 pro Aufgabe; unter etwa 1 Punkt ist Rauschen).

3_trigger5.0Skill-Datei in 6/6 Mit-Skill-Läufen gelesen.
4_instructions_portability4
5_efficiency21.70x Token (146k vs. 86k pro Lauf) und 1.34x Zeit (67s vs. 50s).
6_safety_hygiene5

Grenzen dieses Tests

  • Jeder Test-Prompt verlangte selbst TDD, was der Kontrollgruppe den Großteil des Nutzens gibt; ein Nutzer, der das nicht verlangt, würde gar kein Triggern der Skill-Beschreibung sehen.
  • Nur kleine Python-Aufgaben; die Testqualität wurde nicht bewertet.
  • n = 2 pro Gruppe und Aufgabe: Unterschiede unter etwa 1 Punkt sind Rauschen.
  • Regelbasierte Bewertung misst nur, was die Prüfungen sehen können; Geschmack oder ob ein Ergebnis das bestmögliche ist, lässt sich so nicht beurteilen.

Sicherheit

Siehe security.md. Scan: 0 CRITICAL / 0 HIGH / 0 MEDIUM. Urteil: sicher ausführbar (Sandbox ohne Netzwerk). Ein sauberer Scan beweist nicht, dass ein Skill sicher ist.

Fazit

Auf eine test-first-Anfrage hin erzielt dieser Skill bei kleinen Aufgaben keinen Zusatznutzen: Kontrolle, Ein-Satz-Version und Skill erreichten alle 4.67, während der Skill 1.7x und der Satz 2.1x die Token der Kontrolle verbrauchten. Er kann helfen, Tests über eine längere Sitzung hinweg verhaltensorientiert zu halten, was wir nicht gemessen haben.

Transkript

Laufprotokoll: tdd (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.)
Spalten: Aufgabe, Gruppe-Lauf, Punktzahl (0-5), Tokens, Sekunden, bestandene Prüfungen, vom Agenten geöffnete Skill-Dateien.

t1-slugify control-1: Punkte 5.0, Tokens 78904, Sek. 50.3, Prüfungen 3/3, nichts geöffnet
t1-slugify control-2: Punkte 5.0, Tokens 79205, Sek. 47.1, Prüfungen 3/3, nichts geöffnet
t1-slugify oneliner-1: Punkte 5.0, Tokens 199600, Sek. 74.7, Prüfungen 3/3, nichts geöffnet
t1-slugify oneliner-2: Punkte 5.0, Tokens 168650, Sek. 68.2, Prüfungen 3/3, nichts geöffnet
t1-slugify treatment-1: Punkte 5.0, Tokens 144538, Sek. 57.6, Prüfungen 3/3, geöffnet tdd
t1-slugify treatment-2: Punkte 5.0, Tokens 126047, Sek. 50.7, Prüfungen 3/3, geöffnet tdd
t2-ratelimiter control-1: Punkte 5.0, Tokens 99439, Sek. 60.2, Prüfungen 3/3, nichts geöffnet
t2-ratelimiter control-2: Punkte 5.0, Tokens 99611, Sek. 54.3, Prüfungen 3/3, nichts geöffnet
t2-ratelimiter oneliner-1: Punkte 5.0, Tokens 159969, Sek. 70.9, Prüfungen 3/3, nichts geöffnet

18 Läufe, 3 Artefakte

Beispielausgabe

SOTA · With the skill: test_slug.py (t1-slugify, run 1, Codex)

import unittest from slug import slugify class SlugifyTests(unittest.TestCase): def test_hard_cuts_first_word_when_it_exceeds_limit(self): self.assertEqual(slugify('Supercalifragilistic', 5), 'super') def test_truncates_at_word_boundary(self): self.assertEqual(slugify('Hello, World!', 8), 'hello') def test_normalizes_text(self): self.assertEqual(slugify('Hello, World!'), 'hello-world') def test_preserves_only_ascii_letters_and_digits(self): self.assertEqual(slugify(' -- CAFÉ_42\t中文 / Test!! '), 'caf-42-test') def test_lowercases_before_filtering(self): self.assertEqual(slugify('\u212aELVIN'), 'kelvin') def test_keeps_slug_that_fits_limit(self): for limit in (11, 20, None): with self.subTest(limit=limit): self.assertEqual(slugify('Hello, World!', limit), 'hello-world') def test_keeps_complete_words_without_trailing_separator(self): for limit, expected in ((3, 'one'), (4, 'one'), (6, 'one'), (7, 'one-two'), (8, 'one-two')): with self.subTest(limit=limit): self.assertEqual(slugify('one two three', limit), expected) def test_hard_cuts_long_first_word_even_with_later_words(self): self.assertEqual(slugify('Supercalifragilistic hello', 5), 'super') def test_applies_limit_to_fallback(self): self.assertEqual(slugify('', 2), 'n') def test_empty_normalized_text_has_fallback(self): for text in ('', ' !!! ', '中文'): with self.subTest(text=text): self.assertEqual(slugify(text), 'n-a') if __name__ == '__main__': unittest.main()

Pro ansehen