Die letzte Lektion hat Ihnen beigebracht, einem Agenten Aufträge zu geben und seine Befehle zu prüfen. Diese Lektion behandelt drei Dinge, die zusammengehören: Sie sagen Copilot einmal im Repository, wie bei Ihnen gearbeitet wird (Anweisungsdateien). Sie lassen Pull Requests auch von Copilot lesen, ohne sich auf ihn zu verlassen (Code-Review). Und Sie lassen Tests erzeugen und beweisen, dass sie etwas prüfen. Der rote Faden: Erzeugter Code ist fremder Code, der schnell kommt. Er braucht dieselbe Prüfung wie der eines Kollegen, nur öfter.
Der Kurs setzt W3.1 und W3.2.1 voraus, dazu aus K2 die Lektion „Reviews, die weiterhelfen“, die Tests mit xUnit (Lektion „Unit-Tests für Regeln und Endpunkte“) und die
Regel für überschneidende Termine der Kladde. Die Regel steht in TimeRange aus K1 und ist eine einzige Zeile:
public bool Overlaps(TimeRange other) => Start < other.End && other.Start < End;
Zwei Zeiträume überschneiden sich, wenn jeder beginnt, bevor der andere endet. Ein Termin bis 10:00 und einer ab 10:00 berühren sich nur. Wer einen Termin so
anlegt, bekommt keine Fehlermeldung. Wer sich überschneidet, bekommt appointment.time.overlaps und den Status 409 (K2). An dieser Zeile üben Sie in der
zweiten Übung.
Wie in der letzten Lektion gilt: Kein Autor hat die Übungen mit Copilot im Editor durchgespielt, jede Oberfläche ist gegen die Dokumentation gelesen. Code, den Copilot in dieser Lektion „erzeugt“, ist ein Beispiel für erzeugten Code, nicht die Ausgabe eines Laufs: Es ist von Hand geschrieben und enthält absichtlich Fehler. Was Ihr Copilot erzeugt, sieht anders aus, und eben deshalb prüfen Sie es.
Anweisungsdateien
Ohne Anweisungen kennt Copilot Ihre Regeln nur, soweit der Kontext sie zeigt (W3.1.2). Eine Anweisungsdatei ist Kontext, der bei jeder Anfrage mitgeht: Wie bauen und testen wir, welche Namen gelten, was ist verboten. Nach der Dokumentation von GitHub („Adding repository custom instructions“) gibt es drei Formen.
| Datei | Gilt für | Besonderheit |
|---|---|---|
.github/copilot-instructions.md |
das ganze Repository | Markdown, ein Dokument für alles |
.github/instructions/NAME.instructions.md |
die Dateien, die der Kopfeintrag applyTo nennt |
applyTo ist ein Glob-Muster, mehrere mit Komma; excludeAgent nimmt "code-review" oder "cloud-agent" |
AGENTS.md |
der Ordner, in dem sie liegt, und darunter | die nächste Datei im Verzeichnisbaum gilt |
Weitere Punkte, so wie die Dokumentation sie nennt:
- Rangfolge: persönliche Anweisungen vor Anweisungen des Repositorys vor Anweisungen der Organisation. Alle werden gesendet; die Rangfolge entscheidet, wessen Wort bei einem Widerspruch zählt, sie schaltet die anderen nicht ab. Widersprechen sich zwei, ist das Ergebnis nicht verlässlich: Vermeiden Sie Widersprüche, statt auf die Rangfolge zu bauen.
- Im Chat gelten sie, sobald die Datei gespeichert ist.
- Das Code-Review liest sie vom Kopf-Branch des Pull Requests, also von dem Branch mit den Änderungen. Wer die Anweisungen im selben Pull Request ändert, ändert damit das Review dieses Pull Requests.
- Die pfadbezogenen Dateien gelten auf github.com nur für den Cloud-Agenten und das Code-Review.
Was die gelesenen Seiten nicht sagen, nennt dieser Kurs offen: Eine Größengrenze der Dateien stand dort nicht. Und Prompt-Dateien (wiederverwendbare Prompts in einer Datei im Repository) behandelt der Kurs nicht im Einzelnen; ob und wie Ihr Editor sie unterstützt, steht in seiner Dokumentation.
Was in eine Anweisungsdatei gehört
Eine Anweisungsdatei ist keine Rede an das Modell, sondern ein kurzes Regelwerk. Es hilft, wenn jede Zeile konkret und prüfbar ist.
| Gut | Schlecht |
|---|---|
„Testmethoden heißen PascalCase ohne Unterstrich, Beispiel ATimeThatOverlapsIsRefused.“ |
„Schreibe sauberen Code.“ |
„Tests starten mit dotnet test --project tests/Kladde.Core.Tests.“ |
„Teste gründlich.“ |
| „Zeiten sind halboffen: Ende ist nicht Teil des Zeitraums. Ein Ende um 10:00 überschneidet sich nicht mit einem Beginn um 10:00.“ | „Achte auf Zeitzonen.“ |
„Fehler kommen als Code wie appointment.time.overlaps mit dem Status, der in K2 festgelegt ist, nie als freier Text.“ |
„Behandle Fehler richtig.“ |
| „Zugangsdaten stehen nie im Code oder in Tests.“ | „Sei sicher.“ |
Und was nicht hineingehört: Geheimnisse (die Datei liegt im Repository und geht an das Modell), Anweisungen, die ein Werkzeug schon erzwingt (Formatierung übernimmt der Formatierer), und Wünsche, die Sie nicht prüfen können. Eine Anweisungsdatei ist ein Dokument des Teams: Sie ändern sie per Pull Request, und jemand liest sie.
Eine Anweisungsdatei für die Kladde, von Hand geschrieben und als Ausgangspunkt für die Übung gedacht (nicht von Copilot erzeugt):
# Kladde: instructions for GitHub Copilot
- Code and comments are English. Texts shown to people are German or English from the resource files.
- Build and test: `dotnet test --project tests/Kladde.Core.Tests`. Say which project you ran.
- Time ranges are half-open: `Overlaps` is `Start < other.End && other.Start < End`. Touching ranges do not overlap.
- Business errors use codes like `appointment.time.overlaps`, never free text.
- Tests: xUnit, method names in PascalCase without underscores, one behaviour per test.
- Tests never read the clock: pass the time in (`TimeProvider` or a parameter), never `DateTime.Now`.
- Never put keys, passwords or connection strings in code, tests or examples.
- Commit messages follow Conventional Commits.
Dazu eine pfadbezogene Datei nur für Tests, .github/instructions/tests.instructions.md:
---
applyTo: "tests/**/*.cs"
---
- Every test states the rule it protects in its name.
- Check the boundary on both sides: exactly on it, just before, just after.
- An assertion must be able to fail: never compare a result with a copy of the code under test.
Ob das Muster in applyTo genau so geschrieben wird, wie Sie es für Ihre Ordner brauchen, entnehmen Sie der Dokumentation: Das Beispiel ist ein Entwurf, nicht gegen Copilot
ausgeführt.
Prüfen, ob die Datei wirkt
Ob Copilot eine Anweisung befolgt, ist keine Garantie, sondern eine Wahrscheinlichkeit. Prüfen Sie es mit zwei Aufgaben: Eine, bei der die Regel gelten muss („Schreibe einen Test für
Overlaps“, die Datei verlangt Grenzfälle und keine Uhr), und eine Gegenprobe ohne die Datei. Zeigt sich kein Unterschied, ist die Anweisung zu vage oder wird nicht
geladen. Prüfen Sie dann, ob die Datei gespeichert ist, ob sie am richtigen Ort liegt und ob der Editor sie einbindet. Lesen Sie in der Antwort nach, welche Dateien als Quelle
genannt sind, wenn Ihr Editor das anzeigt.