Perpetuum mobile: Wie Copilot Copilot startet, um ganze Roadmaps abzuarbeiten

Ich bin als diplomierter Informatiker vor allem eins: faul.

Das klingt jetzt vielleicht erstmal nicht nach dem Satz, mit dem man in ein Bewerbungsgespräch gehen sollte, aber ich halte das im technischen Kontext für eine ganz hervorragende Eigenschaft. Nicht diese “ich lasse alles liegen und hoffe, dass jemand anders den Müll rausbringt”-Faulheit. Eher diese andere. Die nützliche. Die, bei der man sich denkt: Wenn ich das dreimal machen muss, kann ich auch gleich zwei Stunden investieren, damit ich es nie wieder machen muss.

Nun.

Ganz so einfach ist es natürlich nie.

Ich mag es nämlich nicht nur bequem, ich mag auch, wenn Dinge gut laufen. Und das ist eine ungünstige Kombination, weil “gut laufen” meistens bedeutet, dass man sich vorher ein paar Gedanken machen muss. Man kann Dinge natürlich auch einfach irgendwie zusammenklicken, bis sie zufällig funktionieren, aber dann hat man später diese schöne Situation, in der man um 23:47 Uhr auf ein Dashboard starrt und flüstert: “Warum bist Du so?”

Programmieren konnte ich dabei nie besonders gut. Jedenfalls nicht in dem Sinne, in dem Menschen programmieren können, die am Wochenende aus Versehen einen Compiler schreiben, weil ihnen beim Kaffee langweilig war. Ich war immer eher der Typ: Ich weiß ziemlich genau, wie die Software sich verhalten sollte, ich weiß auch, warum die vorhandene Software das natürlich wieder nicht tut, und ich habe dann eine sehr ausgeprägte Meinung dazu, wie eine kleine Individualsoftware aussehen müsste, die das Problem elegant aus der Welt schafft.

Das Problem daran: Irgendwer muss diese Individualsoftware dann bauen.

Früher war dieser Irgendwer oft ich. Mit unterschiedlichem Erfolg. Es gab funktionierende Dinge, es gab Dinge, die eher Charakter hatten, und es gab Dinge, die man nachträglich nur mit “war halt 2004” entschuldigen kann.

Heute gibt es Copilot, Codex und die ganze Familie der fleißigen Textwahrscheinlichkeitsmaschinen. Und damit entsteht eine interessante neue Form der Faulheit: Man schreibt nicht mehr zwingend jeden Code selbst, sondern man beschreibt ziemlich genau, was als nächstes passieren soll, lässt einen Agenten loslaufen, schaut sich das Ergebnis an, meckert bei Bedarf und merged, wenn es tut.

Neudeutsch heißt das dann gerne Vibe Coding. Man hat eine Idee, redet ein bisschen mit ChatGPT darüber, bekommt eine Roadmap, lässt sich Issues daraus schneiden und fühlt sich für ungefähr sieben Minuten wie ein sehr effizienter Produktmanager mit eigenem Maschinenraum.

Das ist auch gar nicht falsch. Es ist sogar ziemlich gut.

Nur kommt danach der langweilige Teil.

Denn wenn die Roadmap einmal da ist, liegen da plötzlich zwanzig, dreißig oder fünfzig Issues herum. Alle sehen irgendwie sinnvoll aus. Viele davon stammen ohnehin aus demselben ChatGPT-Gespräch. Und jetzt soll ich als Mensch ernsthaft stundenlang Tickets sortieren, Copilot zuweisen, warten, gucken, nächstes Ticket suchen, wieder zuweisen, wieder warten?

Das ist natürlich Quatsch.

Also macht man, was man als fauler Informatiker macht: Man automatisiert den langweiligen Teil.

So weit, so nett. Aber nach dem ersten erfolgreichen Copilot-PR kommt natürlich sofort die nächste Frage:

Warum muss ich eigentlich den nächsten Copilot-Lauf wieder selbst anschubsen?

Und direkt danach kommt die zweite Frage, die meistens etwas mehr nach verbranntem Toast riecht:

Warum habe ich eigentlich gerade acht Copilot-PRs gleichzeitig, die alle dieselbe Datei anfassen?

Und damit sind wir beim Perpetuum mobile.

Die Idee

Ein echtes Perpetuum mobile funktioniert nicht. Thermodynamik, Physikunterricht, sehr traurige Bastler mit Magneträdern, ihr kennt das.

Ein Repository kann aber so tun als ob.

Die Idee ist simpel: Wenn ein Projekt eine halbwegs vernünftige Roadmap hat, dann kann man diese Roadmap in Issues schneiden. Und wenn diese Issues gut genug beschrieben sind, dann kann Copilot sie nacheinander abarbeiten. Und wenn ein Issue fertig ist, kann ein Workflow das nächste Issue aktivieren. Und wenn das fertig ist, das nächste. Und so weiter, bis entweder die Roadmap leer ist oder die Realität wieder eine Produktentscheidung verlangt.

Das ist kein “KI übernimmt jetzt alles”-Zauber. Das ist eher ein Förderband. Man legt vorne sinnvoll portionierte Arbeit drauf, und hinten kommen Pull Requests raus. Manchmal gute. Manchmal welche, bei denen man dem Agenten freundlich erklärt, dass “funktioniert bei mir” kein Testkonzept ist.

Der entscheidende Punkt ist dabei das nacheinander.

Copilot kann parallel arbeiten. GitHub kann parallel Issues zuweisen. Moderne Agenten können mit beeindruckender Geschwindigkeit beeindruckend viele Branches erzeugen. Das klingt erstmal nach Produktivität, ist aber bei echten Projekten sehr schnell nur eine andere Schreibweise für Merge-Konflikte.

Issue 4 ändert die API. Issue 5 baut schon gegen die alte API. Issue 6 räumt nebenbei Komponenten auf. Issue 7 hat dieselbe Datei “nur kurz” formatiert. Und dann sitzt man da, betrachtet vier Pull Requests, die einzeln plausibel sind, zusammen aber aussehen wie ein Auffahrunfall auf der A3 bei Regen.

Genau diesen Unsinn will ich nicht.

Ich will nicht keine Kontrolle. Ich will nur nicht die Art Kontrolle, bei der ich den ganzen Tag Tickets von links nach rechts schiebe, obwohl die Reihenfolge vorher schon in der Roadmap steht.

Die Zutaten

Man braucht dafür erstaunlich wenig:

  • eine Roadmap, die nicht nur aus Wunschdenken und Nebel besteht,
  • GitHub Issues mit klaren Akzeptanzkriterien,
  • ein paar Labels,
  • einen Sequencer, der das nächste Issue aktiviert,
  • und optional einen Automerge-Workflow, der nur dann merged, wenn die Welt nicht brennt.

Die Labels sind dabei die eigentliche Fernbedienung:

copilot:queued   liegt bereit und darf irgendwann drankommen
copilot:active   ist gerade an der Reihe
agentic-ready    ist klein genug und ordentlich beschrieben
blocked          bitte nicht anfassen, hier fehlt noch Hirn
priority:high    kommt weiter nach vorne

Das Schöne daran ist, dass es nicht besonders schlau ist. Und das meine ich positiv. Sobald Automatisierung zu schlau sein möchte, entwickelt sie gerne eine Persönlichkeit, die ich in Produktionssystemen nicht haben will.

Der Sequencer muss nicht “verstehen”, was Produktstrategie ist. Er muss nur respektieren, dass Issue 12 vor Issue 13 kommt, dass blocked wirklich blocked heißt und dass immer nur ein Copilot-Ticket aktiv sein soll. Das ist ungefähr die Menge an Intelligenz, die ich in diesem Teil des Systems haben möchte.

Das wichtigste Teil: gute Issues

Der Trick ist nicht der Workflow. Der Trick ist das Issue.

Ein schlechtes Issue sagt:

Mach mal Login besser.

Das ist kein Issue. Das ist ein Hilferuf.

Ein brauchbares Issue sagt eher:

## Ziel
Die Setup-Seite zeigt fehlende Mailbox-Recovery-Konfigurationen an.

## Akzeptanzkriterien
- Fehlende Werte erscheinen als Warnung.
- Die Warnung nennt den konkreten nächsten Schritt.
- Der Health-Endpoint liefert dieselbe Information maschinenlesbar.
- Tests decken fehlende und vorhandene Konfiguration ab.

## Nicht-Ziele
- Keine neue Provider-Integration.
- Keine Änderung an bestehenden Secrets.

Damit kann ein Agent arbeiten. Da steht drin, was passieren soll, woran man erkennt, dass es fertig ist, und wo er bitte seine Finger rauslassen soll. Letzteres ist wichtig, weil Agenten sonst manchmal den Ehrgeiz eines Praktikanten am dritten Tag entwickeln: “Ich habe nebenbei noch das Auth-System refactored.”

Danke. Nein.

Der Sequencer

Der Sequencer ist ein kleines Script, das regelmäßig schaut, ob gerade ein Issue aktiv ist. Falls nein, sucht es das nächste offene, nicht blockierte Issue mit copilot:queued und macht daraus copilot:active.

Praktisch bedeutet das: Ich kann eine von ChatGPT vorbereitete Roadmap nehmen, daraus GitHub Issues erzeugen, die Issues einmal sauber priorisieren und dann dem Repository sagen: Hier, arbeite das bitte der Reihe nach ab. Nicht alles auf einmal. Nicht “mal schauen, was passiert”. Sondern schön eins nach dem anderen, wie bei Menschen, nur ohne Stand-up.

Das kann man sehr schlicht per GitHub Actions laufen lassen:

name: Copilot Issue Sequencer

on:
  schedule:
    - cron: "17 * * * *"
  workflow_dispatch:

jobs:
  activate-next:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
      - run: node scripts/copilot-issue-sequencer.mjs

Warum nicht alles gleichzeitig aktivieren?

Weil das dann keine Automation ist, sondern Konfetti mit Schreibrechten.

Ein aktives Issue nach dem anderen ist langweilig, aber langweilig ist bei Infrastruktur eine unterschätzte Tugend.

Natürlich ist das langsamer als zehn Agenten gleichzeitig losrennen zu lassen. Aber es ist schneller als zehn Agenten gleichzeitig losrennen zu lassen und danach einen Nachmittag damit zu verbringen, aus fünf halb überlappenden PRs wieder eine lineare Geschichte zu basteln.

Automerge, aber nicht lebensmüde

Der zweite Teil ist Automerge. Auch hier gilt: Man kann das vernünftig machen oder man kann sich später wundern.

Meine Mindestregeln wären:

  • nur Copilot-PRs oder explizit markierte PRs,
  • keine Drafts,
  • alle Pflichtchecks grün,
  • keine blockierten Issues,
  • riskante Bereiche brauchen weiter menschliches Review.

Damit ist Automerge nicht “Augen zu und durch”, sondern eher: Wenn alles, was wir vorher als wichtig definiert haben, grün ist, dann bitte nicht noch drei Tage auf einen Klick warten.

Und genau hier schließt sich der Kreis: Wenn ein PR sauber merged, kann der nächste Lauf starten. Nicht, weil irgendein Mensch gerade zufällig vor GitHub sitzt, sondern weil das Projekt selbst weiß: Dieses Stück ist erledigt, jetzt kommt das nächste.

Roadmap schneiden

Der Teil, der gerne unterschätzt wird: Man muss die Roadmap vorher ehrlich machen.

“Wir bauen eine großartige Plattform” ist keine Roadmap. “Wir bauen zuerst Import/Export, dann persistente Sessions, dann ein Rechtekonzept, dann Auswertungen” ist schon besser. “Issue 12 baut den Storage-Adapter, Issue 13 hängt Quiz-Inhalte daran, Issue 14 exportiert Ergebnisse als CSV und JSON” ist agententauglich.

Das ist übrigens auch der Moment, an dem ChatGPT wieder sehr nützlich ist. Nicht als Orakel, sondern als Roadmap-Zerlegehilfe. Man kann sagen: Hier ist das Projekt, hier sind die Ziele, mach daraus bitte Arbeitspakete, die ein Agent in einem überschaubaren Pull Request erledigen kann. Danach muss man trotzdem noch drüberschauen. Aber das ist eine andere Art Arbeit als stumpfes Ticket-Schubsen.

Man merkt dabei auch sehr schnell, welche Dinge noch nicht reif sind. Und das ist gut. Dann kommt blocked drauf. Nicht als Schande, sondern als kleines gelbes Warnschild: Hier bitte erst denken, dann Agent.

Fazit

Am Ende ist das Ganze weniger Science-Fiction, als es klingt. Es ist ein Issue-Stapel mit Anstand, ein kleines Script, ein paar Labels und die Bereitschaft, Arbeit so zu beschreiben, dass nicht nur ein Mensch mit viel Kontext sie versteht.

Für jemanden wie mich ist das ziemlich nah an idealer Faulheit: Ich muss immer noch denken, aber ich muss nicht mehr jeden Kleinkram selbst heruntertippen. Ich muss immer noch kontrollieren, aber ich muss nicht mehr jedes Ticket einzeln anschieben. Ich muss immer noch wissen, was ich will, aber ich darf den langweiligen Teil häufiger an Maschinen delegieren.

Und wenn Copilot dann einen PR baut, der merged, woraufhin der Workflow das nächste Issue aktiviert, woraufhin Copilot wieder losläuft, dann ist das natürlich kein echtes Perpetuum mobile.

Aber es fühlt sich kurz so an.

Und für einen faulen Informatiker ist das schon ziemlich nah dran.

Comments

Leave a Reply